thread_primitives.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. #ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP
  2. #define BOOST_WIN32_THREAD_PRIMITIVES_HPP
  3. // win32_thread_primitives.hpp
  4. //
  5. // (C) Copyright 2005-7 Anthony Williams
  6. // (C) Copyright 2007 David Deakins
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See
  9. // accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. #include <boost/thread/detail/config.hpp>
  12. #include <boost/throw_exception.hpp>
  13. #include <boost/assert.hpp>
  14. #include <boost/thread/exceptions.hpp>
  15. #include <boost/detail/interlocked.hpp>
  16. //#include <boost/detail/winapi/synchronization.hpp>
  17. #include <algorithm>
  18. #ifndef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
  19. #if _WIN32_WINNT >= 0x0600 && ! defined _WIN32_WINNT_WS08
  20. #define BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
  21. #endif
  22. #endif
  23. #if defined( BOOST_USE_WINDOWS_H )
  24. # include <windows.h>
  25. namespace boost
  26. {
  27. namespace detail
  28. {
  29. namespace win32
  30. {
  31. #ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
  32. typedef unsigned long long ticks_type;
  33. #else
  34. typedef unsigned long ticks_type;
  35. #endif
  36. typedef ULONG_PTR ulong_ptr;
  37. typedef HANDLE handle;
  38. unsigned const infinite=INFINITE;
  39. unsigned const timeout=WAIT_TIMEOUT;
  40. handle const invalid_handle_value=INVALID_HANDLE_VALUE;
  41. unsigned const event_modify_state=EVENT_MODIFY_STATE;
  42. unsigned const synchronize=SYNCHRONIZE;
  43. unsigned const wait_abandoned=WAIT_ABANDONED;
  44. # ifdef BOOST_NO_ANSI_APIS
  45. using ::CreateMutexW;
  46. using ::CreateEventW;
  47. using ::OpenEventW;
  48. using ::CreateSemaphoreW;
  49. # else
  50. using ::CreateMutexA;
  51. using ::CreateEventA;
  52. using ::OpenEventA;
  53. using ::CreateSemaphoreA;
  54. # endif
  55. using ::CloseHandle;
  56. using ::ReleaseMutex;
  57. using ::ReleaseSemaphore;
  58. using ::SetEvent;
  59. using ::ResetEvent;
  60. using ::WaitForMultipleObjects;
  61. using ::WaitForSingleObject;
  62. using ::GetCurrentProcessId;
  63. using ::GetCurrentThreadId;
  64. using ::GetCurrentThread;
  65. using ::GetCurrentProcess;
  66. using ::DuplicateHandle;
  67. using ::SleepEx;
  68. using ::Sleep;
  69. using ::QueueUserAPC;
  70. using ::GetTickCount;
  71. #ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
  72. using ::GetTickCount64;
  73. #else
  74. inline ticks_type GetTickCount64() { return GetTickCount(); }
  75. #endif
  76. }
  77. }
  78. }
  79. #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
  80. # ifdef UNDER_CE
  81. # ifndef WINAPI
  82. # ifndef _WIN32_WCE_EMULATION
  83. # define WINAPI __cdecl // Note this doesn't match the desktop definition
  84. # else
  85. # define WINAPI __stdcall
  86. # endif
  87. # endif
  88. # ifdef __cplusplus
  89. extern "C" {
  90. # endif
  91. typedef int BOOL;
  92. typedef unsigned long DWORD;
  93. typedef void* HANDLE;
  94. # include <kfuncs.h>
  95. # ifdef __cplusplus
  96. }
  97. # endif
  98. # endif
  99. namespace boost
  100. {
  101. namespace detail
  102. {
  103. namespace win32
  104. {
  105. #ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
  106. typedef unsigned long long ticks_type;
  107. #else
  108. typedef unsigned long ticks_type;
  109. #endif
  110. # ifdef _WIN64
  111. typedef unsigned __int64 ulong_ptr;
  112. # else
  113. typedef unsigned long ulong_ptr;
  114. # endif
  115. typedef void* handle;
  116. unsigned const infinite=~0U;
  117. unsigned const timeout=258U;
  118. handle const invalid_handle_value=(handle)(-1);
  119. unsigned const event_modify_state=2;
  120. unsigned const synchronize=0x100000u;
  121. unsigned const wait_abandoned=0x00000080u;
  122. extern "C"
  123. {
  124. struct _SECURITY_ATTRIBUTES;
  125. # ifdef BOOST_NO_ANSI_APIS
  126. __declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
  127. __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
  128. __declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
  129. __declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
  130. # else
  131. __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
  132. __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
  133. __declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
  134. __declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
  135. # endif
  136. __declspec(dllimport) int __stdcall CloseHandle(void*);
  137. __declspec(dllimport) int __stdcall ReleaseMutex(void*);
  138. __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long);
  139. __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
  140. __declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
  141. __declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
  142. __declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
  143. __declspec(dllimport) void __stdcall Sleep(unsigned long);
  144. typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
  145. __declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
  146. __declspec(dllimport) unsigned long __stdcall GetTickCount();
  147. # ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
  148. __declspec(dllimport) ticks_type __stdcall GetTickCount64();
  149. # endif
  150. # ifndef UNDER_CE
  151. __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
  152. __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
  153. __declspec(dllimport) void* __stdcall GetCurrentThread();
  154. __declspec(dllimport) void* __stdcall GetCurrentProcess();
  155. __declspec(dllimport) int __stdcall SetEvent(void*);
  156. __declspec(dllimport) int __stdcall ResetEvent(void*);
  157. # else
  158. using ::GetCurrentProcessId;
  159. using ::GetCurrentThreadId;
  160. using ::GetCurrentThread;
  161. using ::GetCurrentProcess;
  162. using ::SetEvent;
  163. using ::ResetEvent;
  164. # endif
  165. }
  166. # ifndef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
  167. inline ticks_type GetTickCount64() { return GetTickCount(); }
  168. # endif
  169. }
  170. }
  171. }
  172. #else
  173. # error "Win32 functions not available"
  174. #endif
  175. #include <boost/config/abi_prefix.hpp>
  176. namespace boost
  177. {
  178. namespace detail
  179. {
  180. namespace win32
  181. {
  182. enum event_type
  183. {
  184. auto_reset_event=false,
  185. manual_reset_event=true
  186. };
  187. enum initial_event_state
  188. {
  189. event_initially_reset=false,
  190. event_initially_set=true
  191. };
  192. inline handle create_anonymous_event(event_type type,initial_event_state state)
  193. {
  194. #if !defined(BOOST_NO_ANSI_APIS)
  195. handle const res=win32::CreateEventA(0,type,state,0);
  196. #else
  197. handle const res=win32::CreateEventW(0,type,state,0);
  198. #endif
  199. if(!res)
  200. {
  201. boost::throw_exception(thread_resource_error());
  202. }
  203. return res;
  204. }
  205. inline handle create_anonymous_semaphore(long initial_count,long max_count)
  206. {
  207. #if !defined(BOOST_NO_ANSI_APIS)
  208. handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
  209. #else
  210. handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
  211. #endif
  212. if(!res)
  213. {
  214. boost::throw_exception(thread_resource_error());
  215. }
  216. return res;
  217. }
  218. inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
  219. {
  220. #if !defined(BOOST_NO_ANSI_APIS)
  221. handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
  222. #else
  223. handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
  224. #endif
  225. return res;
  226. }
  227. inline handle duplicate_handle(handle source)
  228. {
  229. handle const current_process=GetCurrentProcess();
  230. long const same_access_flag=2;
  231. handle new_handle=0;
  232. bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
  233. if(!success)
  234. {
  235. boost::throw_exception(thread_resource_error());
  236. }
  237. return new_handle;
  238. }
  239. inline void release_semaphore(handle semaphore,long count)
  240. {
  241. BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
  242. }
  243. class BOOST_THREAD_DECL handle_manager
  244. {
  245. private:
  246. handle handle_to_manage;
  247. handle_manager(handle_manager&);
  248. handle_manager& operator=(handle_manager&);
  249. void cleanup()
  250. {
  251. if(handle_to_manage && handle_to_manage!=invalid_handle_value)
  252. {
  253. BOOST_VERIFY(CloseHandle(handle_to_manage));
  254. }
  255. }
  256. public:
  257. explicit handle_manager(handle handle_to_manage_):
  258. handle_to_manage(handle_to_manage_)
  259. {}
  260. handle_manager():
  261. handle_to_manage(0)
  262. {}
  263. handle_manager& operator=(handle new_handle)
  264. {
  265. cleanup();
  266. handle_to_manage=new_handle;
  267. return *this;
  268. }
  269. operator handle() const
  270. {
  271. return handle_to_manage;
  272. }
  273. handle duplicate() const
  274. {
  275. return duplicate_handle(handle_to_manage);
  276. }
  277. void swap(handle_manager& other)
  278. {
  279. std::swap(handle_to_manage,other.handle_to_manage);
  280. }
  281. handle release()
  282. {
  283. handle const res=handle_to_manage;
  284. handle_to_manage=0;
  285. return res;
  286. }
  287. bool operator!() const
  288. {
  289. return !handle_to_manage;
  290. }
  291. ~handle_manager()
  292. {
  293. cleanup();
  294. }
  295. };
  296. }
  297. }
  298. }
  299. #if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE)
  300. namespace boost
  301. {
  302. namespace detail
  303. {
  304. namespace win32
  305. {
  306. #if _MSC_VER==1400
  307. extern "C" unsigned char _interlockedbittestandset(long *a,long b);
  308. extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
  309. #else
  310. extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b);
  311. extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b);
  312. #endif
  313. #pragma intrinsic(_interlockedbittestandset)
  314. #pragma intrinsic(_interlockedbittestandreset)
  315. inline bool interlocked_bit_test_and_set(long* x,long bit)
  316. {
  317. return _interlockedbittestandset(x,bit)!=0;
  318. }
  319. inline bool interlocked_bit_test_and_reset(long* x,long bit)
  320. {
  321. return _interlockedbittestandreset(x,bit)!=0;
  322. }
  323. }
  324. }
  325. }
  326. #define BOOST_THREAD_BTS_DEFINED
  327. #elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86)
  328. namespace boost
  329. {
  330. namespace detail
  331. {
  332. namespace win32
  333. {
  334. inline bool interlocked_bit_test_and_set(long* x,long bit)
  335. {
  336. #ifndef BOOST_INTEL_CXX_VERSION
  337. __asm {
  338. mov eax,bit;
  339. mov edx,x;
  340. lock bts [edx],eax;
  341. setc al;
  342. };
  343. #else
  344. bool ret;
  345. __asm {
  346. mov eax,bit
  347. mov edx,x
  348. lock bts [edx],eax
  349. setc al
  350. mov ret, al
  351. };
  352. return ret;
  353. #endif
  354. }
  355. inline bool interlocked_bit_test_and_reset(long* x,long bit)
  356. {
  357. #ifndef BOOST_INTEL_CXX_VERSION
  358. __asm {
  359. mov eax,bit;
  360. mov edx,x;
  361. lock btr [edx],eax;
  362. setc al;
  363. };
  364. #else
  365. bool ret;
  366. __asm {
  367. mov eax,bit
  368. mov edx,x
  369. lock btr [edx],eax
  370. setc al
  371. mov ret, al
  372. };
  373. return ret;
  374. #endif
  375. }
  376. }
  377. }
  378. }
  379. #define BOOST_THREAD_BTS_DEFINED
  380. #endif
  381. #ifndef BOOST_THREAD_BTS_DEFINED
  382. namespace boost
  383. {
  384. namespace detail
  385. {
  386. namespace win32
  387. {
  388. inline bool interlocked_bit_test_and_set(long* x,long bit)
  389. {
  390. long const value=1<<bit;
  391. long old=*x;
  392. do
  393. {
  394. long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old);
  395. if(current==old)
  396. {
  397. break;
  398. }
  399. old=current;
  400. }
  401. while(true);
  402. return (old&value)!=0;
  403. }
  404. inline bool interlocked_bit_test_and_reset(long* x,long bit)
  405. {
  406. long const value=1<<bit;
  407. long old=*x;
  408. do
  409. {
  410. long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old);
  411. if(current==old)
  412. {
  413. break;
  414. }
  415. old=current;
  416. }
  417. while(true);
  418. return (old&value)!=0;
  419. }
  420. }
  421. }
  422. }
  423. #endif
  424. #include <boost/config/abi_suffix.hpp>
  425. #endif