C++ std::thread - 命名你的线程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10121560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
std::thread - naming your thread
提问by Folkert van Heusden
The new C++ has this std::thread type. Works like a charm. Now I would like to give each thread a name for more easy debugging (like java allows you to). With pthreads I would do:
新的 C++ 有这个 std::thread 类型。奇迹般有效。现在我想给每个线程一个更容易调试的名称(就像 java 允许的那样)。使用 pthreads 我会这样做:
pthread_setname_np(pthread_self(), "thread_name");
but how can I do this with c++0x? I know it uses pthreads underneath on Linux systems, but I would like to make my application portable. Is it possible at all?
但是我怎么能用 c++0x 做到这一点呢?我知道它在 Linux 系统下使用 pthreads,但我想让我的应用程序可移植。有可能吗?
采纳答案by Mike Seymour
A portable way to do this is to maintain a map of names, keyed by the thread's ID, obtained from thread::get_id()
. Alternatively, as suggested in the comments, you could use a thread_local
variable, if you only need to access the name from within the thread.
一种可移植的方法是维护一个名称映射,以线程 ID 为键,从thread::get_id()
. 或者,如评论中所建议的thread_local
,如果您只需要从线程内访问名称,则可以使用变量。
If you didn't need portability, then you could get the underlying pthread_t
from thread::native_handle()
and do whatever platform-specific shenanigans you like with that. Be aware that the _np
on the thread naming functions means "not posix", so they aren't guaranteed to be available on all pthreads implementations.
如果您不需要可移植性,那么您可以从中获取底层pthread_t
信息thread::native_handle()
并使用它做任何您喜欢的特定于平台的恶作剧。请注意,_np
线程命名函数的意思是“not posix”,因此不能保证它们在所有 pthreads 实现上都可用。
回答by Mark Lakata
An attempt at making a wrapper to deal with many Linuxes as well as Windows. Please edit as needed.
尝试制作一个包装器来处理许多 Linux 以及 Windows。请根据需要进行编辑。
#ifdef _WIN32
#include <windows.h>
const DWORD MS_VC_EXCEPTION=0x406D1388;
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
void SetThreadName(uint32_t dwThreadID, const char* threadName)
{
// DWORD dwThreadID = ::GetThreadId( static_cast<HANDLE>( t.native_handle() ) );
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
__try
{
RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
void SetThreadName( const char* threadName)
{
SetThreadName(GetCurrentThreadId(),threadName);
}
void SetThreadName( std::thread* thread, const char* threadName)
{
DWORD threadId = ::GetThreadId( static_cast<HANDLE>( thread->native_handle() ) );
SetThreadName(threadId,threadName);
}
#else
void SetThreadName(std::thread* thread, const char* threadName)
{
auto handle = thread->native_handle();
pthread_setname_np(handle,threadName);
}
#include <sys/prctl.h>
void SetThreadName( const char* threadName)
{
prctl(PR_SET_NAME,threadName,0,0,0);
}
#endif
回答by Stephan Dollberg
回答by Soylent Graham
For windows [debugger], you can easily use the "normal" method; http://msdn.microsoft.com/en-gb/library/xcb2z8hs.aspx
对于windows [debugger],可以轻松使用“正常”方法; http://msdn.microsoft.com/en-gb/library/xcb2z8hs.aspx
Just need the thread id which you can obtain via
只需要可以通过以下方式获取的线程 ID
#include <windows.h>
DWORD ThreadId = ::GetThreadId( static_cast<HANDLE>( mThread.native_handle() ) );
回答by Zack Yezek
I've both seen this done in a system predating c++11 (where we basically invented our own Thread class that was very similar to std::thread) and in one I wrote fairly recently.
我在一个早于 c++11 的系统(我们基本上发明了我们自己的 Thread 类,它与 std::thread 非常相似)和我最近写的一个系统中都看到了这一点。
Basically, the pool really puts std::thread 2 layers down- you have a PoolThread class that contains a std::thread plus metadata like its name, ID, etc. and the the control structure that links it to its controlling pool, and the ThreadPool itself. You want to use thread pools in most threaded code for several reasons:
1) You can hide all the explicit "detach", "join", start thread on std::thread construction, etc. from users. That produces MUCH safer & cleaner code.
2) Better resource management: Too many threads will cripple performance even more than having too few. A well-built pool can do advanced things like automatic load balancing and cleaning-up hung or deadlocked threads.
3) Thread reuse: std::thread by itself is easiest to use by running every parallel task on its own thread. But thread creation & destruction are expensive, and can easily swamp the speed boost from parallel processing if you're not careful. So, it usually makes more sense to have pool threads that pull work tasks from a queue and only exit after receiving some signal.
4) Error handling: std::thread is just an execution context. If the task you're running on it throws an un-handled exception or std::thread ITSELF fails, the process will just crash right there. To do fault-tolerant multithreading, you need a Pool or something similar that can quickly catch such things and at least emit meaningful error messages before the process dies.
基本上,池真的把 std::thread 2 层放下——你有一个 PoolThread 类,它包含一个 std::thread 加上它的名称、ID 等元数据,以及将它链接到其控制池的控制结构,以及线程池本身。您想在大多数线程代码中使用线程池有以下几个原因:
1) 您可以对用户隐藏所有显式的“分离”、“连接”、std::thread 构造上的启动线程等。这会产生更安全和更清洁的代码。
2) 更好的资源管理:线程太多比线程太少对性能的影响更大。一个构建良好的池可以做一些高级的事情,比如自动负载平衡和清理挂起或死锁的线程。
3) 线程重用:通过在自己的线程上运行每个并行任务,std::thread 本身最容易使用。但是线程的创建和销毁是昂贵的,如果您不小心,很容易淹没并行处理的速度提升。因此,让池线程从队列中提取工作任务并仅在收到某些信号后才退出通常更有意义。
4) 错误处理:std::thread 只是一个执行上下文。如果您在其上运行的任务引发未处理的异常或 std::thread 本身失败,则进程将在那里崩溃。要进行容错多线程处理,您需要一个 Pool 或类似的东西,它可以快速捕获此类事件并至少在进程终止之前发出有意义的错误消息。