You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现仅收到退出信号终止、异常自动重启的std::thread包装类

方案优化点和改进实现

核心优化点

  • 线程安全修复:原方案中exit_requested_是普通bool类型,主线程调用signal_exit修改该值、工作线程读取该值的操作存在数据竞争,属于未定义行为,需要替换为std::atomic<bool>保证多线程访问安全。
  • 降低版本依赖,兼容C++11及以上标准:不需要用类模板绑定lambda类型,改用std::function<void()>存储任务即可,构造函数通过完美转发适配任意可调用对象和参数,使用体验和原生std::thread完全一致,无需C++17支持。
  • 异常处理完善:原方案仅捕获std::exception类型异常,若任务抛出非标准异常会直接触发程序终止,补充catch(...)捕获所有异常;同时支持自定义错误处理回调,替代固定写std::cout的硬编码逻辑。
  • 接口对齐原生std::thread:补充detach、get_id、joinable等常用接口,降低用户学习成本;新增析构函数自动处理线程退出逻辑,避免原生std::thread析构时若仍可连接直接终止程序的问题。
  • 空任务防护:增加对空任务的检查,避免调用空可调用对象触发异常。

改进后完整实现

#include <thread>
#include <atomic>
#include <functional>
#include <exception>
#include <iostream>

class thread_wrapper
{
public:
    // 兼容任意可调用对象和参数,和std::thread用法完全一致
    template<typename Callable, typename... Args>
    explicit thread_wrapper(Callable&& func, Args&&... args) 
        : task_(std::bind(std::forward<Callable>(func), std::forward<Args>(args)...))
        , th_(&thread_wrapper::execute, this)
    {}

    ~thread_wrapper()
    {
        if (th_.joinable())
        {
            signal_exit();
            join();
        }
    }

    void signal_exit() 
    {
        exit_requested_.store(true, std::memory_order_release);
    }

    bool joinable() const noexcept { return th_.joinable(); }
    void join() { if (joinable()) th_.join(); }
    void detach() { th_.detach(); }
    std::thread::id get_id() const noexcept { return th_.get_id(); }
    std::thread::native_handle_type native_handle() { return th_.native_handle(); }

    // 可选:自定义异常处理回调
    void set_error_handler(std::function<void(const std::exception_ptr&)> handler)
    {
        error_handler_ = std::move(handler);
    }

private:
    std::thread th_;
    std::atomic<bool> exit_requested_{false};
    std::function<void()> task_;
    std::function<void(const std::exception_ptr&)> error_handler_;

    void execute()
    {
        while(!exit_requested_.load(std::memory_order_acquire))
        {
            try
            {
                if (task_) task_();
            }
            catch (...)
            {
                auto eptr = std::current_exception();
                if (error_handler_)
                {
                    error_handler_(eptr);
                }
                else
                {
                    // 默认错误处理逻辑
                    try
                    {
                        std::rethrow_exception(eptr);
                    }
                    catch (const std::exception& e)
                    {
                        std::cerr << "Thread task error: " << e.what() << std::endl;
                    }
                    catch (...)
                    {
                        std::cerr << "Thread task caught unknown non-standard exception" << std::endl;
                    }
                }
            }
        }
    }
};

使用示例

#include <chrono>
using namespace std::chrono_literals;

class Foo
{
public:
    void say_hello(int num) { 
        std::cout << "Hello! count: " << num << std::endl;
        std::this_thread::sleep_for(2s);
    }
};

int main()
{
    Foo foo;
    // 用法1:和原方案一致传lambda
    thread_wrapper th1([&foo](){
        foo.say_hello(1); 
    });
    // 用法2:直接传成员函数和参数,和std::thread完全一致,不需要手动封装lambda
    thread_wrapper th2(&Foo::say_hello, &foo, 2);

    std::this_thread::sleep_for(10s);
    th1.signal_exit();
    th2.signal_exit();
    // 不需要手动调用join,析构函数会自动处理
    return 0;
}

内容的提问来源于stack exchange,提问作者Mdp11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 14:45:04