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
。
我想制作一个助手 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
。