作为通用的跨平台高性能线程库,在很多跨平台的项目中都可以看见pthread的身影。pthread本身的实现比较优雅,APIs使用起来也很方便。
但在Windows下使用静态编译的pthread时要特别注意一下,必须显式的调用如下四个函数,否则pthread用到的一些全局变量会没有被初始化,导致所有的pthread的APIs调用都crash.
BOOL pthread_win32_process_attach_np (void);
BOOL pthread_win32_process_detach_np (void);
BOOL pthread_win32_thread_attach_np (void);
BOOL pthread_win32_thread_detach_np (void);
pthread官方文档对此有如下的明确说明:
These functions contain the code normally run via dllMain
when the library is used as a dll but which need to be
called explicitly by an application when the library
is statically linked.
You will need to call pthread_win32_process_attach_np() before
you can call any pthread routines when statically linking.
You should call pthread_win32_process_detach_np() before
exiting your application to clean up.
pthread_win32_thread_attach_np() is currently a no-op, but
pthread_win32_thread_detach_np() is needed to clean up
the implicit pthread handle that is allocated to a Win32 thread if
it calls certain pthreads routines. Call this routine when the
Win32 thread exits.
These functions invariably return TRUE except for
pthread_win32_process_attach_np() which will return FALSE
if pthreads-win32 initialisation fails.
通过函数的名字我们不难猜测出如下调用顺序
在程序开始的时候要调用:
BOOL pthread_win32_process_attach_np (void);
BOOL pthread_win32_thread_attach_np (void);
在程序退出时要调用:
BOOL pthread_win32_thread_detach_np (void);
BOOL pthread_win32_process_detach_np (void);
比较通用的做法是在模块Load和UnLoad的时候做这个attach和detach操作,如下面所示:
/* Callback for our DLL so we can initialize pthread */
BOOL WINAPI DllMain( HANDLE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
#ifdef PTW32_STATIC_LIB
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
pthread_win32_process_attach_np();
case DLL_THREAD_ATTACH:
pthread_win32_thread_attach_np();
break;
case DLL_THREAD_DETACH:
pthread_win32_thread_detach_np();
break;
case DLL_PROCESS_DETACH:
pthread_win32_thread_detach_np();
pthread_win32_process_detach_np();
break;
}
#endif
return TRUE;
}