This commit is contained in:
2025-10-24 18:17:58 +08:00
commit c98e7e61b3
48 changed files with 10175 additions and 0 deletions

297
src/common/error.cpp Normal file
View File

@@ -0,0 +1,297 @@
// ================================================================================================
// Audio Backend - 错误处理和异常类实现
// ================================================================================================
#include "error.h"
#include <algorithm>
#include <unordered_map>
#if ALICHO_PLATFORM_WINDOWS
#include <windows.h>
#elif ALICHO_PLATFORM_UNIX
#include <errno.h>
#endif
namespace audio_backend::common {
// ================================================================================================
// 错误码描述映射
// ================================================================================================
static const std::unordered_map<ErrorCode, std::string> error_descriptions = {
// 通用错误
{ErrorCode::SUCCESS, "操作成功"},
{ErrorCode::UNKNOWN_ERROR, "未知错误"},
{ErrorCode::INVALID_ARGUMENT, "无效参数"},
{ErrorCode::INVALID_OPERATION, "无效操作"},
{ErrorCode::NOT_IMPLEMENTED, "功能未实现"},
{ErrorCode::OUT_OF_MEMORY, "内存不足"},
{ErrorCode::OPERATION_TIMED_OUT, "操作超时"},
{ErrorCode::NOT_INITIALIZED, "未初始化"},
{ErrorCode::ALREADY_INITIALIZED, "已经初始化"},
// 文件和I/O错误
{ErrorCode::FILE_NOT_FOUND, "文件未找到"},
{ErrorCode::FILE_ACCESS_DENIED, "文件访问被拒绝"},
{ErrorCode::FILE_READ_ERROR, "文件读取错误"},
{ErrorCode::FILE_WRITE_ERROR, "文件写入错误"},
{ErrorCode::FILE_FORMAT_ERROR, "文件格式错误"},
// 音频处理错误
{ErrorCode::AUDIO_FORMAT_ERROR, "音频格式错误"},
{ErrorCode::AUDIO_DEVICE_ERROR, "音频设备错误"},
{ErrorCode::AUDIO_BUFFER_UNDERRUN, "音频缓冲区欠载"},
{ErrorCode::AUDIO_BUFFER_OVERRUN, "音频缓冲区溢出"},
{ErrorCode::AUDIO_SAMPLE_RATE_MISMATCH, "采样率不匹配"},
{ErrorCode::AUDIO_CHANNEL_COUNT_MISMATCH, "声道数不匹配"},
// 插件错误
{ErrorCode::PLUGIN_LOAD_ERROR, "插件加载错误"},
{ErrorCode::PLUGIN_NOT_FOUND, "插件未找到"},
{ErrorCode::PLUGIN_VERSION_MISMATCH, "插件版本不匹配"},
{ErrorCode::PLUGIN_INITIALIZATION_ERROR, "插件初始化错误"},
{ErrorCode::PLUGIN_COMMUNICATION_ERROR, "插件通信错误"},
{ErrorCode::PLUGIN_EXECUTION_ERROR, "插件执行错误"},
{ErrorCode::PLUGIN_TIMEOUT, "插件超时"},
// 通信错误
{ErrorCode::COMMUNICATION_ERROR, "通信错误"},
{ErrorCode::CONNECTION_ERROR, "连接错误"},
{ErrorCode::DISCONNECTED, "连接已断开"},
{ErrorCode::MESSAGE_FORMAT_ERROR, "消息格式错误"},
{ErrorCode::PROTOCOL_ERROR, "协议错误"},
{ErrorCode::TIMEOUT, "超时"},
// 系统错误
{ErrorCode::SYSTEM_ERROR, "系统错误"},
{ErrorCode::PERMISSION_DENIED, "权限被拒绝"},
{ErrorCode::NOT_ENOUGH_RESOURCES, "资源不足"}
};
// ================================================================================================
// 错误分类映射
// ================================================================================================
static const std::unordered_map<ErrorCode, ErrorCategory> error_categories = {
// 通用错误
{ErrorCode::SUCCESS, ErrorCategory::GENERAL},
{ErrorCode::UNKNOWN_ERROR, ErrorCategory::GENERAL},
{ErrorCode::INVALID_ARGUMENT, ErrorCategory::GENERAL},
{ErrorCode::INVALID_OPERATION, ErrorCategory::GENERAL},
{ErrorCode::NOT_IMPLEMENTED, ErrorCategory::GENERAL},
{ErrorCode::OUT_OF_MEMORY, ErrorCategory::GENERAL},
{ErrorCode::OPERATION_TIMED_OUT, ErrorCategory::GENERAL},
{ErrorCode::NOT_INITIALIZED, ErrorCategory::GENERAL},
{ErrorCode::ALREADY_INITIALIZED, ErrorCategory::GENERAL},
// 文件错误
{ErrorCode::FILE_NOT_FOUND, ErrorCategory::FILE},
{ErrorCode::FILE_ACCESS_DENIED, ErrorCategory::FILE},
{ErrorCode::FILE_READ_ERROR, ErrorCategory::FILE},
{ErrorCode::FILE_WRITE_ERROR, ErrorCategory::FILE},
{ErrorCode::FILE_FORMAT_ERROR, ErrorCategory::FILE},
// 音频错误
{ErrorCode::AUDIO_FORMAT_ERROR, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_DEVICE_ERROR, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_BUFFER_UNDERRUN, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_BUFFER_OVERRUN, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_SAMPLE_RATE_MISMATCH, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_CHANNEL_COUNT_MISMATCH, ErrorCategory::AUDIO},
// 插件错误
{ErrorCode::PLUGIN_LOAD_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_NOT_FOUND, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_VERSION_MISMATCH, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_INITIALIZATION_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_COMMUNICATION_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_EXECUTION_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_TIMEOUT, ErrorCategory::PLUGIN},
// 通信错误
{ErrorCode::COMMUNICATION_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::CONNECTION_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::DISCONNECTED, ErrorCategory::COMMUNICATION},
{ErrorCode::MESSAGE_FORMAT_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::PROTOCOL_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::TIMEOUT, ErrorCategory::COMMUNICATION},
// 系统错误
{ErrorCode::SYSTEM_ERROR, ErrorCategory::SYSTEM},
{ErrorCode::PERMISSION_DENIED, ErrorCategory::SYSTEM},
{ErrorCode::NOT_ENOUGH_RESOURCES, ErrorCategory::SYSTEM}
};
// ================================================================================================
// 公共函数实现
// ================================================================================================
ErrorCategory get_error_category(ErrorCode code) {
auto it = error_categories.find(code);
if (it != error_categories.end()) {
return it->second;
}
return ErrorCategory::GENERAL;
}
std::string get_error_description(ErrorCode code) {
auto it = error_descriptions.find(code);
if (it != error_descriptions.end()) {
return it->second;
}
return "未知错误代码: " + std::to_string(static_cast<int>(code));
}
std::exception_ptr create_exception(ErrorCode code,
const std::string& message,
const std::string& details) {
ErrorCategory category = get_error_category(code);
try {
switch (category) {
case ErrorCategory::FILE:
throw FileException(code, message, details);
case ErrorCategory::AUDIO:
throw AudioException(code, message, details);
case ErrorCategory::PLUGIN:
throw PluginException(code, message, details);
case ErrorCategory::COMMUNICATION:
throw CommunicationException(code, message, details);
case ErrorCategory::SYSTEM:
throw SystemException(code, message, details);
default:
throw AudioBackendException(code, message, details);
}
} catch (...) {
return std::current_exception();
}
}
void throw_exception(ErrorCode code,
const std::string& message,
const std::string& details) {
std::rethrow_exception(create_exception(code, message, details));
}
void check_error(bool condition,
ErrorCode error_code,
const std::string& message,
const std::string& details) {
if (condition) {
throw_exception(error_code, message, details);
}
}
ErrorCode system_error_to_error_code(int system_error) {
#if ALICHO_PLATFORM_WINDOWS
switch (system_error) {
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
return ErrorCode::FILE_NOT_FOUND;
case ERROR_ACCESS_DENIED:
return ErrorCode::FILE_ACCESS_DENIED;
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_OUTOFMEMORY:
return ErrorCode::OUT_OF_MEMORY;
case ERROR_TIMEOUT:
return ErrorCode::OPERATION_TIMED_OUT;
case ERROR_INVALID_PARAMETER:
return ErrorCode::INVALID_ARGUMENT;
default:
return ErrorCode::SYSTEM_ERROR;
}
#elif ALICHO_PLATFORM_UNIX
switch (system_error) {
case ENOENT:
return ErrorCode::FILE_NOT_FOUND;
case EACCES:
case EPERM:
return ErrorCode::FILE_ACCESS_DENIED;
case ENOMEM:
return ErrorCode::OUT_OF_MEMORY;
case ETIMEDOUT:
return ErrorCode::OPERATION_TIMED_OUT;
case EINVAL:
return ErrorCode::INVALID_ARGUMENT;
default:
return ErrorCode::SYSTEM_ERROR;
}
#else
return ErrorCode::SYSTEM_ERROR;
#endif
}
ErrorCode std_error_to_error_code(const std::error_code& ec) {
if (ec.category() == std::generic_category()) {
return system_error_to_error_code(ec.value());
} else if (ec.category() == AudioBackendErrorCategory::instance()) {
return static_cast<ErrorCode>(ec.value());
} else {
return ErrorCode::SYSTEM_ERROR;
}
}
// ================================================================================================
// ErrorHandler实现
// ================================================================================================
void ErrorHandler::add_error_handler(const ErrorCallback& handler) {
handlers_.push_back(handler);
}
void ErrorHandler::remove_error_handler(const ErrorCallback& handler) {
// 注意这个比较可能不会按预期工作因为std::function的比较很复杂
// 在实际使用中可能需要使用其他方式来管理处理器比如返回ID
auto it = std::find_if(handlers_.begin(), handlers_.end(),
[&handler](const ErrorCallback& h) {
// 这里的比较不太可靠,应该考虑使用其他方式
return &h == &handler;
});
if (it != handlers_.end()) {
handlers_.erase(it);
}
}
void ErrorHandler::handle_error(const AudioBackendException& exception) {
for (const auto& handler : handlers_) {
try {
handler(exception);
} catch (...) {
// 忽略错误处理器中的异常,防止无限递归
}
}
}
void ErrorHandler::handle_error(ErrorCode code,
const std::string& message,
const std::string& details) {
try {
AudioBackendException exception(code, message, details);
handle_error(exception);
} catch (...) {
// 忽略创建异常时的错误
}
}
void ErrorHandler::handle_exception(std::exception_ptr eptr) {
if (!eptr) return;
try {
std::rethrow_exception(eptr);
} catch (const AudioBackendException& e) {
handle_error(e);
} catch (const std::exception& e) {
// 对于其他标准异常创建一个通用的AudioBackendException
AudioBackendException wrapper(ErrorCode::UNKNOWN_ERROR, e.what());
handle_error(wrapper);
} catch (...) {
// 对于其他异常,创建一个未知错误
AudioBackendException wrapper(ErrorCode::UNKNOWN_ERROR, "未知异常类型");
handle_error(wrapper);
}
}
void ErrorHandler::clear_handlers() {
handlers_.clear();
}
} // namespace audio_backend::common