Ticket #2575: thread_primitives.hpp

File thread_primitives.hpp, 13.2 KB (added by asonawane@…, 11 years ago)

itanium patch

Line 
1#ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP
2#define BOOST_WIN32_THREAD_PRIMITIVES_HPP
3
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)
12
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>
18
19#if defined( BOOST_USE_WINDOWS_H )
20# include <windows.h>
21
22namespace boost
23{
24 namespace detail
25 {
26 namespace win32
27 {
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;
33
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;
59 }
60 }
61}
62#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
63
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
72
73# ifdef __cplusplus
74extern "C" {
75# endif
76typedef int BOOL;
77typedef unsigned long DWORD;
78typedef void* HANDLE;
79
80# include <kfuncs.h>
81# ifdef __cplusplus
82}
83# endif
84# endif
85
86namespace boost
87{
88 namespace detail
89 {
90 namespace win32
91 {
92
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);
102
103 extern "C"
104 {
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);
125
126 __declspec(dllimport) unsigned long __stdcall GetTickCount();
127
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
143 }
144 }
145 }
146}
147#else
148# error "Win32 functions not available"
149#endif
150
151#include <boost/config/abi_prefix.hpp>
152
153namespace boost
154{
155 namespace detail
156 {
157 namespace win32
158 {
159 enum event_type
160 {
161 auto_reset_event=false,
162 manual_reset_event=true
163 };
164
165 enum initial_event_state
166 {
167 event_initially_reset=false,
168 event_initially_set=true
169 };
170
171 inline handle create_anonymous_event(event_type type,initial_event_state state)
172 {
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)
179 {
180 throw thread_resource_error();
181 }
182 return res;
183 }
184
185 inline handle create_anonymous_semaphore(long initial_count,long max_count)
186 {
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)
193 {
194 throw thread_resource_error();
195 }
196 return res;
197 }
198
199 inline handle duplicate_handle(handle source)
200 {
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)
206 {
207 throw thread_resource_error();
208 }
209 return new_handle;
210 }
211
212 inline void release_semaphore(handle semaphore,long count)
213 {
214 BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
215 }
216
217 class handle_manager
218 {
219 private:
220 handle handle_to_manage;
221 handle_manager(handle_manager&);
222 handle_manager& operator=(handle_manager&);
223
224 void cleanup()
225 {
226 if(handle_to_manage && handle_to_manage!=invalid_handle_value)
227 {
228 BOOST_VERIFY(CloseHandle(handle_to_manage));
229 }
230 }
231
232 public:
233 explicit handle_manager(handle handle_to_manage_):
234 handle_to_manage(handle_to_manage_)
235 {}
236 handle_manager():
237 handle_to_manage(0)
238 {}
239
240 handle_manager& operator=(handle new_handle)
241 {
242 cleanup();
243 handle_to_manage=new_handle;
244 return *this;
245 }
246
247 operator handle() const
248 {
249 return handle_to_manage;
250 }
251
252 handle duplicate() const
253 {
254 return duplicate_handle(handle_to_manage);
255 }
256
257 void swap(handle_manager& other)
258 {
259 std::swap(handle_to_manage,other.handle_to_manage);
260 }
261
262 handle release()
263 {
264 handle const res=handle_to_manage;
265 handle_to_manage=0;
266 return res;
267 }
268
269 bool operator!() const
270 {
271 return !handle_to_manage;
272 }
273
274 ~handle_manager()
275 {
276 cleanup();
277 }
278 };
279
280 }
281 }
282}
283
284#if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE)
285
286namespace boost
287{
288 namespace detail
289 {
290 namespace win32
291 {
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
299
300#if !defined(_M_IA64)
301#pragma intrinsic(_interlockedbittestandset)
302#pragma intrinsic(_interlockedbittestandreset)
303
304 inline bool interlocked_bit_test_and_set(long* x,long bit)
305 {
306 return _interlockedbittestandset(x,bit)!=0;
307 }
308
309 inline bool interlocked_bit_test_and_reset(long* x,long bit)
310 {
311 return _interlockedbittestandreset(x,bit)!=0;
312 }
313#else
314 inline bool interlocked_bit_test_and_set(long* x,long bit)
315 {
316 return InterlockedBitTestAndSet(x,bit)!=0;
317 }
318
319 inline bool interlocked_bit_test_and_reset(long* x,long bit)
320 {
321 return InterlockedBitTestAndReset(x,bit)!=0;
322 }
323#endif
324 }
325 }
326}
327#define BOOST_THREAD_BTS_DEFINED
328#elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86)
329namespace boost
330{
331 namespace detail
332 {
333 namespace win32
334 {
335 inline bool interlocked_bit_test_and_set(long* x,long bit)
336 {
337 __asm {
338 mov eax,bit;
339 mov edx,x;
340 lock bts [edx],eax;
341 setc al;
342 };
343 }
344
345 inline bool interlocked_bit_test_and_reset(long* x,long bit)
346 {
347 __asm {
348 mov eax,bit;
349 mov edx,x;
350 lock btr [edx],eax;
351 setc al;
352 };
353 }
354
355 }
356 }
357}
358#elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IA64)
359namespace boost
360{
361 namespace detail
362 {
363 namespace win32
364 {
365 inline bool interlocked_bit_test_and_set(long* x,long bit)
366 {
367 InterlockedBitTestAndSet(x,bit);
368 }
369
370 inline bool interlocked_bit_test_and_reset(long* x,long bit)
371 {
372 InterlockedBitTestAndReset(x,bit);
373 }
374 }
375 }
376}
377#define BOOST_THREAD_BTS_DEFINED
378#endif
379
380#ifndef BOOST_THREAD_BTS_DEFINED
381
382namespace 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
405 inline bool interlocked_bit_test_and_reset(long* x,long bit)
406 {
407 long const value=1<<bit;
408 long old=*x;
409 do
410 {
411 long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old);
412 if(current==old)
413 {
414 break;
415 }
416 old=current;
417 }
418 while(true);
419 return (old&value)!=0;
420 }
421 }
422 }
423}
424#endif
425
426#include <boost/config/abi_suffix.hpp>
427
428#endif