std::thread helper class 添加线程名称和堆栈大小

std::thread helper class to add thread name and stack size

我想制作一个助手 class(或 std::thread 的子class)以允许设置堆栈大小和线程名称。 如果线程在平台上是 运行,不支持例如堆栈大小,这个数字应该被忽略。

我在想一个“ThreadHelper”,它有扩展的构造函数接口,只是returns一个std::thread。

老实说,对于 std::thread 包含的所有模板内容,我的经验很少。

现在线程 class 被实例化为: m_thread = new std::thread(&Button::Process, this); 我想要这样的东西: m_thread = new ThreadHelper.Create(&Button::Process, this, stackSize, name);

如有任何建议,我们将不胜感激。

谢谢 马丁

您可以执行以下操作: 您需要一个围绕线程启动函数的包装器,以便您可以在线程函数 运行ning 之前(也可能在之后)调用适当的函数。包含一个 try-catch 块并进行一些错误处理可能也是个好主意。

template <typename ThreadStartFnc>
struct ThreadWrapper
{
   ThreadStartFnc fnc;
   const char *name;     // (1) Note: careful, just a pointer here, not a string. See below.
   size_t priority;
   size_t stack_size;

   ThreadWrapper(...) // constructor here...

   void operator()()
   {
      SetThreadName(name);         // Whatever that is on your system
      SetThreadPriority(priority); // dito
      SetStackSize(stack_size);    // not all systems allow this
      try {
         fnc();
      }
      catch(...) {
         cerr << "Exception caught"; // Do exception processing here.
      }
   }
};

并且您需要一种简单的方法来实例化带有“插入”包装器的 std::thread,如下所示:

template <typename Fnc>
std::thread make_thread(const Fnc& f, const char *name, size_t priority=0, size_t stack_size=0)
{
   return std::thread(ThreadWrapper<Fnc>(f, name, priority, stack_size));
}

基本上就是这样。 std::thread 接受一个 Functor 对象,这就是 ThreadWrapper。它调用 Functor() 来启动线程,即 void operator()()。此函数使用附加参数名称、优先级、stack_size 来设置所有内容,然后调用您的函数。

使用可变参数模板参数等 C++11/14/17 好东西来增强它 and/or lambda 函数,随心所欲。

下面是我们使用的实际包装函数(虽然我们不使用 Functor,但我们使用 boost::bind 和静态模板函数)。

    template <typename Fnc>
    static inline void run_cstr(const Fnc &f, const char *name, DWORD priority)
    {
        int rc=_configthreadlocale(0);
/*
        _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
        setlocale(LC_ALL, "C");
*/
        SetThreadName(name);
        watchdog::set_thread_info(name);
        ::SetThreadPriority(::GetCurrentThread(), priority);
        _set_se_translator(&_se_translator);
        _set_invalid_parameter_handler(&my_invalid_parameter_handler);
        __try {
            f();
        }
        __except (global_seh_handler(GetExceptionCode(), GetExceptionInformation()) ) {
        }
    }

它为 Visual Studio 设置线程名称 (SetThreadName),设置语言环境,设置线程优先级,将我们的软件看门狗连接到线程并设置全局 Windows try/catch 所有异常的处理程序,包括访问冲突等.... 如果任何未捕获的异常(包括无效的标准库参数)在此处结束,将执行 global_seh_handler。它将写入我们用于 post 即时调试的故障转储文件。

(1) 注意:我使用 const char *name 作为线程名称,因为我假设线程将立即 运行,而线程名称的字符串仍然可用.如果您长期存储 ThreadWrapper 类型的对象,那实际上是不安全的。然后,您需要将 const char* 更改为 std::string