pthread-win32库编译及使用方法注意事项

  1. “该文引用自 CruiseYoung的:pthread-win32库编译及使用方法注意事项     
  2. http://blog.csdn.net/fksec/article/details/41517953”   

1 官网

1.1 POSIX Threads (pthreads) for Win32
http://www.sourceware.org/pthreads-win32/
下载地址:ftp://sourceware.org/pub/pthreads-win32/
1.2 当前最新版本为:PTHREADS-WIN32 RELEASE 2.9.1 (2012-05-27)
下载到的文件为pthreads-w32-2-9-1-release.zip
解压到“pthreads-w32-2-9-1-release”目录,里面有三个子目录:
[plain]  view plain  copy
 print ?
  1. pre-build.2   
  2. pthreads.2   
  3. QueueUserAPCEx  
Pthreads.2 里面包含了pthreads 的源代码;
Pre-build.2 里面包含了include和 lib 分别包含了pthreads for win32 的头文件和库文件(包括动态连接库)。以下做法不推荐:将include 和lib 里面的内容分别复制到你的编译器的include 和 lib 目录,同时将lib 目录中的 dll 文件copy 到操作系统的system32 文件夹中或应用程序执行目录。
QueueUserAPCEx 里面是一个alert的driver,编译需要DDK ,默认vs2013 没有安装。Windows Device Driver Kit (NTDDK.h) 需要额外单独安装。

2 源代码编译

虽然源码包里提供了vc6的项目文件, 但是我不推荐直接打开, 而推荐用nmake.默认的会告诉你一堆nmake参数的. 
:请仔细阅读:
[plain]  view plain  copy
 print ?
  1. pthreads-w32-2-9-1-release\pthreads.2\README(系列文件)  
  2. pthreads-w32-2-9-1-release\pthreads.2\tests\README  
2.1 命令选取:
参考文档:pthreads-w32-2-9-1-release\pthreads.2\Nmakefile
编译库我选取以下4个命令:
[plain]  view plain  copy
 print ?
  1. nmake clean VC-static (to build the MSVC static lib with C cleanup code)  
  2. nmake clean VC-static-debug (to build the debug MSVC static lib with C cleanup code)  
  3.   
  4. nmake clean VC-inlined (to build the MSVC inlined dll with C cleanup code)  
  5. nmake clean VC-inlined-debug (to build the debug MSVC inlined dll with C cleanup code)  
参考文档:pthreads-w32-2-9-1-release\pthreads.2\tests\Makefile
测试我选取以下2个命令
[plain]  view plain  copy
 print ?
  1. nmake clean VC (to test using VC dll with VC (no EH) applications)  
  2. nmake clean VC-static (to test using VC static lib with VC (no EH) applications)  
2.2 Nmakefile文件修改
将pthreads-w32-2-9-1-release\pthreads.2\Nmakefile文件中的以下语句
[plain]  view plain  copy
 print ?
  1. install:  
  2.     copy pthread*.dll $(DLLDEST)  
  3.     copy pthread*.lib $(LIBDEST)  
  4.     copy pthread.h $(HDRDEST)  
  5.     copy sched.h $(HDRDEST)  
  6.     copy semaphore.h $(HDRDEST)  
替换为:
[plain]  view plain  copy
 print ?
  1. install:  
  2.     if not exist $(DEVROOT) mkdir $(DEVROOT)  
  3.     if not exist $(DLLDEST) mkdir $(DLLDEST)  
  4.     if not exist $(LIBDEST) mkdir $(LIBDEST)  
  5.     if not exist $(HDRDEST) mkdir $(HDRDEST)      
  6.     xcopy /H /Y /R /I /V /K pthread*.dll $(DLLDEST)  
  7.     xcopy /H /Y /R /I /V /K pthread*.pdb $(LIBDEST)  
  8.     copy /Y pthread*.lib $(LIBDEST)  
  9.     copy /Y pthread.h $(HDRDEST)  
  10.     copy /Y sched.h $(HDRDEST)  
  11.     copy /Y semaphore.h $(HDRDEST)  
2.3 编译命令
通过对“pthreads-w32-2-9-1-release\pthreads.2\Nmakefile”分析,本人对编译命令我稍作修改。
x64编译:
[plain]  view plain  copy
 print ?
  1. nmake realclean VC-inlined-debug  
  2. nmake DEVROOT=D:\comm\pthreads\debug_x64 install  
  3.   
  4. nmake realclean VC-inlined  
  5. nmake DEVROOT=D:\comm\pthreads\release_x64 install  
  6. cd tests  
  7. nmake clean VC  
  8. nmake clean  
  9. cd ..  
  10.   
  11. nmake realclean VC-static-debug  
  12. nmake DEVROOT=D:\comm\pthreads\debug_x64_static install  
  13.   
  14. nmake realclean VC-static  
  15. nmake DEVROOT=D:\comm\pthreads\release_x64_static install  
  16. cd tests  
  17. nmake clean VC-static  
  18. nmake clean  
  19. cd ..  
x86编译:
[plain]  view plain  copy
 print ?
  1. nmake realclean VC-inlined-debug  
  2. nmake DEVROOT=D:\comm\pthreads\debug_x86 install  
  3.   
  4. nmake realclean VC-inlined  
  5. nmake DEVROOT=D:\comm\pthreads\release_x86 install  
  6.   
  7. cd tests  
  8. nmake clean VC  
  9. nmake clean  
  10. cd ..  
  11.   
  12. nmake realclean VC-static-debug  
  13. nmake DEVROOT=D:\comm\pthreads\debug_x86_static install  
  14.   
  15. nmake realclean VC-static  
  16. nmake DEVROOT=D:\comm\pthreads\release_x86_static install  
  17.   
  18. cd tests  
  19. nmake clean VC-static  
  20. nmake clean  
  21. cd ..  
两步合一(只编译库):
x64编译:
[plain]  view plain  copy
 print ?
  1. nmake realclean VC-inlined-debug DEVROOT=D:\comm\pthreads\debug_x64 install  
  2. nmake realclean VC-inlined DEVROOT=D:\comm\pthreads\release_x64 install  
  3. nmake realclean VC-static-debug DEVROOT=D:\comm\pthreads\debug_x64_static install  
  4. nmake realclean VC-static DEVROOT=D:\comm\pthreads\release_x64_static install  
x86编译:
[cpp]  view plain  copy
 print ?
  1. nmake realclean VC-inlined-debug DEVROOT=D:\comm\pthreads\debug_x86 install  
  2. nmake realclean VC-inlined DEVROOT=D:\\comm\pthreads\release_x86 install  
  3. nmake realclean VC-static-debug DEVROOT=D:\comm\pthreads\debug_x86_static install  
  4. nmake realclean VC-static DEVROOT=D:\comm\pthreads\release_x86_static install  

3 pthread-win32应用注意事项

注:在此请仔细阅读pthreads-w32-2-9-1-release\pthreads.2\README文件
3.1 pthreadVCE或pthreadGCE使用注意事项
原文摘录
[plain]  view plain  copy
 print ?
  1. [If you use either pthreadVCE or pthreadGCE]  
  2.   
  3. 1. [See also the discussion in the FAQ file - Q2, Q4, and Q5]  
  4.   
  5. If your application contains catch(...) blocks in your POSIX  
  6. threads then you will need to replace the "catch(...)" with the macro  
  7. "PtW32Catch", eg.  
  8.   
  9.     #ifdef PtW32Catch  
  10.         PtW32Catch {  
  11.             ...  
  12.         }  
  13.     #else  
  14.         catch(...) {  
  15.             ...  
  16.         }  
  17.     #endif  
  18.   
  19. Otherwise neither pthreads cancelation nor pthread_exit() will work  
  20. reliably when using versions of the library that use C++ exceptions  
  21. for cancelation and thread exit.  
  22.   
  23. This is due to what is believed to be a C++ compliance error in VC++  
  24. whereby you may not have multiple handlers for the same exception in  
  25. the same try/catch block. GNU G++ doesn't have this restriction.  
3.2 Cleanup代码默认形式
原文摘录
[plain]  view plain  copy
 print ?
  1. Cleanup code default style  
  2. --------------------------  
  3.   
  4. Previously, if not defined, the cleanup style was determined automatically  
  5. from the compiler used, and one of the following was defined accordingly:  
  6.   
  7.     __CLEANUP_SEH   MSVC only  
  8.     __CLEANUP_CXX   C++, including MSVC++, GNU G++  
  9.     __CLEANUP_C C, including GNU GCC, not MSVC  
  10.   
  11. These defines determine the style of cleanup (see pthread.h) and,  
  12. most importantly, the way that cancelation and thread exit (via  
  13. pthread_exit) is performed (see the routine ptw32_throw()).  
  14.   
  15. In short, the exceptions versions of the library throw an exception  
  16. when a thread is canceled, or exits via pthread_exit(). This exception is  
  17. caught by a handler in the thread startup routine, so that the  
  18. the correct stack unwinding occurs regardless of where the thread  
  19. is when it's canceled or exits via pthread_exit().  
  20.   
  21. In this snapshot, unless the build explicitly defines (e.g. via a  
  22. compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then  
  23. the build NOW always defaults to __CLEANUP_C style cleanup. This style  
  24. uses setjmp/longjmp in the cancelation and pthread_exit implementations,  
  25. and therefore won't do stack unwinding even when linked to applications  
  26. that have it (e.g. C++ apps). This is for consistency with most/all  
  27. commercial Unix POSIX threads implementations.  
  28.   
  29. Although it was not clearly documented before, it is still necessary to  
  30. build your application using the same __CLEANUP_* define as was  
  31. used for the version of the library that you link with, so that the  
  32. correct parts of pthread.h are included. That is, the possible  
  33. defines require the following library versions:  
  34.   
  35.     __CLEANUP_SEH   pthreadVSE.dll  
  36.     __CLEANUP_CXX   pthreadVCE.dll or pthreadGCE.dll  
  37.     __CLEANUP_C pthreadVC.dll or pthreadGC.dll  
  38.   
  39. It is recommended that you let pthread.h use it's default __CLEANUP_C  
  40. for both library and application builds. That is, don't define any of  
  41. the above, and then link with pthreadVC.lib (MSVC or MSVC++) and  
  42. libpthreadGC.a (MinGW GCC or G++). The reason is explained below, but  
  43. another reason is that the prebuilt pthreadVCE.dll is currently broken.  
  44. Versions built with MSVC++ later than version 6 may not be broken, but I  
  45. can't verify this yet.  
  46.   
  47. WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY?  
  48. Because no commercial Unix POSIX threads implementation allows you to  
  49. choose to have stack unwinding. Therefore, providing it in pthread-win32  
  50. as a default is dangerous. We still provide the choice but unless  
  51. you consciously choose to do otherwise, your pthreads applications will  
  52. now run or crash in similar ways irrespective of the pthreads platform  
  53. you use. Or at least this is the hope.  
3.3  静态库编译及使用(重中之重)
原文摘录
[plain]  view plain  copy
 print ?
  1. Building the library as a statically linkable library  
  2. -----------------------------------------------------  
  3.   
  4. General: PTW32_STATIC_LIB must be defined for both the library build and the  
  5. application build. The makefiles supplied and used by the following 'make'  
  6. command lines will define this for you.  
  7.   
  8. MSVC (creates pthreadVCn.lib as a static link lib):  
  9.   
  10. nmake clean VC-static  
  11.   
  12.   
  13.   
  14. MinGW32 (creates libpthreadGCn.a as a static link lib):  
  15.   
  16. make clean GC-static  
  17.   
  18.   
  19.   
  20. Define PTW32_STATIC_LIB when building your application. Also, your  
  21. application must call a two non-portable routines to initialise the  
  22. some state on startup and cleanup before exit. One other routine needs  
  23. to be called to cleanup after any Win32 threads have called POSIX API  
  24. routines. See README.NONPORTABLE or the html reference manual pages for  
  25. details on these routines:  
  26.   
  27. BOOL pthread_win32_process_attach_np (void);  
  28. BOOL pthread_win32_process_detach_np (void);  
  29. BOOL pthread_win32_thread_attach_np (void); // Currently a no-op  
  30. BOOL pthread_win32_thread_detach_np (void);  
  31.   
  32.   
  33.   
  34. The tests makefiles have the same targets but only check that the  
  35. static library is statically linkable. They don't run the full  
  36. testsuite. To run the full testsuite, build the dlls and run the  
  37. dll test targets.  
3.4  pthread_win32不可移植的特性及问题(非常重要)
详见pthreads-w32-2-9-1-release\pthreads.2\README.NONPORTABLE文件
原文摘录
[plain]  view plain  copy
 print ?
  1. This file documents non-portable functions and other issues.  
  2.   
  3. Non-portable functions included in pthreads-win32  
  4. -------------------------------------------------  
  5.   
  6. BOOL  
  7. pthread_win32_test_features_np(int mask)  
  8.   
  9.     This routine allows an application to check which  
  10.     run-time auto-detected features are available within  
  11.     the library.  
  12.   
  13.     The possible features are:  
  14.   
  15.         PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE  
  16.             Return TRUE if the native version of  
  17.             InterlockedCompareExchange() is being used.  
  18.             This feature is not meaningful in recent  
  19.             library versions as MSVC builds only support  
  20.             system implemented ICE. Note that all Mingw  
  21.             builds use inlined asm versions of all the  
  22.             Interlocked routines.  
  23.         PTW32_ALERTABLE_ASYNC_CANCEL  
  24.             Return TRUE is the QueueUserAPCEx package  
  25.             QUSEREX.DLL is available and the AlertDrv.sys  
  26.             driver is loaded into Windows, providing  
  27.             alertable (pre-emptive) asyncronous threads  
  28.             cancelation. If this feature returns FALSE  
  29.             then the default async cancel scheme is in  
  30.             use, which cannot cancel blocked threads.  
  31.   
  32.     Features may be Or'ed into the mask parameter, in which case  
  33.     the routine returns TRUE if any of the Or'ed features would  
  34.     return TRUE. At this stage it doesn't make sense to Or features  
  35.     but it may some day.  
  36.   
  37.   
  38. void *  
  39. pthread_timechange_handler_np(void *)  
  40.   
  41.         To improve tolerance against operator or time service  
  42.         initiated system clock changes.  
  43.   
  44.         This routine can be called by an application when it  
  45.         receives a WM_TIMECHANGE message from the system. At  
  46.         present it broadcasts all condition variables so that  
  47.         waiting threads can wake up and re-evaluate their  
  48.         conditions and restart their timed waits if required.  
  49.   
  50.         It has the same return type and argument type as a  
  51.         thread routine so that it may be called directly  
  52.         through pthread_create(), i.e. as a separate thread.  
  53.   
  54.         Parameters  
  55.   
  56.         Although a parameter must be supplied, it is ignored.  
  57.         The value NULL can be used.  
  58.   
  59.         Return values  
  60.   
  61.         It can return an error EAGAIN to indicate that not  
  62.         all condition variables were broadcast for some reason.  
  63.         Otherwise, 0 is returned.  
  64.   
  65.         If run as a thread, the return value is returned  
  66.         through pthread_join().  
  67.   
  68.         The return value should be cast to an integer.  
  69.   
  70.   
  71. HANDLE  
  72. pthread_getw32threadhandle_np(pthread_t thread);  
  73.   
  74.     Returns the win32 thread handle that the POSIX  
  75.     thread "thread" is running as.  
  76.   
  77.     Applications can use the win32 handle to set  
  78.     win32 specific attributes of the thread.  
  79.   
  80. DWORD  
  81. pthread_getw32threadid_np (pthread_t thread)  
  82.   
  83.     Returns the Windows native thread ID that the POSIX  
  84.     thread "thread" is running as.  
  85.   
  86.         Only valid when the library is built where  
  87.         ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)  
  88.         and otherwise returns 0.  
  89.   
  90.   
  91. int  
  92. pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, int kind)  
  93.   
  94. int  
  95. pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, int *kind)  
  96.   
  97.         These two routines are included for Linux compatibility  
  98.         and are direct equivalents to the standard routines  
  99.                 pthread_mutexattr_settype  
  100.                 pthread_mutexattr_gettype  
  101.   
  102.         pthread_mutexattr_setkind_np accepts the following  
  103.         mutex kinds:  
  104.                 PTHREAD_MUTEX_FAST_NP  
  105.                 PTHREAD_MUTEX_ERRORCHECK_NP  
  106.                 PTHREAD_MUTEX_RECURSIVE_NP  
  107.   
  108.         These are really just equivalent to (respectively):  
  109.                 PTHREAD_MUTEX_NORMAL  
  110.                 PTHREAD_MUTEX_ERRORCHECK  
  111.                 PTHREAD_MUTEX_RECURSIVE  
  112.   
  113. int  
  114. pthread_delay_np (const struct timespec *interval);  
  115.   
  116.         This routine causes a thread to delay execution for a specific period of time.  
  117.         This period ends at the current time plus the specified interval. The routine  
  118.         will not return before the end of the period is reached, but may return an  
  119.         arbitrary amount of time after the period has gone by. This can be due to  
  120.         system load, thread priorities, and system timer granularity.  
  121.   
  122.         Specifying an interval of zero (0) seconds and zero (0) nanoseconds is  
  123.         allowed and can be used to force the thread to give up the processor or to  
  124.         deliver a pending cancelation request.  
  125.   
  126.         This routine is a cancelation point.  
  127.   
  128.         The timespec structure contains the following two fields:  
  129.   
  130.                 tv_sec is an integer number of seconds.  
  131.                 tv_nsec is an integer number of nanoseconds.   
  132.   
  133.         Return Values  
  134.   
  135.         If an error condition occurs, this routine returns an integer value  
  136.         indicating the type of error. Possible return values are as follows:  
  137.   
  138.         0          Successful completion.   
  139.         [EINVAL]   The value specified by interval is invalid.   
  140.   
  141. int  
  142. pthread_num_processors_np (void)  
  143.   
  144.         This routine (found on HPUX systems) returns the number of processors  
  145.         in the system. This implementation actually returns the number of  
  146.         processors available to the process, which can be a lower number  
  147.         than the system's number, depending on the process's affinity mask.  
  148.   
  149. BOOL  
  150. pthread_win32_process_attach_np (void);  
  151.   
  152. BOOL  
  153. pthread_win32_process_detach_np (void);  
  154.   
  155. BOOL  
  156. pthread_win32_thread_attach_np (void);  
  157.   
  158. BOOL  
  159. pthread_win32_thread_detach_np (void);  
  160.   
  161.     These functions contain the code normally run via dllMain  
  162.     when the library is used as a dll but which need to be  
  163.     called explicitly by an application when the library  
  164.     is statically linked. As of version 2.9.0 of the library, static  
  165.     builds using either MSC or GCC will call pthread_win32_process_*  
  166.     automatically at application startup and exit respectively.  
  167.   
  168.     Otherwise, you will need to call pthread_win32_process_attach_np()  
  169.     before you can call any pthread routines when statically linking.  
  170.     You should call pthread_win32_process_detach_np() before  
  171.     exiting your application to clean up.  
  172.   
  173.     pthread_win32_thread_attach_np() is currently a no-op, but  
  174.     pthread_win32_thread_detach_np() is needed to clean up  
  175.     the implicit pthread handle that is allocated to a Win32 thread if  
  176.     it calls any pthreads routines. Call this routine when the  
  177.     Win32 thread exits.  
  178.   
  179.     Threads created through pthread_create() do not need to call  
  180.     pthread_win32_thread_detach_np().  
  181.   
  182.     These functions invariably return TRUE except for  
  183.     pthread_win32_process_attach_np() which will return FALSE  
  184.     if pthreads-win32 initialisation fails.  
  185.   
  186. int  
  187. pthreadCancelableWait (HANDLE waitHandle);  
  188.   
  189. int  
  190. pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout);  
  191.   
  192.     These two functions provide hooks into the pthread_cancel  
  193.     mechanism that will allow you to wait on a Windows handle  
  194.     and make it a cancellation point. Both functions block  
  195.     until either the given w32 handle is signaled, or  
  196.     pthread_cancel has been called. It is implemented using  
  197.     WaitForMultipleObjects on 'waitHandle' and a manually  
  198.     reset w32 event used to implement pthread_cancel.  
  199.   
  200.   
  201. Non-portable issues  
  202. -------------------  
  203.   
  204. Thread priority  
  205.   
  206.     POSIX defines a single contiguous range of numbers that determine a  
  207.     thread's priority. Win32 defines priority classes and priority  
  208.     levels relative to these classes. Classes are simply priority base  
  209.     levels that the defined priority levels are relative to such that,  
  210.     changing a process's priority class will change the priority of all  
  211.     of it's threads, while the threads retain the same relativity to each  
  212.     other.  
  213.   
  214.     A Win32 system defines a single contiguous monotonic range of values  
  215.     that define system priority levels, just like POSIX. However, Win32  
  216.     restricts individual threads to a subset of this range on a  
  217.     per-process basis.  
  218.   
  219.     The following table shows the base priority levels for combinations  
  220.     of priority class and priority value in Win32.  
  221.       
  222.      Process Priority Class               Thread Priority Level  
  223.      -----------------------------------------------------------------  
  224.      1 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_IDLE  
  225.      1 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_IDLE  
  226.      1 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_IDLE  
  227.      1 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_IDLE  
  228.      1 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_IDLE  
  229.      2 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_LOWEST  
  230.      3 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_BELOW_NORMAL  
  231.      4 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_NORMAL  
  232.      4 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_LOWEST  
  233.      5 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_ABOVE_NORMAL  
  234.      5 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_BELOW_NORMAL  
  235.      5 Background NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_LOWEST  
  236.      6 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_HIGHEST  
  237.      6 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_NORMAL  
  238.      6 Background NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_BELOW_NORMAL  
  239.      7 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_ABOVE_NORMAL  
  240.      7 Background NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_NORMAL  
  241.      7 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_LOWEST  
  242.      8 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_HIGHEST  
  243.      8 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_ABOVE_NORMAL  
  244.      8 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_BELOW_NORMAL  
  245.      8 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_LOWEST  
  246.      9 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_HIGHEST  
  247.      9 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_NORMAL  
  248.      9 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_BELOW_NORMAL  
  249.     10 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_ABOVE_NORMAL  
  250.     10 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_NORMAL  
  251.     11 Foreground NORMAL_PRIORITY_CLASS   THREAD_PRIORITY_HIGHEST  
  252.     11 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_ABOVE_NORMAL  
  253.     11 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_LOWEST  
  254.     12 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_HIGHEST  
  255.     12 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_BELOW_NORMAL  
  256.     13 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_NORMAL  
  257.     14 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_ABOVE_NORMAL  
  258.     15 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_HIGHEST  
  259.     15 HIGH_PRIORITY_CLASS                THREAD_PRIORITY_TIME_CRITICAL  
  260.     15 IDLE_PRIORITY_CLASS                THREAD_PRIORITY_TIME_CRITICAL  
  261.     15 BELOW_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_TIME_CRITICAL  
  262.     15 NORMAL_PRIORITY_CLASS              THREAD_PRIORITY_TIME_CRITICAL  
  263.     15 ABOVE_NORMAL_PRIORITY_CLASS        THREAD_PRIORITY_TIME_CRITICAL  
  264.     16 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_IDLE  
  265.     17 REALTIME_PRIORITY_CLASS            -7  
  266.     18 REALTIME_PRIORITY_CLASS            -6  
  267.     19 REALTIME_PRIORITY_CLASS            -5  
  268.     20 REALTIME_PRIORITY_CLASS            -4  
  269.     21 REALTIME_PRIORITY_CLASS            -3  
  270.     22 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_LOWEST  
  271.     23 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_BELOW_NORMAL  
  272.     24 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_NORMAL  
  273.     25 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_ABOVE_NORMAL  
  274.     26 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_HIGHEST  
  275.     27 REALTIME_PRIORITY_CLASS             3  
  276.     28 REALTIME_PRIORITY_CLASS             4  
  277.     29 REALTIME_PRIORITY_CLASS             5  
  278.     30 REALTIME_PRIORITY_CLASS             6  
  279.     31 REALTIME_PRIORITY_CLASS            THREAD_PRIORITY_TIME_CRITICAL  
  280.       
  281.     Windows NT:  Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported.  
  282.   
  283.   
  284.     As you can see, the real priority levels available to any individual  
  285.     Win32 thread are non-contiguous.  
  286.   
  287.     An application using pthreads-win32 should not make assumptions about  
  288.     the numbers used to represent thread priority levels, except that they  
  289.     are monotonic between the values returned by sched_get_priority_min()  
  290.     and sched_get_priority_max(). E.g. Windows 95, 98, NT, 2000, XP make  
  291.     available a non-contiguous range of numbers between -15 and 15, while  
  292.     at least one version of WinCE (3.0) defines the minimum priority  
  293.     (THREAD_PRIORITY_LOWEST) as 5, and the maximum priority  
  294.     (THREAD_PRIORITY_HIGHEST) as 1.  
  295.   
  296.     Internally, pthreads-win32 maps any priority levels between  
  297.     THREAD_PRIORITY_IDLE and THREAD_PRIORITY_LOWEST to THREAD_PRIORITY_LOWEST,  
  298.     or between THREAD_PRIORITY_TIME_CRITICAL and THREAD_PRIORITY_HIGHEST to  
  299.     THREAD_PRIORITY_HIGHEST. Currently, this also applies to  
  300.     REALTIME_PRIORITY_CLASSi even if levels -7, -6, -5, -4, -3, 3, 4, 5, and 6  
  301.     are supported.  
  302.   
  303.     If it wishes, a Win32 application using pthreads-win32 can use the Win32  
  304.     defined priority macros THREAD_PRIORITY_IDLE through  
  305.     THREAD_PRIORITY_TIME_CRITICAL.  
  306.   
  307.   
  308. The opacity of the pthread_t datatype  
  309. -------------------------------------  
  310. and possible solutions for portable null/compare/hash, etc  
  311. ----------------------------------------------------------  
  312.   
  313. Because pthread_t is an opague datatype an implementation is permitted to define  
  314. pthread_t in any way it wishes. That includes defining some bits, if it is  
  315. scalar, or members, if it is an aggregate, to store information that may be  
  316. extra to the unique identifying value of the ID. As a result, pthread_t values  
  317. may not be directly comparable.  
  318.   
  319. If you want your code to be portable you must adhere to the following contraints:  
  320.   
  321. 1) Don't assume it is a scalar data type, e.g. an integer or pointer value. There  
  322. are several other implementations where pthread_t is also a struct. See our FAQ  
  323. Question 11 for our reasons for defining pthread_t as a struct.  
  324.   
  325. 2) You must not compare them using relational or equality operators. You must use  
  326. the API function pthread_equal() to test for equality.  
  327.   
  328. 3) Never attempt to reference individual members.  
  329.   
  330.   
  331. The problem  
  332.   
  333. Certain applications would like to be able to access only the 'pure' pthread_t  
  334. id values, primarily to use as keys into data structures to manage threads or  
  335. thread-related data, but this is not possible in a maximally portable and  
  336. standards compliant way for current POSIX threads implementations.  
  337.   
  338. For implementations that define pthread_t as a scalar, programmers often employ  
  339. direct relational and equality operators on pthread_t. This code will break when  
  340. ported to an implementation that defines pthread_t as an aggregate type.  
  341.   
  342. For implementations that define pthread_t as an aggregate, e.g. a struct,  
  343. programmers can use memcmp etc., but then face the prospect that the struct may  
  344. include alignment padding bytes or bits as well as extra implementation-specific  
  345. members that are not part of the unique identifying value.  
  346.   
  347. [While this is not currently the case for pthreads-win32, opacity also  
  348. means that an implementation is free to change the definition, which should  
  349. generally only require that applications be recompiled and relinked, not  
  350. rewritten.]  
  351.   
  352.   
  353. Doesn't the compiler take care of padding?  
  354.   
  355. The C89 and later standards only effectively guarrantee element-by-element  
  356. equivalence following an assignment or pass by value of a struct or union,  
  357. therefore undefined areas of any two otherwise equivalent pthread_t instances  
  358. can still compare differently, e.g. attempting to compare two such pthread_t  
  359. variables byte-by-byte, e.g. memcmp(&t1, &t2, sizeof(pthread_t) may give an  
  360. incorrect result. In practice I'm reasonably confident that compilers routinely  
  361. also copy the padding bytes, mainly because assignment of unions would be far  
  362. too complicated otherwise. But it just isn't guarranteed by the standard.  
  363.   
  364. Illustration:  
  365.   
  366. We have two thread IDs t1 and t2  
  367.   
  368. pthread_t t1, t2;  
  369.   
  370. In an application we create the threads and intend to store the thread IDs in an  
  371. ordered data structure (linked list, tree, etc) so we need to be able to compare  
  372. them in order to insert them initially and also to traverse.  
  373.   
  374. Suppose pthread_t contains undefined padding bits and our compiler copies our  
  375. pthread_t [struct] element-by-element, then for the assignment:  
  376.   
  377. pthread_t temp = t1;  
  378.   
  379. temp and t1 will be equivalent and correct but a byte-for-byte comparison such as  
  380. memcmp(&temp, &t1, sizeof(pthread_t)) == 0 may not return true as we expect because  
  381. the undefined bits may not have the same values in the two variable instances.  
  382.   
  383. Similarly if passing by value under the same conditions.  
  384.   
  385. If, on the other hand, the undefined bits are at least constant through every  
  386. assignment and pass-by-value then the byte-for-byte comparison  
  387. memcmp(&temp, &t1, sizeof(pthread_t)) == 0 will always return the expected result.  
  388. How can we force the behaviour we need?  
  389.   
  390.   
  391. Solutions  
  392.   
  393. Adding new functions to the standard API or as non-portable extentions is  
  394. the only reliable and portable way to provide the necessary operations.  
  395. Remember also that POSIX is not tied to the C language. The most common  
  396. functions that have been suggested are:  
  397.   
  398. pthread_null()  
  399. pthread_compare()  
  400. pthread_hash()  
  401.   
  402. A single more general purpose function could also be defined as a  
  403. basis for at least the last two of the above functions.  
  404.   
  405. First we need to list the freedoms and constraints with restpect  
  406. to pthread_t so that we can be sure our solution is compatible with the  
  407. standard.  
  408.   
  409. What is known or may be deduced from the standard:  
  410. 1) pthread_t must be able to be passed by value, so it must be a single object.  
  411. 2) from (1) it must be copyable so cannot embed thread-state information, locks  
  412. or other volatile objects required to manage the thread it associates with.  
  413. 3) pthread_t may carry additional information, e.g. for debugging or to manage  
  414. itself.  
  415. 4) there is an implicit requirement that the size of pthread_t is determinable  
  416. at compile-time and size-invariant, because it must be able to copy the object  
  417. (i.e. through assignment and pass-by-value). Such copies must be genuine  
  418. duplicates, not merely a copy of a pointer to a common instance such as  
  419. would be the case if pthread_t were defined as an array.  
  420.   
  421.   
  422. Suppose we define the following function:  
  423.   
  424. /* This function shall return it's argument */  
  425. pthread_t* pthread_normalize(pthread_t* thread);  
  426.   
  427. For scalar or aggregate pthread_t types this function would simply zero any bits  
  428. within the pthread_t that don't uniquely identify the thread, including padding,  
  429. such that client code can return consistent results from operations done on the  
  430. result. If the additional bits are a pointer to an associate structure then  
  431. this function would ensure that the memory used to store that associate  
  432. structure does not leak. After normalization the following compare would be  
  433. valid and repeatable:  
  434.   
  435. memcmp(pthread_normalize(&t1),pthread_normalize(&t2),sizeof(pthread_t))  
  436.   
  437. Note 1: such comparisons are intended merely to order and sort pthread_t values  
  438. and allow them to index various data structures. They are not intended to reveal  
  439. anything about the relationships between threads, like startup order.  
  440.   
  441. Note 2: the normalized pthread_t is also a valid pthread_t that uniquely  
  442. identifies the same thread.  
  443.   
  444. Advantages:  
  445. 1) In most existing implementations this function would reduce to a no-op that  
  446. emits no additional instructions, i.e after in-lining or optimisation, or if  
  447. defined as a macro:  
  448. #define pthread_normalise(tptr) (tptr)  
  449.   
  450. 2) This single function allows an application to portably derive  
  451. application-level versions of any of the other required functions.  
  452.   
  453. 3) It is a generic function that could enable unanticipated uses.  
  454.   
  455. Disadvantages:  
  456. 1) Less efficient than dedicated compare or hash functions for implementations  
  457. that include significant extra non-id elements in pthread_t.  
  458.   
  459. 2) Still need to be concerned about padding if copying normalized pthread_t.  
  460. See the later section on defining pthread_t to neutralise padding issues.  
  461.   
  462. Generally a pthread_t may need to be normalized every time it is used,  
  463. which could have a significant impact. However, this is a design decision  
  464. for the implementor in a competitive environment. An implementation is free  
  465. to define a pthread_t in a way that minimises or eliminates padding or  
  466. renders this function a no-op.  
  467.   
  468. Hazards:  
  469. 1) Pass-by-reference directly modifies 'thread' so the application must  
  470. synchronise access or ensure that the pointer refers to a copy. The alternative  
  471. of pass-by-value/return-by-value was considered but then this requires two copy  
  472. operations, disadvantaging implementations where this function is not a no-op  
  473. in terms of speed of execution. This function is intended to be used in high  
  474. frequency situations and needs to be efficient, or at least not unnecessarily  
  475. inefficient. The alternative also sits awkwardly with functions like memcmp.  
  476.   
  477. 2) [Non-compliant] code that uses relational and equality operators on  
  478. arithmetic or pointer style pthread_t types would need to be rewritten, but it  
  479. should be rewritten anyway.  
  480.   
  481.   
  482. C implementation of null/compare/hash functions using pthread_normalize():  
  483.   
  484. /* In pthread.h */  
  485. pthread_t* pthread_normalize(pthread_t* thread);  
  486.   
  487. /* In user code */  
  488. /* User-level bitclear function - clear bits in loc corresponding to mask */  
  489. void* bitclear (void* loc, void* mask, size_t count);  
  490.   
  491. typedef unsigned int hash_t;  
  492.   
  493. /* User-level hash function */  
  494. hash_t hash(void* ptr, size_t count);  
  495.   
  496. /*  
  497.  * User-level pthr_null function - modifies the origin thread handle.  
  498.  * The concept of a null pthread_t is highly implementation dependent  
  499.  * and this design may be far from the mark. For example, in an  
  500.  * implementation "null" may mean setting a special value inside one  
  501.  * element of pthread_t to mean "INVALID". However, if that value was zero and  
  502.  * formed part of the id component then we may get away with this design.  
  503.  */  
  504. pthread_t* pthr_null(pthread_t* tp)  
  505. {  
  506.   /*   
  507.    * This should have the same effect as memset(tp, 0, sizeof(pthread_t))  
  508.    * We're just showing that we can do it.  
  509.    */  
  510.   void* p = (void*) pthread_normalize(tp);  
  511.   return (pthread_t*) bitclear(p, p, sizeof(pthread_t));  
  512. }  
  513.   
  514. /*  
  515.  * Safe user-level pthr_compare function - modifies temporary thread handle copies  
  516.  */  
  517. int pthr_compare_safe(pthread_t thread1, pthread_t thread2)  
  518. {  
  519.   return memcmp(pthread_normalize(&thread1), pthread_normalize(&thread2), sizeof(pthread_t));  
  520. }  
  521.   
  522. /*  
  523.  * Fast user-level pthr_compare function - modifies origin thread handles  
  524.  */  
  525. int pthr_compare_fast(pthread_t* thread1, pthread_t* thread2)  
  526. {  
  527.   return memcmp(pthread_normalize(&thread1), pthread_normalize(&thread2), sizeof(pthread_t));  
  528. }  
  529.   
  530. /*  
  531.  * Safe user-level pthr_hash function - modifies temporary thread handle copy  
  532.  */  
  533. hash_t pthr_hash_safe(pthread_t thread)  
  534. {  
  535.   return hash((void *) pthread_normalize(&thread), sizeof(pthread_t));  
  536. }  
  537.   
  538. /*  
  539.  * Fast user-level pthr_hash function - modifies origin thread handle  
  540.  */  
  541. hash_t pthr_hash_fast(pthread_t thread)  
  542. {  
  543.   return hash((void *) pthread_normalize(&thread), sizeof(pthread_t));  
  544. }  
  545.   
  546. /* User-level bitclear function - modifies the origin array */  
  547. void* bitclear(void* loc, void* mask, size_t count)  
  548. {  
  549.   int i;  
  550.   for (i=0; i < count; i++) {  
  551.     (unsigned char) *loc++ &= ~((unsigned char) *mask++);  
  552.   }  
  553. }  
  554.   
  555. /* Donald Knuth hash */  
  556. hash_t hash(void* str, size_t count)  
  557. {  
  558.    hash_t hash = (hash_t) count;  
  559.    unsigned int i = 0;  
  560.   
  561.    for(i = 0; i < len; str++, i++)  
  562.    {  
  563.       hash = ((hash << 5) ^ (hash >> 27)) ^ (*str);  
  564.    }  
  565.    return hash;  
  566. }  
  567.   
  568. /* Example of advantage point (3) - split a thread handle into its id and non-id values */  
  569. pthread_t id = thread, non-id = thread;  
  570. bitclear((void*) &non-id, (void*) pthread_normalize(&id), sizeof(pthread_t));  
  571.   
  572.   
  573. A pthread_t type change proposal to neutralise the effects of padding  
  574.   
  575. Even if pthread_nornalize() is available, padding is still a problem because  
  576. the standard only garrantees element-by-element equivalence through  
  577. copy operations (assignment and pass-by-value). So padding bit values can  
  578. still change randomly after calls to pthread_normalize().  
  579.   
  580. [I suspect that most compilers take the easy path and always byte-copy anyway,  
  581. partly because it becomes too complex to do (e.g. unions that contain sub-aggregates)  
  582. but also because programmers can easily design their aggregates to minimise and  
  583. often eliminate padding].  
  584.   
  585. How can we eliminate the problem of padding bytes in structs? Could  
  586. defining pthread_t as a union rather than a struct provide a solution?  
  587.   
  588. In fact, the Linux pthread.h defines most of it's pthread_*_t objects (but not  
  589. pthread_t itself) as unions, possibly for this and/or other reasons. We'll  
  590. borrow some element naming from there but the ideas themselves are well known  
  591. - the __align element used to force alignment of the union comes from K&R's  
  592. storage allocator example.  
  593.   
  594. /* Essentially our current pthread_t renamed */  
  595. typedef struct {  
  596.   struct thread_state_t * __p;  
  597.   long __x; /* sequence counter */  
  598. } thread_id_t;  
  599.   
  600. Ensuring that the last element in the above struct is a long ensures that the  
  601. overall struct size is a multiple of sizeof(long), so there should be no trailing  
  602. padding in this struct or the union we define below.  
  603. (Later we'll see that we can handle internal but not trailing padding.)  
  604.   
  605. /* New pthread_t */  
  606. typedef union {  
  607.   char __size[sizeof(thread_id_t)]; /* array as the first element */  
  608.   thread_id_t __tid;  
  609.   long __align;  /* Ensure that the union starts on long boundary */  
  610. } pthread_t;  
  611.   
  612. This guarrantees that, during an assignment or pass-by-value, the compiler copies  
  613. every byte in our thread_id_t because the compiler guarrantees that the __size  
  614. array, which we have ensured is the equal-largest element in the union, retains  
  615. equivalence.  
  616.   
  617. This means that pthread_t values stored, assigned and passed by value will at least  
  618. carry the value of any undefined padding bytes along and therefore ensure that  
  619. those values remain consistent. Our comparisons will return consistent results and  
  620. our hashes of [zero initialised] pthread_t values will also return consistent  
  621. results.  
  622.   
  623. We have also removed the need for a pthread_null() function; we can initialise  
  624. at declaration time or easily create our own const pthread_t to use in assignments  
  625. later:  
  626.   
  627. const pthread_t null_tid = {0}; /* braces are required */  
  628.   
  629. pthread_t t;  
  630. ...  
  631. t = null_tid;  
  632.   
  633.   
  634. Note that we don't have to explicitly make use of the __size array at all. It's  
  635. there just to force the compiler behaviour we want.  
  636.   
  637.   
  638. Partial solutions without a pthread_normalize function  
  639.   
  640.   
  641. An application-level pthread_null and pthread_compare proposal  
  642. (and pthread_hash proposal by extention)  
  643.   
  644. In order to deal with the problem of scalar/aggregate pthread_t type disparity in  
  645. portable code I suggest using an old-fashioned union, e.g.:  
  646.   
  647. Contraints:  
  648. - there is no padding, or padding values are preserved through assignment and  
  649.   pass-by-value (see above);  
  650. - there are no extra non-id values in the pthread_t.  
  651.   
  652.   
  653. Example 1: A null initialiser for pthread_t variables...  
  654.   
  655. typedef union {  
  656.     unsigned char b[sizeof(pthread_t)];  
  657.     pthread_t t;  
  658. } init_t;  
  659.   
  660. const init_t initial = {0};  
  661.   
  662. pthread_t tid = initial.t; /* init tid to all zeroes */  
  663.   
  664.   
  665. Example 2: A comparison function for pthread_t values  
  666.   
  667. typedef union {  
  668.    unsigned char b[sizeof(pthread_t)];  
  669.    pthread_t t;  
  670. } pthcmp_t;  
  671.   
  672. int pthcmp(pthread_t left, pthread_t right)  
  673. {  
  674.   /*  
  675.   * Compare two pthread handles in a way that imposes a repeatable but arbitrary  
  676.   * ordering on them.  
  677.   * I.e. given the same set of pthread_t handles the ordering should be the same  
  678.   * each time but the order has no particular meaning other than that. E.g.  
  679.   * the ordering does not imply the thread start sequence, or any other  
  680.   * relationship between threads.  
  681.   *  
  682.   * Return values are:  
  683.   * 1 : left is greater than right  
  684.   * 0 : left is equal to right  
  685.   * -1 : left is less than right  
  686.   */  
  687.   int i;  
  688.   pthcmp_t L, R;  
  689.   L.t = left;  
  690.   R.t = right;  
  691.   for (i = 0; i < sizeof(pthread_t); i++)  
  692.   {  
  693.     if (L.b[i] > R.b[i])  
  694.       return 1;  
  695.     else if (L.b[i] < R.b[i])  
  696.       return -1;  
  697.   }  
  698.   return 0;  
  699. }  
  700.   
  701. It has been pointed out that the C99 standard allows for the possibility that  
  702. integer types also may include padding bits, which could invalidate the above  
  703. method. This addition to C99 was specifically included after it was pointed  
  704. out that there was one, presumably not particularly well known, architecture  
  705. that included a padding bit in it's 32 bit integer type. See section 6.2.6.2  
  706. of both the standard and the rationale, specifically the paragraph starting at  
  707. line 16 on page 43 of the rationale.  
  708.   
  709.   
  710. An aside  
  711.   
  712. Certain compilers, e.g. gcc and one of the IBM compilers, include a feature  
  713. extention: provided the union contains a member of the same type as the  
  714. object then the object may be cast to the union itself.  
  715.   
  716. We could use this feature to speed up the pthrcmp() function from example 2  
  717. above by casting rather than assigning the pthread_t arguments to the union, e.g.:  
  718.   
  719. int pthcmp(pthread_t left, pthread_t right)  
  720. {  
  721.   /*  
  722.   * Compare two pthread handles in a way that imposes a repeatable but arbitrary  
  723.   * ordering on them.  
  724.   * I.e. given the same set of pthread_t handles the ordering should be the same  
  725.   * each time but the order has no particular meaning other than that. E.g.  
  726.   * the ordering does not imply the thread start sequence, or any other  
  727.   * relationship between threads.  
  728.   *  
  729.   * Return values are:  
  730.   * 1 : left is greater than right  
  731.   * 0 : left is equal to right  
  732.   * -1 : left is less than right  
  733.   */  
  734.   int i;  
  735.   for (i = 0; i < sizeof(pthread_t); i++)  
  736.   {  
  737.     if (((pthcmp_t)left).b[i] > ((pthcmp_t)right).b[i])  
  738.       return 1;  
  739.     else if (((pthcmp_t)left).b[i] < ((pthcmp_t)right).b[i])  
  740.       return -1;  
  741.   }  
  742.   return 0;  
  743. }  
  744.   
  745.   
  746. Result thus far  
  747.   
  748. We can't remove undefined bits if they are there in pthread_t already, but we have  
  749. attempted to render them inert for comparison and hashing functions by making them  
  750. consistent through assignment, copy and pass-by-value.  
  751.   
  752. Note: Hashing pthread_t values requires that all pthread_t variables be initialised  
  753. to the same value (usually all zeros) before being assigned a proper thread ID, i.e.  
  754. to ensure that any padding bits are zero, or at least the same value for all  
  755. pthread_t. Since all pthread_t values are generated by the library in the first  
  756. instance this need not be an application-level operation.  
  757.   
  758.   
  759. Conclusion  
  760.   
  761. I've attempted to resolve the multiple issues of type opacity and the possible  
  762. presence of undefined bits and bytes in pthread_t values, which prevent  
  763. applications from comparing or hashing pthread handles.  
  764.   
  765. Two complimentary partial solutions have been proposed, one an application-level  
  766. scheme to handle both scalar and aggregate pthread_t types equally, plus a  
  767. definition of pthread_t itself that neutralises padding bits and bytes by  
  768. coercing semantics out of the compiler to eliminate variations in the values of  
  769. padding bits.  
  770.   
  771. I have not provided any solution to the problem of handling extra values embedded  
  772. in pthread_t, e.g. debugging or trap information that an implementation is entitled  
  773. to include. Therefore none of this replaces the portability and flexibility of API  
  774. functions but what functions are needed? The threads standard is unlikely to  
  775. include that can be implemented by a combination of existing features and more  
  776. generic functions (several references in the threads rationale suggest this.  
  777. Therefore I propose that the following function could replace the several functions  
  778. that have been suggested in conversations:  
  779.   
  780. pthread_t * pthread_normalize(pthread_t * handle);  
  781.   
  782. For most existing pthreads implementations this function, or macro, would reduce to  
  783. a no-op with zero call overhead.  

4 QueueUserAPCEx编译

由于VS2013 + WDK 8.1 Update编译驱动的方式我还没有搞清楚,以后补上。

5 pthread通用初始化头文件

对于pthread_win32的使用我提供一个通用的初始化文件“cruise_ptw32_static_init.h”,如下
[cpp]  view plain  copy
 print ?
  1. #ifndef CRUISE_PTW32_STATIC_INIT_H  
  2. #define CRUISE_PTW32_STATIC_INIT_H  
  3.   
  4. #ifdef PTW32_STATIC_LIB  
  5. #include   
  6. #include   
  7. #endif  
  8.   
  9.   
  10. static void ptw32_enable_cancel(void)  
  11. {  
  12. #ifdef PTW32_STATIC_LIB  
  13.     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);  
  14.     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);  
  15. #endif  
  16. }  
  17. #define CRUISE_PTW32_ENABLE_CANCEL()    {ptw32_enable_cancel();}  
  18.   
  19.   
  20. static void ptw32_attach(void)  
  21. {  
  22. #ifdef PTW32_STATIC_LIB  
  23.     pthread_win32_process_attach_np();  
  24.     pthread_win32_thread_attach_np();  
  25. #endif  
  26. }  
  27.   
  28.   
  29. static void ptw32_detach(void)  
  30. {  
  31. #ifdef PTW32_STATIC_LIB  
  32.     pthread_win32_thread_detach_np();  
  33.     pthread_win32_process_detach_np();  
  34. #endif  
  35. }  
  36.   
  37.   
  38. #if defined(_WIN32) && defined(PTW32_STATIC_LIB)   
  39. #define CRUISE_PTW32_INIT()                                     \  
  40. {                                                               \  
  41.     attach_ptw32();                                             \  
  42.     atexit((P_ATEXIT_PROC)detach_ptw32);                        \  
  43. }  
  44. #else  
  45. #define CRUISE_PTW32_INIT()  
  46. #endif  
  47.   
  48.   
  49. #endif // CRUISE_PTW32_STATIC_INIT_H  

6 参考资料

pthread学习
http://www.cppblog.com/saha/articles/189802.html
pthread_win32下的 pthread_t与posix的pthread_t的不同
http://www.cnblogs.com/ayanmw/archive/2012/08/07/2626661.html
pthread 静态编译版本在Windows下使用时的注意事项
http://blog.csdn.net/psusong/article/details/5189659
64位win7 vs2010 pthread的配置 - - ITeye技术网站
http://houyingsoft.iteye.com/blog/1907670
跨平台多线程
http://shenan1984.blog.163.com/blog/static/2530851020098231001787/
QueueUserAPCEx版本2:真正的异步通知用户模式在Windows平台上
http://www.orcode.com/article/Processes_20117249.html
跨平台多线程编程-fychit-ChinaUnix博客
http://blog.chinaunix.net/uid-20776117-id-1847029.html
跨平台多线程库pthread
http://blog.csdn.net/yinyhy/article/details/10959997
pthread-win32静态库的编译和使用方法
http://download.csdn.net/detail/eugenelyq/3604896
/MinGW/Base/pthreads-w32/pthreads-w32-2.9.0-pre-20110507-2
http://sourceforge.net/projects/mingw/files/MinGW/Base/pthreads-w32/pthreads-w32-2.9.0-pre-20110507-2/

你可能感兴趣的:(pthread)