-
Notifications
You must be signed in to change notification settings - Fork 0
Master #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Walkthrough这次更新主要涉及在多个子目录中添加新的C++源文件和CMakeLists.txt文件。新增的功能包括音频处理、文件读取和分析、学生成绩管理、二分搜索、银行账户管理、购物车管理、图书馆系统、线程管理、epoll事件处理、配置文件读取、以及非线性数据转换等。还对.gitignore文件进行了更新,排除了.idea目录。 Changes
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
|
@coderabbitai review |
Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (20)
- .gitignore (1 hunks)
- c++/misc/CMakeLists.txt (1 hunks)
- c++/misc/ChenPengYuan/CMakeLists.txt (1 hunks)
- c++/misc/ChenPengYuan/cpy_0_001.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_001.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_002.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_003.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_004.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_005.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_006.cpp (1 hunks)
- c++/misc/KangDengli/CMakeLists.txt (1 hunks)
- c++/misc/KangDengli/KangDengli01.cpp (1 hunks)
- c++/misc/XuShaoQiu/CMakeLists.txt (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu001.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu002.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu003.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu004.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu005.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu006.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu007.cpp (1 hunks)
Files skipped from review due to trivial changes (8)
- .gitignore
- c++/misc/CMakeLists.txt
- c++/misc/ChenPengYuan/CMakeLists.txt
- c++/misc/ChenPengYuan/cpy_1_001.cpp
- c++/misc/ChenPengYuan/cpy_1_003.cpp
- c++/misc/ChenPengYuan/cpy_1_005.cpp
- c++/misc/KangDengli/CMakeLists.txt
- c++/misc/XuShaoQiu/CMakeLists.txt
Additional comments not posted (29)
c++/misc/XuShaoQiu/XuShaoQiu001.cpp (2)
4-9: 打印列表函数实现正确,无需修改。
31-34: 主函数实现正确,调用了listOpt函数并返回0。c++/misc/XuShaoQiu/XuShaoQiu005.cpp (2)
9-24: 显示配置文件内容的函数实现正确,但建议注意getConfigPath().c_str()可能存在的内存问题。
26-29: 主函数实现正确,调用了showConfigContent函数并返回0。c++/misc/XuShaoQiu/XuShaoQiu003.cpp (1)
33-37: 主函数实现正确,正确地创建并等待线程结束。c++/misc/XuShaoQiu/XuShaoQiu007.cpp (1)
5-42: 显示配置文件内容的函数实现正确,正确处理了多行配置和空白字符。但该函数较为复杂,建议在文档中详细说明其行为。c++/misc/ChenPengYuan/cpy_0_001.cpp (3)
3-9: 音频回调构造函数实现正确,正确地初始化了音频参数和缓冲区。但建议检查malloc的返回值以处理内存分配失败的情况。
11-13: 音频回调析构函数实现正确,正确地释放了分配的内存。
15-34: 处理音频数据的函数实现正确,正确地使用互斥锁确保线程安全,并妥善处理了数据移动。建议添加错误处理逻辑以应对潜在的问题。c++/misc/ChenPengYuan/cpy_1_002.cpp (2)
4-15: 学生类实现正确,提供了获取学生姓名和成绩的方法。
17-46: 教室类实现正确,提供了添加学生、计算平均分和查找最高分学生的方法。建议添加对除以零的错误处理。c++/misc/ChenPengYuan/cpy_1_006.cpp (3)
4-17: 代码实现了书籍的基本属性和获取方法,逻辑清晰,没有发现问题。
19-46: 图书馆类实现了添加书籍、按标题查找书籍和按作者统计书籍数量的功能,使用了标准C++库,代码结构合理。
48-63: 主函数中演示了图书馆类和书籍类的使用,包括添加书籍、查找书籍和统计作者的书籍数量,输出语句正确地展示了这些操作的结果。c++/misc/ChenPengYuan/cpy_1_004.cpp (3)
6-38: 银行账户类实现了存款、取款和获取余额的功能,对存取款的金额进行了有效性检查,逻辑正确。
40-64: 银行类管理一系列的银行账户,提供了开户、销户和计算总存款的功能,使用了现代C++特性如emplace_back,提高了效率。
66-84: 主函数中演示了银行类和银行账户类的使用,包括开户、进行交易和销户,输出语句正确地展示了这些操作的结果。c++/misc/KangDengli/KangDengli01.cpp (3)
10-41: 线程类提供了线程管理的框架,包括启动、停止、暂停和恢复线程的方法,使用了现代C++的并发特性。
106-115:MyThread类是Thread的简单扩展,重写了threadLoop方法以执行特定任务,实现简单且正确。
117-127: 主函数中演示了MyThread类的使用,包括启动线程、暂停、恢复和停止,输出语句正确地展示了这些操作的结果。c++/misc/XuShaoQiu/XuShaoQiu006.cpp (4)
3-9:NLAData结构简单且正确地定义了非线性转换点的字段。
13-36:mw2SdkNonLinear函数根据输入使用定义的转换点计算非线性输出,实现正确,使用了适当的数学运算。
38-77:sdk2MwNonLinear函数执行mw2SdkNonLinear转换的逆变换。它正确处理斜率可能为零的情况,以避免除零错误。
79-100: 主函数演示了mw2SdkNonLinear和sdk2MwNonLinear函数的使用。它执行转换并检查是否可以检索原始值,这对于验证转换的正确性至关重要。c++/misc/XuShaoQiu/XuShaoQiu002.cpp (2)
12-89:EPoll类管理epoll事件,提供了插入文件描述符和运行事件循环的方法。实现处理了错误,并使用了现代C++特性,如std::thread和std::atomic。
91-127: 主函数演示了EPoll类用于处理UDP套接字事件的使用。它正确地设置了套接字,进行了绑定,并使用EPoll实例来管理传入数据。c++/misc/XuShaoQiu/XuShaoQiu004.cpp (3)
10-13:EventListener类是事件监听器的接口,正确地定义了纯虚函数onEvent。
15-92:EventHub类管理事件监听器和事件。它提供了添加、删除和清除监听器的方法,以及同步和异步发布事件的方法。实现有效地使用了现代C++的并发特性。
129-146: 主函数演示了EventHub和EventListener类用于事件处理的使用。它设置了监听器,发布了事件,并清理了资源。实现正确,有效地演示了功能。
| for (auto iter = list.begin(); iter != list.end(); iter++) { | ||
| if (*iter == 2) { | ||
| list.erase(iter); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
在循环中删除列表元素可能会导致迭代器失效。建议使用std::remove_if来安全地移除元素。
- for (auto iter = list.begin(); iter != list.end(); iter++) {
- if (*iter == 2) {
- list.erase(iter);
- }
- }
+ list.remove_if([](int value) { return value == 2; });Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| for (auto iter = list.begin(); iter != list.end(); iter++) { | |
| if (*iter == 2) { | |
| list.erase(iter); | |
| } | |
| } | |
| list.remove_if([](int value) { return value == 2; }); |
| char filePath[256] = {0}; | ||
| sprintf(filePath, "/home/qiushao/config.ini"); | ||
| thread = std::thread(theadLoop, filePath); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
创建线程的函数中,filePath作为局部变量可能会在线程函数访问时已经被销毁。建议将其声明为静态变量。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 14
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (20)
- .gitignore (1 hunks)
- c++/misc/CMakeLists.txt (1 hunks)
- c++/misc/ChenPengYuan/CMakeLists.txt (1 hunks)
- c++/misc/ChenPengYuan/cpy_0_001.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_001.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_002.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_003.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_004.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_005.cpp (1 hunks)
- c++/misc/ChenPengYuan/cpy_1_006.cpp (1 hunks)
- c++/misc/KangDengli/CMakeLists.txt (1 hunks)
- c++/misc/KangDengli/KangDengli01.cpp (1 hunks)
- c++/misc/XuShaoQiu/CMakeLists.txt (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu001.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu002.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu003.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu004.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu005.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu006.cpp (1 hunks)
- c++/misc/XuShaoQiu/XuShaoQiu007.cpp (1 hunks)
Files skipped from review due to trivial changes (8)
- .gitignore
- c++/misc/CMakeLists.txt
- c++/misc/ChenPengYuan/CMakeLists.txt
- c++/misc/ChenPengYuan/cpy_1_001.cpp
- c++/misc/ChenPengYuan/cpy_1_002.cpp
- c++/misc/ChenPengYuan/cpy_1_003.cpp
- c++/misc/KangDengli/CMakeLists.txt
- c++/misc/XuShaoQiu/CMakeLists.txt
Additional comments not posted (15)
c++/misc/XuShaoQiu/XuShaoQiu001.cpp (2)
4-9: 打印列表功能实现正确,使用了C风格的输入输出,与包含的头文件一致。
31-34: 主函数实现简单明了,正确调用了listOpt函数。c++/misc/XuShaoQiu/XuShaoQiu005.cpp (3)
5-7: 获取配置文件路径的函数实现正确,但路径硬编码,建议增加灵活性。
9-24: 显示配置文件内容的函数正确处理了文件打开错误,并使用了C风格的输入输出。
26-29: 主函数实现简单明了,正确调用了showConfigContent函数。c++/misc/XuShaoQiu/XuShaoQiu003.cpp (1)
33-37: 主函数实现简单明了,正确创建了线程并等待其完成。c++/misc/ChenPengYuan/cpy_0_001.cpp (1)
11-13: 音频处理类的析构函数正确地释放了分配的内存。c++/misc/ChenPengYuan/cpy_1_005.cpp (3)
4-14: 商品类提供了获取商品名称和价格的方法,实现正确。
17-45: 购物车类正确实现了添加商品、计算总价和查找最贵商品的方法。
47-58: 主函数正确创建了购物车,添加了商品,并显示了总成本和最贵的商品。c++/misc/ChenPengYuan/cpy_1_006.cpp (1)
4-17: 代码实现了一个简单的书籍信息封装,没有发现问题。c++/misc/ChenPengYuan/cpy_1_004.cpp (1)
6-37: 银行账户类实现了存款和取款功能,包含基本的验证,没有发现问题。c++/misc/KangDengli/KangDengli01.cpp (1)
106-115: 自定义线程类正确地重写了threadLoop方法,没有发现问题。c++/misc/XuShaoQiu/XuShaoQiu006.cpp (1)
3-9: 非线性转换数据点的结构定义简单明了,没有发现问题。c++/misc/XuShaoQiu/XuShaoQiu004.cpp (1)
10-13: 事件监听器接口定义了虚拟方法onEvent用于事件处理,没有发现问题。
| class Library { | ||
| public: | ||
| void AddBook(const Book& book) { | ||
| books_.push_back(book); | ||
| } | ||
|
|
||
| Book* FindBookByTitle(const std::string& title) { | ||
| for (auto& book : books_) { | ||
| if (book.GetTitle() == title) { | ||
| return &book; | ||
| } | ||
| } | ||
| return nullptr; | ||
| } | ||
|
|
||
| size_t CountBooksByAuthor(const std::string& author) { | ||
| size_t count = 0; | ||
| for (auto& book : books_) { | ||
| if (book.GetAuthor() == author) { | ||
| ++count; | ||
| } | ||
| } | ||
| return count; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
建议将 FindBookByTitle 方法返回的指针设置为常量,以防止外部修改书籍对象。
- Book* FindBookByTitle(const std::string& title) {
+ const Book* FindBookByTitle(const std::string& title) const {Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| class Library { | |
| public: | |
| void AddBook(const Book& book) { | |
| books_.push_back(book); | |
| } | |
| Book* FindBookByTitle(const std::string& title) { | |
| for (auto& book : books_) { | |
| if (book.GetTitle() == title) { | |
| return &book; | |
| } | |
| } | |
| return nullptr; | |
| } | |
| size_t CountBooksByAuthor(const std::string& author) { | |
| size_t count = 0; | |
| for (auto& book : books_) { | |
| if (book.GetAuthor() == author) { | |
| ++count; | |
| } | |
| } | |
| return count; | |
| } | |
| class Library { | |
| public: | |
| void AddBook(const Book& book) { | |
| books_.push_back(book); | |
| } | |
| const Book* FindBookByTitle(const std::string& title) const { | |
| for (auto& book : books_) { | |
| if (book.GetTitle() == title) { | |
| return &book; | |
| } | |
| } | |
| return nullptr; | |
| } | |
| size_t CountBooksByAuthor(const std::string& author) { | |
| size_t count = 0; | |
| for (auto& book : books_) { | |
| if (book.GetAuthor() == author) { | |
| ++count; | |
| } | |
| } | |
| return count; | |
| } |
| class Bank { | ||
| public: | ||
| BankAccount* OpenAccount(std::string owner, double initial_balance) { | ||
| accounts_.emplace_back(owner, initial_balance); | ||
| return &accounts_.back(); | ||
| } | ||
|
|
||
| bool CloseAccount(BankAccount* account) { | ||
| for (auto it = accounts_.begin(); it != accounts_.end(); ++it) { | ||
| if (&(*it) == account) { | ||
| accounts_.erase(it); | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| double GetTotalDeposits() const { | ||
| return std::accumulate(accounts_.begin(), accounts_.end(), 0.0, | ||
| [](double sum, const BankAccount& account) { return sum + account.GetBalance(); }); | ||
| } | ||
|
|
||
| private: | ||
| std::vector<BankAccount> accounts_; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
对于大量账户的情况,当前的关闭账户方法效率较低。建议使用更高效的数据结构,如 std::map,来管理账户。
- std::vector<BankAccount> accounts_;
+ std::map<std::string, BankAccount> accounts_;Committable suggestion was skipped due low confidence.
| class Thread { | ||
| public: | ||
| explicit Thread(std::string threadName); | ||
| virtual ~Thread() = default; | ||
|
|
||
| virtual void start(); | ||
|
|
||
| virtual void stop(); | ||
|
|
||
| virtual void pause(); | ||
|
|
||
| virtual void resume(); | ||
|
|
||
| protected: | ||
| virtual bool threadLoop() = 0; | ||
| virtual bool prepare(); | ||
| virtual void destroy(); | ||
|
|
||
| private: | ||
| void interrupt(bool); | ||
|
|
||
| void run(); | ||
|
|
||
| protected: | ||
| std::thread thread_; | ||
| std::atomic<bool> interrupted_; | ||
| std::atomic<bool> started_; | ||
| std::atomic<bool> paused_; | ||
| std::condition_variable cond_; | ||
| std::mutex mutex_; | ||
| std::string threadName_; | ||
| }; | ||
|
|
||
| Thread::Thread(std::string threadName) : | ||
| interrupted_(false), | ||
| started_(false), | ||
| paused_(false), | ||
| threadName_(std::move(threadName)) { | ||
| } | ||
|
|
||
| void Thread::start() { | ||
| interrupt(false); | ||
| thread_ = std::thread(&Thread::run, this); | ||
| started_ = true; | ||
| } | ||
|
|
||
| void Thread::stop() { | ||
| if (!started_) { | ||
| return; | ||
| } | ||
| if (paused_) { | ||
| resume(); | ||
| } | ||
| interrupt(true); | ||
| destroy(); | ||
| } | ||
|
|
||
| void Thread::pause() { | ||
| paused_ = true; | ||
| } | ||
|
|
||
| void Thread::resume() { | ||
| paused_ = false; | ||
| cond_.notify_one(); | ||
| } | ||
|
|
||
| void Thread::destroy() { | ||
| if(!started_) { | ||
| return; | ||
| } | ||
| started_ = false; | ||
| if (thread_.joinable()) { | ||
| thread_.join(); | ||
| } | ||
| } | ||
|
|
||
| void Thread::interrupt(bool flag) { | ||
| interrupted_ = flag; | ||
| } | ||
|
|
||
| void Thread::run() { | ||
| do { | ||
| if (paused_) { | ||
| std::unique_lock<std::mutex> lock(mutex_); | ||
| cond_.wait(lock, [&] { | ||
| return !paused_; | ||
| }); | ||
| } | ||
|
|
||
| if (!threadLoop()) { | ||
| started_ = false; | ||
| break; | ||
| } | ||
| } while (!interrupted_); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
线程管理类提供了全面的功能。建议将 interrupt 方法重命名为 setInterrupted,以提高代码的可读性。
- void interrupt(bool);
+ void setInterrupted(bool);Committable suggestion was skipped due low confidence.
| void listOpt() { | ||
| std::list<int> list; | ||
| list.push_back(1); | ||
| list.push_back(2); | ||
| list.push_back(2); | ||
| list.push_back(3); | ||
| list.push_back(4); | ||
| list.push_back(2); | ||
|
|
||
| printList(list); | ||
|
|
||
| for (auto iter = list.begin(); iter != list.end(); iter++) { | ||
| if (*iter == 2) { | ||
| list.erase(iter); | ||
| } | ||
| } | ||
|
|
||
| printList(list); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
在循环中删除列表元素时未正确管理迭代器,可能导致未定义行为。
- for (auto iter = list.begin(); iter != list.end(); iter++) {
- if (*iter == 2) {
- list.erase(iter);
- }
- }
+ for (auto iter = list.begin(); iter != list.end(); ) {
+ if (*iter == 2) {
+ iter = list.erase(iter);
+ } else {
+ ++iter;
+ }
+ }Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| void listOpt() { | |
| std::list<int> list; | |
| list.push_back(1); | |
| list.push_back(2); | |
| list.push_back(2); | |
| list.push_back(3); | |
| list.push_back(4); | |
| list.push_back(2); | |
| printList(list); | |
| for (auto iter = list.begin(); iter != list.end(); iter++) { | |
| if (*iter == 2) { | |
| list.erase(iter); | |
| } | |
| } | |
| printList(list); | |
| void listOpt() { | |
| std::list<int> list; | |
| list.push_back(1); | |
| list.push_back(2); | |
| list.push_back(2); | |
| list.push_back(3); | |
| list.push_back(4); | |
| list.push_back(2); | |
| printList(list); | |
| for (auto iter = list.begin(); iter != list.end(); ) { | |
| if (*iter == 2) { | |
| iter = list.erase(iter); | |
| } else { | |
| ++iter; | |
| } | |
| } | |
| printList(list); |
| void sdk2MwNonLinear(uint32_t input, uint32_t *output) { | ||
| double slopValue; | ||
| uint32_t diffValue; | ||
| uint32_t baseValue; | ||
| if (nlaData.u32Point75 < input) { | ||
| if (nlaData.u32Point100 != nlaData.u32Point75) { | ||
| slopValue = 25.0 / (int32_t) (nlaData.u32Point100 - nlaData.u32Point75); | ||
| } else { | ||
| slopValue = 0; | ||
| } | ||
| diffValue = input - nlaData.u32Point75; | ||
| baseValue = 75; | ||
| } else if (nlaData.u32Point50 < input) { | ||
| if (nlaData.u32Point75 != nlaData.u32Point50) { | ||
| slopValue = 25.0 / (int32_t) (nlaData.u32Point75 - nlaData.u32Point50); | ||
| } else { | ||
| slopValue = 0; | ||
| } | ||
| diffValue = input - nlaData.u32Point50; | ||
| baseValue = 50; | ||
| } else if (nlaData.u32Point25 < input) { | ||
| if (nlaData.u32Point50 != nlaData.u32Point25) { | ||
| slopValue = 25.0 / (int32_t) (nlaData.u32Point50 - nlaData.u32Point25); | ||
| } else { | ||
| slopValue = 0; | ||
| } | ||
| diffValue = input - nlaData.u32Point25; | ||
| baseValue = 25; | ||
| } else { | ||
| if (nlaData.u32Point25 != nlaData.u32Point0) { | ||
| slopValue = 25.0 / (int32_t) (nlaData.u32Point25 - nlaData.u32Point0); | ||
| } else { | ||
| slopValue = 0; | ||
| } | ||
| diffValue = input - nlaData.u32Point0; | ||
| baseValue = 0; | ||
| } | ||
|
|
||
| *output = baseValue + (int32_t) (slopValue * diffValue); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
函数执行反向分段线性转换。同样存在不必要的强制类型转换问题。
- slopValue = 25.0 / (int32_t) (nlaData.u32Point100 - nlaData.u32Point75);
+ slopValue = 25.0 / (nlaData.u32Point100 - nlaData.u32Point75);Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| void sdk2MwNonLinear(uint32_t input, uint32_t *output) { | |
| double slopValue; | |
| uint32_t diffValue; | |
| uint32_t baseValue; | |
| if (nlaData.u32Point75 < input) { | |
| if (nlaData.u32Point100 != nlaData.u32Point75) { | |
| slopValue = 25.0 / (int32_t) (nlaData.u32Point100 - nlaData.u32Point75); | |
| } else { | |
| slopValue = 0; | |
| } | |
| diffValue = input - nlaData.u32Point75; | |
| baseValue = 75; | |
| } else if (nlaData.u32Point50 < input) { | |
| if (nlaData.u32Point75 != nlaData.u32Point50) { | |
| slopValue = 25.0 / (int32_t) (nlaData.u32Point75 - nlaData.u32Point50); | |
| } else { | |
| slopValue = 0; | |
| } | |
| diffValue = input - nlaData.u32Point50; | |
| baseValue = 50; | |
| } else if (nlaData.u32Point25 < input) { | |
| if (nlaData.u32Point50 != nlaData.u32Point25) { | |
| slopValue = 25.0 / (int32_t) (nlaData.u32Point50 - nlaData.u32Point25); | |
| } else { | |
| slopValue = 0; | |
| } | |
| diffValue = input - nlaData.u32Point25; | |
| baseValue = 25; | |
| } else { | |
| if (nlaData.u32Point25 != nlaData.u32Point0) { | |
| slopValue = 25.0 / (int32_t) (nlaData.u32Point25 - nlaData.u32Point0); | |
| } else { | |
| slopValue = 0; | |
| } | |
| diffValue = input - nlaData.u32Point0; | |
| baseValue = 0; | |
| } | |
| *output = baseValue + (int32_t) (slopValue * diffValue); | |
| } | |
| void sdk2MwNonLinear(uint32_t input, uint32_t *output) { | |
| double slopValue; | |
| uint32_t diffValue; | |
| uint32_t baseValue; | |
| if (nlaData.u32Point75 < input) { | |
| if (nlaData.u32Point100 != nlaData.u32Point75) { | |
| slopValue = 25.0 / (nlaData.u32Point100 - nlaData.u32Point75); | |
| } else { | |
| slopValue = 0; | |
| } | |
| diffValue = input - nlaData.u32Point75; | |
| baseValue = 75; | |
| } else if (nlaData.u32Point50 < input) { | |
| if (nlaData.u32Point75 != nlaData.u32Point50) { | |
| slopValue = 25.0 / (nlaData.u32Point75 - nlaData.u32Point50); | |
| } else { | |
| slopValue = 0; | |
| } | |
| diffValue = input - nlaData.u32Point50; | |
| baseValue = 50; | |
| } else if (nlaData.u32Point25 < input) { | |
| if (nlaData.u32Point50 != nlaData.u32Point25) { | |
| slopValue = 25.0 / (nlaData.u32Point50 - nlaData.u32Point25); | |
| } else { | |
| slopValue = 0; | |
| } | |
| diffValue = input - nlaData.u32Point25; | |
| baseValue = 25; | |
| } else { | |
| if (nlaData.u32Point25 != nlaData.u32Point0) { | |
| slopValue = 25.0 / (nlaData.u32Point25 - nlaData.u32Point0); | |
| } else { | |
| slopValue = 0; | |
| } | |
| diffValue = input - nlaData.u32Point0; | |
| baseValue = 0; | |
| } | |
| *output = baseValue + (int32_t) (slopValue * diffValue); | |
| } |
| void showConfigContent() { | ||
| constexpr int LINE_MAX_LEN = 4096; | ||
| const char *filePath = "/home/qiushao/config.ini"; | ||
| char line[LINE_MAX_LEN] = {0}; | ||
| printf("file path = %s\n", filePath); | ||
| FILE *fp = fopen(filePath, "r"); | ||
| if (fp == nullptr) { | ||
| perror("Error opening file"); | ||
| return; | ||
| } | ||
|
|
||
| size_t last = 0; | ||
| while (fgets(line + last, 256, fp) != nullptr) { | ||
| int len = (int)strlen(line) - 1; // 去掉字符串结束符 '\0' | ||
|
|
||
| while ((len>=0) && ((line[len]=='\n') || (isspace(line[len])))) { | ||
| // 去除行尾空白字符(空格,TAB, 换行), trim | ||
| line[len]=0 ; | ||
| len-- ; | ||
| } | ||
|
|
||
| if (len < 0) { | ||
| // 空行 | ||
| continue; | ||
| } | ||
|
|
||
| if (line[len] == '\\') { | ||
| // 多行配置 | ||
| last = len; | ||
| continue; | ||
| } | ||
| printf("%s\n", line); | ||
| last = 0; | ||
| memset(line, 0, LINE_MAX_LEN); | ||
| } | ||
|
|
||
| fclose(fp); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
处理配置文件内容的函数正确实现了多行条目的读取。但是,在处理字符串时使用了潜在不安全的方法,建议改进。
- while (fgets(line + last, 256, fp) != nullptr) {
+ while (fgets(line + last, LINE_MAX_LEN - last, fp) != nullptr) {Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| void showConfigContent() { | |
| constexpr int LINE_MAX_LEN = 4096; | |
| const char *filePath = "/home/qiushao/config.ini"; | |
| char line[LINE_MAX_LEN] = {0}; | |
| printf("file path = %s\n", filePath); | |
| FILE *fp = fopen(filePath, "r"); | |
| if (fp == nullptr) { | |
| perror("Error opening file"); | |
| return; | |
| } | |
| size_t last = 0; | |
| while (fgets(line + last, 256, fp) != nullptr) { | |
| int len = (int)strlen(line) - 1; // 去掉字符串结束符 '\0' | |
| while ((len>=0) && ((line[len]=='\n') || (isspace(line[len])))) { | |
| // 去除行尾空白字符(空格,TAB, 换行), trim | |
| line[len]=0 ; | |
| len-- ; | |
| } | |
| if (len < 0) { | |
| // 空行 | |
| continue; | |
| } | |
| if (line[len] == '\\') { | |
| // 多行配置 | |
| last = len; | |
| continue; | |
| } | |
| printf("%s\n", line); | |
| last = 0; | |
| memset(line, 0, LINE_MAX_LEN); | |
| } | |
| fclose(fp); | |
| void showConfigContent() { | |
| constexpr int LINE_MAX_LEN = 4096; | |
| const char *filePath = "/home/qiushao/config.ini"; | |
| char line[LINE_MAX_LEN] = {0}; | |
| printf("file path = %s\n", filePath); | |
| FILE *fp = fopen(filePath, "r"); | |
| if (fp == nullptr) { | |
| perror("Error opening file"); | |
| return; | |
| } | |
| size_t last = 0; | |
| while (fgets(line + last, LINE_MAX_LEN - last, fp) != nullptr) { | |
| int len = (int)strlen(line) - 1; // 去掉字符串结束符 '\0' | |
| while ((len>=0) && ((line[len]=='\n') || (isspace(line[len])))) { | |
| // 去除行尾空白字符(空格,TAB, 换行), trim | |
| line[len]=0 ; | |
| len-- ; | |
| } | |
| if (len < 0) { | |
| // 空行 | |
| continue; | |
| } | |
| if (line[len] == '\\') { | |
| // 多行配置 | |
| last = len; | |
| continue; | |
| } | |
| printf("%s\n", line); | |
| last = 0; | |
| memset(line, 0, LINE_MAX_LEN); | |
| } | |
| fclose(fp); | |
| } |
| MyCallback::MyCallback(AudioParam param) : audioParam_(param) { | ||
| frameDiv_ = sizeof(int16_t) * audioParam_.channelCount; | ||
| //公式:数据率=采样频率(Hz)×量化位数(bit)×声道数(bit/s),在48000 Hz采样率下,如果是16位立体声,数据率将是 1536 kbps。 | ||
| audioDataRate = (audioParam_.sampleRate * audioParam_.AudioFormat * audioParam_.channelCount)/1000; | ||
| bufferSize_ = audioDataRate * 50; | ||
| frameBuffer_ = static_cast<uint8_t *>(malloc(bufferSize_)); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
音频处理类的构造函数正确计算了数据率并分配了缓冲区。建议添加内存分配失败的检查。
- frameBuffer_ = static_cast<uint8_t *>(malloc(bufferSize_));
+ frameBuffer_ = static_cast<uint8_t *>(malloc(bufferSize_));
+ if (!frameBuffer_) {
+ throw std::bad_alloc();
+ }Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| MyCallback::MyCallback(AudioParam param) : audioParam_(param) { | |
| frameDiv_ = sizeof(int16_t) * audioParam_.channelCount; | |
| //公式:数据率=采样频率(Hz)×量化位数(bit)×声道数(bit/s),在48000 Hz采样率下,如果是16位立体声,数据率将是 1536 kbps。 | |
| audioDataRate = (audioParam_.sampleRate * audioParam_.AudioFormat * audioParam_.channelCount)/1000; | |
| bufferSize_ = audioDataRate * 50; | |
| frameBuffer_ = static_cast<uint8_t *>(malloc(bufferSize_)); | |
| } | |
| MyCallback::MyCallback(AudioParam param) : audioParam_(param) { | |
| frameDiv_ = sizeof(int16_t) * audioParam_.channelCount; | |
| //公式:数据率=采样频率(Hz)×量化位数(bit)×声道数(bit/s),在48000 Hz采样率下,如果是16位立体声,数据率将是 1536 kbps。 | |
| audioDataRate = (audioParam_.sampleRate * audioParam_.AudioFormat * audioParam_.channelCount)/1000; | |
| bufferSize_ = audioDataRate * 50; | |
| frameBuffer_ = static_cast<uint8_t *>(malloc(bufferSize_)); | |
| if (!frameBuffer_) { | |
| throw std::bad_alloc(); | |
| } | |
| } |
| class EPoll { | ||
| public: | ||
| EPoll(int maxEvents, std::function<void(int fd)> readAvailableCallback); | ||
| ~EPoll(); | ||
|
|
||
| bool insertFd(int fd) const; | ||
|
|
||
| private: | ||
| void eventLoop(); | ||
| private: | ||
| const int maxEvents_; | ||
| int epollFd_ = -1; | ||
| int exitEventFd_ = -1; | ||
| std::function<void(int fd)> readAvailableCallback_; | ||
| std::thread thread_; | ||
| std::atomic<bool> interrupted_{}; | ||
| }; | ||
|
|
||
| EPoll::EPoll(const int maxEvents, std::function<void(int)> readAvailableCallback) : maxEvents_(maxEvents) { | ||
| readAvailableCallback_ = std::move(readAvailableCallback); | ||
| epollFd_ = epoll_create1(0); | ||
| if (epollFd_ <= 0) { | ||
| printf("epoll_create error: %s\n", strerror(errno)); | ||
| return; | ||
| } | ||
|
|
||
| exitEventFd_ = eventfd(0, 0); | ||
| if (exitEventFd_ <= 0) { | ||
| printf("create eventfd error: %s\n", strerror(errno)); | ||
| return; | ||
| } | ||
| insertFd(exitEventFd_); | ||
|
|
||
| interrupted_.store(false); | ||
| thread_ = std::thread(&EPoll::eventLoop, this); | ||
| } | ||
|
|
||
| EPoll::~EPoll() { | ||
| interrupted_.store(true); | ||
| auto ret = eventfd_write(exitEventFd_, 0); | ||
| if (ret != 0) { | ||
| printf("eventfd_write error : ret = %d, error: %s\n", ret, strerror(errno)); | ||
| } | ||
| thread_.join(); | ||
| close(exitEventFd_); | ||
| close(epollFd_); | ||
| } | ||
|
|
||
| bool EPoll::insertFd(int fd) const { | ||
| struct epoll_event event{}; | ||
| event.events = EPOLLIN; | ||
| event.data.fd = fd; | ||
| if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &event) < 0) { | ||
| printf("epoll_ctl add error: %s\n", strerror(errno)); | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| void EPoll::eventLoop() { | ||
| while (!interrupted_.load()) { | ||
| struct epoll_event events[maxEvents_]; | ||
| int count = epoll_wait(epollFd_, events, maxEvents_, -1); | ||
| if (count == -1) { | ||
| printf("epoll_wait error: %s\n", strerror(errno)); | ||
| continue; | ||
| } | ||
|
|
||
| for (int i = 0; i < count; ++i) { | ||
| if (events[i].data.fd == exitEventFd_) { | ||
| printf("exit event loop\n"); | ||
| return; | ||
| } | ||
| readAvailableCallback_(events[i].data.fd); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EPoll 类用于管理 epoll 事件,结构良好。建议在错误处理中抛出异常,而不是仅打印错误信息,以使代码更加健壮。
- printf("epoll_create error: %s\n", strerror(errno));
+ throw std::runtime_error("epoll_create error: " + std::string(strerror(errno)));Committable suggestion was skipped due low confidence.
| oboe::DataCallbackResult | ||
| MyCallback::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) { | ||
| auto *outputData = static_cast<int16_t *>(audioData); | ||
| size_t waitLen = numFrames * frameDiv_; | ||
| if ((frameCount_++ & 0xff) == 0) { | ||
| LOGV("waitLen = %d, cachedSize_ = %d", waitLen, cachedSize_); | ||
| } | ||
|
|
||
| std::lock_guard<std::mutex> lock(mutex_); | ||
| if (cachedSize_ < waitLen) { | ||
| memset(outputData, 0, waitLen); | ||
| memcpy(outputData, &frameBuffer_, cachedSize_); | ||
| cachedSize_ = 0; | ||
| } else { | ||
| memcpy(outputData, &frameBuffer_, waitLen); | ||
| cachedSize_ -= waitLen; | ||
| memmove(frameBuffer_, frameBuffer_ + waitLen, cachedSize_); | ||
| } | ||
| return oboe::DataCallbackResult::Continue; | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
处理音频数据的方法正确管理了缓冲区。但是,使用了潜在不安全的方法访问缓冲区,建议改进。
- memcpy(outputData, &frameBuffer_, cachedSize_);
+ memcpy(outputData, frameBuffer_, cachedSize_);
- memcpy(outputData, &frameBuffer_, waitLen);
+ memcpy(outputData, frameBuffer_, waitLen);
- memmove(frameBuffer_, frameBuffer_ + waitLen, cachedSize_);
+ memmove(frameBuffer_, frameBuffer_ + waitLen, cachedSize_);Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| oboe::DataCallbackResult | |
| MyCallback::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) { | |
| auto *outputData = static_cast<int16_t *>(audioData); | |
| size_t waitLen = numFrames * frameDiv_; | |
| if ((frameCount_++ & 0xff) == 0) { | |
| LOGV("waitLen = %d, cachedSize_ = %d", waitLen, cachedSize_); | |
| } | |
| std::lock_guard<std::mutex> lock(mutex_); | |
| if (cachedSize_ < waitLen) { | |
| memset(outputData, 0, waitLen); | |
| memcpy(outputData, &frameBuffer_, cachedSize_); | |
| cachedSize_ = 0; | |
| } else { | |
| memcpy(outputData, &frameBuffer_, waitLen); | |
| cachedSize_ -= waitLen; | |
| memmove(frameBuffer_, frameBuffer_ + waitLen, cachedSize_); | |
| } | |
| return oboe::DataCallbackResult::Continue; | |
| } | |
| oboe::DataCallbackResult | |
| MyCallback::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) { | |
| auto *outputData = static_cast<int16_t *>(audioData); | |
| size_t waitLen = numFrames * frameDiv_; | |
| if ((frameCount_++ & 0xff) == 0) { | |
| LOGV("waitLen = %d, cachedSize_ = %d", waitLen, cachedSize_); | |
| } | |
| std::lock_guard<std::mutex> lock(mutex_); | |
| if (cachedSize_ < waitLen) { | |
| memset(outputData, 0, waitLen); | |
| memcpy(outputData, frameBuffer_, cachedSize_); | |
| cachedSize_ = 0; | |
| } else { | |
| memcpy(outputData, frameBuffer_, waitLen); | |
| cachedSize_ -= waitLen; | |
| memmove(frameBuffer_, frameBuffer_ + waitLen, cachedSize_); | |
| } | |
| return oboe::DataCallbackResult::Continue; | |
| } |
| class EventHub { | ||
| public: | ||
| EventHub() { | ||
| eventThead_ = std::thread(&EventHub::eventThread, this); | ||
| } | ||
|
|
||
| ~EventHub() { | ||
| interrupted_.store(true); | ||
| eventQueueCondition_.notify_one(); | ||
| eventThead_.join(); | ||
| } | ||
|
|
||
| void eventThread() { | ||
| while (!interrupted_.load()) { | ||
| eventLoop(); | ||
| } | ||
| } | ||
|
|
||
| void eventLoop() { | ||
| std::unique_lock<std::mutex> lock(eventQueueMutex_); | ||
| while (eventQueue_.empty()) { | ||
| if (interrupted_.load()) { | ||
| return; | ||
| } | ||
| eventQueueCondition_.wait(lock); | ||
| } | ||
|
|
||
| auto event = eventQueue_.front(); | ||
| eventQueue_.pop_front(); | ||
| publishEventSync(event); | ||
| } | ||
|
|
||
| void addEventListener(EventListener *listener) { | ||
| std::lock_guard<std::mutex> lock(listenerMutex_); | ||
| printf("addEventListener %p\n", listener); | ||
| listenerList_.push_back(listener); | ||
| } | ||
|
|
||
| void removeEventListener(EventListener *listener) { | ||
| std::lock_guard<std::mutex> lock(listenerMutex_); | ||
| printf("removeEventListener %p\n", listener); | ||
| for (auto it = listenerList_.begin(); it != listenerList_.end();) { | ||
| if (*it == listener) { | ||
| it = listenerList_.erase(it); | ||
| } else { | ||
| ++it; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void clearEventListener() { | ||
| listenerList_.clear(); | ||
| } | ||
|
|
||
| void publishEventSync(int event) { | ||
| std::lock_guard<std::mutex> lock(listenerMutex_); | ||
| for (auto const &listener : listenerList_) { | ||
| listener->onEvent(event); | ||
| } | ||
| } | ||
|
|
||
| void publishEventAsync(int event) { | ||
| std::lock_guard<std::mutex> lock(eventQueueMutex_); | ||
| eventQueue_.push_back(event); | ||
| eventQueueCondition_.notify_one(); | ||
| } | ||
|
|
||
| private: | ||
| std::mutex listenerMutex_; | ||
| std::list<EventListener*> listenerList_; | ||
|
|
||
| std::mutex eventQueueMutex_; | ||
| std::condition_variable eventQueueCondition_; | ||
| std::list<int> eventQueue_; | ||
|
|
||
| std::thread eventThead_; | ||
| std::atomic<bool> interrupted_{false}; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
事件中心类管理事件监听器列表和事件队列。建议在 publishEventAsync 方法中添加线程安全注释,以阐明其线程安全性。
+ // 确保此方法在多线程环境中安全调用
void publishEventAsync(int event) {Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
| class EventHub { | |
| public: | |
| EventHub() { | |
| eventThead_ = std::thread(&EventHub::eventThread, this); | |
| } | |
| ~EventHub() { | |
| interrupted_.store(true); | |
| eventQueueCondition_.notify_one(); | |
| eventThead_.join(); | |
| } | |
| void eventThread() { | |
| while (!interrupted_.load()) { | |
| eventLoop(); | |
| } | |
| } | |
| void eventLoop() { | |
| std::unique_lock<std::mutex> lock(eventQueueMutex_); | |
| while (eventQueue_.empty()) { | |
| if (interrupted_.load()) { | |
| return; | |
| } | |
| eventQueueCondition_.wait(lock); | |
| } | |
| auto event = eventQueue_.front(); | |
| eventQueue_.pop_front(); | |
| publishEventSync(event); | |
| } | |
| void addEventListener(EventListener *listener) { | |
| std::lock_guard<std::mutex> lock(listenerMutex_); | |
| printf("addEventListener %p\n", listener); | |
| listenerList_.push_back(listener); | |
| } | |
| void removeEventListener(EventListener *listener) { | |
| std::lock_guard<std::mutex> lock(listenerMutex_); | |
| printf("removeEventListener %p\n", listener); | |
| for (auto it = listenerList_.begin(); it != listenerList_.end();) { | |
| if (*it == listener) { | |
| it = listenerList_.erase(it); | |
| } else { | |
| ++it; | |
| } | |
| } | |
| } | |
| void clearEventListener() { | |
| listenerList_.clear(); | |
| } | |
| void publishEventSync(int event) { | |
| std::lock_guard<std::mutex> lock(listenerMutex_); | |
| for (auto const &listener : listenerList_) { | |
| listener->onEvent(event); | |
| } | |
| } | |
| void publishEventAsync(int event) { | |
| std::lock_guard<std::mutex> lock(eventQueueMutex_); | |
| eventQueue_.push_back(event); | |
| eventQueueCondition_.notify_one(); | |
| } | |
| private: | |
| std::mutex listenerMutex_; | |
| std::list<EventListener*> listenerList_; | |
| std::mutex eventQueueMutex_; | |
| std::condition_variable eventQueueCondition_; | |
| std::list<int> eventQueue_; | |
| std::thread eventThead_; | |
| std::atomic<bool> interrupted_{false}; | |
| }; | |
| class EventHub { | |
| public: | |
| EventHub() { | |
| eventThead_ = std::thread(&EventHub::eventThread, this); | |
| } | |
| ~EventHub() { | |
| interrupted_.store(true); | |
| eventQueueCondition_.notify_one(); | |
| eventThead_.join(); | |
| } | |
| void eventThread() { | |
| while (!interrupted_.load()) { | |
| eventLoop(); | |
| } | |
| } | |
| void eventLoop() { | |
| std::unique_lock<std::mutex> lock(eventQueueMutex_); | |
| while (eventQueue_.empty()) { | |
| if (interrupted_.load()) { | |
| return; | |
| } | |
| eventQueueCondition_.wait(lock); | |
| } | |
| auto event = eventQueue_.front(); | |
| eventQueue_.pop_front(); | |
| publishEventSync(event); | |
| } | |
| void addEventListener(EventListener *listener) { | |
| std::lock_guard<std::mutex> lock(listenerMutex_); | |
| printf("addEventListener %p\n", listener); | |
| listenerList_.push_back(listener); | |
| } | |
| void removeEventListener(EventListener *listener) { | |
| std::lock_guard<std::mutex> lock(listenerMutex_); | |
| printf("removeEventListener %p\n", listener); | |
| for (auto it = listenerList_.begin(); it != listenerList_.end();) { | |
| if (*it == listener) { | |
| it = listenerList_.erase(it); | |
| } else { | |
| ++it; | |
| } | |
| } | |
| } | |
| void clearEventListener() { | |
| listenerList_.clear(); | |
| } | |
| void publishEventSync(int event) { | |
| std::lock_guard<std::mutex> lock(listenerMutex_); | |
| for (auto const &listener : listenerList_) { | |
| listener->onEvent(event); | |
| } | |
| } | |
| // 确保此方法在多线程环境中安全调用 | |
| void publishEventAsync(int event) { | |
| std::lock_guard<std::mutex> lock(eventQueueMutex_); | |
| eventQueue_.push_back(event); | |
| eventQueueCondition_.notify_one(); | |
| } | |
| private: | |
| std::mutex listenerMutex_; | |
| std::list<EventListener*> listenerList_; | |
| std::mutex eventQueueMutex_; | |
| std::condition_variable eventQueueCondition_; | |
| std::list<int> eventQueue_; | |
| std::thread eventThead_; | |
| std::atomic<bool> interrupted_{false}; | |
| }; |
Summary by CodeRabbit
新功能
优化
其他
.idea目录添加到.gitignore文件中,避免其被版本控制系统跟踪。