| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #ifndef AVPLAYER2_THREADBASE_H
- #define AVPLAYER2_THREADBASE_H
- #include <atomic>
- #include <chrono>
- #include <condition_variable>
- #include <functional>
- #include <mutex>
- #include <thread>
- class ThreadBase
- {
- public:
- ThreadBase()
- : m_exit(std::make_shared<std::atomic<bool>>(false))
- , m_running(false)
- {}
- virtual ~ThreadBase()
- {
- if (m_running.load()) {
- // 原子化停止请求
- requestExit();
- // 安全等待线程结束
- safeJoin();
- }
- }
- // 禁止拷贝
- ThreadBase(const ThreadBase&) = delete;
- ThreadBase& operator=(const ThreadBase&) = delete;
- ThreadBase(ThreadBase&&) = delete;
- ThreadBase& operator=(ThreadBase&&) = delete;
- // 启动线程
- void start()
- {
- if (m_running)
- return;
- *m_exit = false;
- m_running = true;
- m_thread = std::thread(&ThreadBase::threadEntry, this);
- }
- // 请求线程退出
- virtual void stop()
- {
- *m_exit = true;
- m_cv.notify_all();
- }
- // 等待线程退出
- void join()
- {
- if (!m_thread.joinable() || m_joined)
- return;
- if (std::this_thread::get_id() != m_thread.get_id()) {
- m_thread.join();
- m_joined = true;
- m_running = false;
- }
- }
- bool isRunning() const { return m_running.load(); }
- bool isExit() const { return m_exit && m_exit->load(); }
- // 设置线程结束回调
- void setOnFinished(std::function<void()> cb)
- {
- // 使用弱引用避免悬空指针
- auto weakExit = std::weak_ptr(m_exit);
- m_onFinished = [weakExit, cb]() {
- if (auto exitPtr = weakExit.lock()) {
- // 仅当退出标志设置后执行回调
- if (*exitPtr) {
- cb();
- }
- }
- };
- }
- protected:
- virtual void run() = 0;
- std::shared_ptr<std::atomic<bool>> m_exit;
- std::atomic<bool> m_running;
- std::thread m_thread;
- std::condition_variable m_cv;
- std::mutex m_mutex;
- private:
- // 新增辅助变量用于安全退出检测
- std::atomic<bool> m_finishFlag{false};
- std::mutex m_finishMutex;
- std::condition_variable m_finishCv;
- bool m_joined = false;
- std::function<void()> m_onFinished;
- // 安全的退出请求
- void requestExit() noexcept
- {
- if (m_exit) {
- m_exit->store(true);
- m_cv.notify_all();
- }
- }
- // 使用条件变量实现安全的超时等待
- void safeJoin() noexcept
- {
- if (!m_thread.joinable())
- return;
- // 检查是否在自身线程中
- if (std::this_thread::get_id() == m_thread.get_id()) {
- m_thread.detach();
- m_joined = true;
- return;
- }
- // 超时等待线程结束
- {
- std::unique_lock<std::mutex> lock(m_finishMutex);
- if (m_finishCv.wait_for(lock, std::chrono::milliseconds(500), [this] {
- return m_finishFlag.load();
- })) {
- // 线程已正常结束
- join();
- }
- }
- // 最终资源释放
- if (m_thread.joinable()) {
- try {
- m_thread.join();
- } catch (...) {
- // 忽略所有异常
- }
- m_joined = true;
- }
- }
- // 线程入口点
- void threadEntry() noexcept
- {
- try {
- run(); // 用户逻辑
- } catch (const std::exception& e) {
- // 记录标准异常
- // 注意:这里不能使用Qt的日志系统,因为可能在非主线程中
- // 可以考虑使用线程安全的日志记录方式
- (void)e; // 避免未使用变量警告
- } catch (...) {
- // 记录未知异常
- // 同样需要线程安全的日志记录
- }
-
- // 确保退出标志被设置
- if (m_exit) {
- *m_exit = true;
- }
-
- // 设置完成标志
- m_finishFlag = true;
- m_running = false;
- m_finishCv.notify_one();
- // 安全执行回调
- try {
- if (m_onFinished) {
- m_onFinished();
- }
- } catch (...) {
- // 回调函数异常不应影响线程清理
- }
- }
- };
- #endif // AVPLAYER2_THREADBASE_H
|