fix doc example typo
[boost.git] / boost / thread / win32 / thread_primitives.hpp
blob67a1bc3cb2a3c2479109df8b50c71411ead895fe
1 #ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP
2 #define BOOST_WIN32_THREAD_PRIMITIVES_HPP
4 // win32_thread_primitives.hpp
5 //
6 // (C) Copyright 2005-7 Anthony Williams
7 // (C) Copyright 2007 David Deakins
8 //
9 // Distributed under the Boost Software License, Version 1.0. (See
10 // accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
13 #include <boost/config.hpp>
14 #include <boost/assert.hpp>
15 #include <boost/thread/exceptions.hpp>
16 #include <boost/detail/interlocked.hpp>
17 #include <algorithm>
19 #if defined( BOOST_USE_WINDOWS_H )
20 # include <windows.h>
22 namespace boost
24 namespace detail
26 namespace win32
28 typedef ULONG_PTR ulong_ptr;
29 typedef HANDLE handle;
30 unsigned const infinite=INFINITE;
31 unsigned const timeout=WAIT_TIMEOUT;
32 handle const invalid_handle_value=INVALID_HANDLE_VALUE;
34 # ifdef BOOST_NO_ANSI_APIS
35 using ::CreateMutexW;
36 using ::CreateEventW;
37 using ::CreateSemaphoreW;
38 # else
39 using ::CreateMutexA;
40 using ::CreateEventA;
41 using ::CreateSemaphoreA;
42 # endif
43 using ::CloseHandle;
44 using ::ReleaseMutex;
45 using ::ReleaseSemaphore;
46 using ::SetEvent;
47 using ::ResetEvent;
48 using ::WaitForMultipleObjects;
49 using ::WaitForSingleObject;
50 using ::GetCurrentProcessId;
51 using ::GetCurrentThreadId;
52 using ::GetCurrentThread;
53 using ::GetCurrentProcess;
54 using ::DuplicateHandle;
55 using ::SleepEx;
56 using ::Sleep;
57 using ::QueueUserAPC;
58 using ::GetTickCount;
62 #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
64 # ifdef UNDER_CE
65 # ifndef WINAPI
66 # ifndef _WIN32_WCE_EMULATION
67 # define WINAPI __cdecl // Note this doesn't match the desktop definition
68 # else
69 # define WINAPI __stdcall
70 # endif
71 # endif
73 # ifdef __cplusplus
74 extern "C" {
75 # endif
76 typedef int BOOL;
77 typedef unsigned long DWORD;
78 typedef void* HANDLE;
80 # include <kfuncs.h>
81 # ifdef __cplusplus
83 # endif
84 # endif
86 namespace boost
88 namespace detail
90 namespace win32
93 # ifdef _WIN64
94 typedef unsigned __int64 ulong_ptr;
95 # else
96 typedef unsigned long ulong_ptr;
97 # endif
98 typedef void* handle;
99 unsigned const infinite=~0U;
100 unsigned const timeout=258U;
101 handle const invalid_handle_value=(handle)(-1);
103 extern "C"
105 struct _SECURITY_ATTRIBUTES;
106 # ifdef BOOST_NO_ANSI_APIS
107 __declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
108 __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
109 __declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
110 # else
111 __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
112 __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
113 __declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
114 # endif
115 __declspec(dllimport) int __stdcall CloseHandle(void*);
116 __declspec(dllimport) int __stdcall ReleaseMutex(void*);
117 __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long);
118 __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
119 __declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
120 __declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
121 __declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
122 __declspec(dllimport) void __stdcall Sleep(unsigned long);
123 typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
124 __declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
126 __declspec(dllimport) unsigned long __stdcall GetTickCount();
128 # ifndef UNDER_CE
129 __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
130 __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
131 __declspec(dllimport) void* __stdcall GetCurrentThread();
132 __declspec(dllimport) void* __stdcall GetCurrentProcess();
133 __declspec(dllimport) int __stdcall SetEvent(void*);
134 __declspec(dllimport) int __stdcall ResetEvent(void*);
135 # else
136 using ::GetCurrentProcessId;
137 using ::GetCurrentThreadId;
138 using ::GetCurrentThread;
139 using ::GetCurrentProcess;
140 using ::SetEvent;
141 using ::ResetEvent;
142 # endif
147 #else
148 # error "Win32 functions not available"
149 #endif
151 #include <boost/config/abi_prefix.hpp>
153 namespace boost
155 namespace detail
157 namespace win32
159 enum event_type
161 auto_reset_event=false,
162 manual_reset_event=true
165 enum initial_event_state
167 event_initially_reset=false,
168 event_initially_set=true
171 inline handle create_anonymous_event(event_type type,initial_event_state state)
173 #if !defined(BOOST_NO_ANSI_APIS)
174 handle const res=win32::CreateEventA(0,type,state,0);
175 #else
176 handle const res=win32::CreateEventW(0,type,state,0);
177 #endif
178 if(!res)
180 throw thread_resource_error();
182 return res;
185 inline handle create_anonymous_semaphore(long initial_count,long max_count)
187 #if !defined(BOOST_NO_ANSI_APIS)
188 handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
189 #else
190 handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
191 #endif
192 if(!res)
194 throw thread_resource_error();
196 return res;
199 inline handle duplicate_handle(handle source)
201 handle const current_process=GetCurrentProcess();
202 long const same_access_flag=2;
203 handle new_handle=0;
204 bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
205 if(!success)
207 throw thread_resource_error();
209 return new_handle;
212 inline void release_semaphore(handle semaphore,long count)
214 BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
217 class handle_manager
219 private:
220 handle handle_to_manage;
221 handle_manager(handle_manager&);
222 handle_manager& operator=(handle_manager&);
224 void cleanup()
226 if(handle_to_manage && handle_to_manage!=invalid_handle_value)
228 BOOST_VERIFY(CloseHandle(handle_to_manage));
232 public:
233 explicit handle_manager(handle handle_to_manage_):
234 handle_to_manage(handle_to_manage_)
236 handle_manager():
237 handle_to_manage(0)
240 handle_manager& operator=(handle new_handle)
242 cleanup();
243 handle_to_manage=new_handle;
244 return *this;
247 operator handle() const
249 return handle_to_manage;
252 handle duplicate() const
254 return duplicate_handle(handle_to_manage);
257 void swap(handle_manager& other)
259 std::swap(handle_to_manage,other.handle_to_manage);
262 handle release()
264 handle const res=handle_to_manage;
265 handle_to_manage=0;
266 return res;
269 bool operator!() const
271 return !handle_to_manage;
274 ~handle_manager()
276 cleanup();
284 #if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE)
286 namespace boost
288 namespace detail
290 namespace win32
292 #if _MSC_VER==1400
293 extern "C" unsigned char _interlockedbittestandset(long *a,long b);
294 extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
295 #else
296 extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b);
297 extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b);
298 #endif
300 #pragma intrinsic(_interlockedbittestandset)
301 #pragma intrinsic(_interlockedbittestandreset)
303 inline bool interlocked_bit_test_and_set(long* x,long bit)
305 return _interlockedbittestandset(x,bit)!=0;
308 inline bool interlocked_bit_test_and_reset(long* x,long bit)
310 return _interlockedbittestandreset(x,bit)!=0;
316 #define BOOST_THREAD_BTS_DEFINED
317 #elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86)
318 namespace boost
320 namespace detail
322 namespace win32
324 inline bool interlocked_bit_test_and_set(long* x,long bit)
326 __asm {
327 mov eax,bit;
328 mov edx,x;
329 lock bts [edx],eax;
330 setc al;
334 inline bool interlocked_bit_test_and_reset(long* x,long bit)
336 __asm {
337 mov eax,bit;
338 mov edx,x;
339 lock btr [edx],eax;
340 setc al;
347 #define BOOST_THREAD_BTS_DEFINED
348 #endif
350 #ifndef BOOST_THREAD_BTS_DEFINED
352 namespace boost
354 namespace detail
356 namespace win32
358 inline bool interlocked_bit_test_and_set(long* x,long bit)
360 long const value=1<<bit;
361 long old=*x;
364 long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old);
365 if(current==old)
367 break;
369 old=current;
371 while(true);
372 return (old&value)!=0;
375 inline bool interlocked_bit_test_and_reset(long* x,long bit)
377 long const value=1<<bit;
378 long old=*x;
381 long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old);
382 if(current==old)
384 break;
386 old=current;
388 while(true);
389 return (old&value)!=0;
394 #endif
396 #include <boost/config/abi_suffix.hpp>
398 #endif