init
This commit is contained in:
297
src/common/error.cpp
Normal file
297
src/common/error.cpp
Normal 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
|
||||
Reference in New Issue
Block a user