]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/thread/detail/config.hpp> | |
14 | #include <boost/predef/platform.h> | |
15 | #include <boost/throw_exception.hpp> | |
16 | #include <boost/assert.hpp> | |
17 | #include <boost/thread/exceptions.hpp> | |
18 | #include <boost/detail/interlocked.hpp> | |
19 | #include <boost/detail/winapi/config.hpp> | |
20 | //#include <boost/detail/winapi/synchronization.hpp> | |
21 | #include <algorithm> | |
22 | ||
23 | #if BOOST_PLAT_WINDOWS_RUNTIME | |
24 | #include <thread> | |
25 | #endif | |
26 | ||
27 | #if defined( BOOST_USE_WINDOWS_H ) | |
28 | # include <windows.h> | |
29 | ||
30 | namespace boost | |
31 | { | |
32 | namespace detail | |
33 | { | |
34 | namespace win32 | |
35 | { | |
36 | typedef HANDLE handle; | |
37 | typedef SYSTEM_INFO system_info; | |
38 | typedef unsigned __int64 ticks_type; | |
39 | typedef FARPROC farproc_t; | |
40 | unsigned const infinite=INFINITE; | |
41 | unsigned const timeout=WAIT_TIMEOUT; | |
42 | handle const invalid_handle_value=INVALID_HANDLE_VALUE; | |
43 | unsigned const event_modify_state=EVENT_MODIFY_STATE; | |
44 | unsigned const synchronize=SYNCHRONIZE; | |
45 | unsigned const wait_abandoned=WAIT_ABANDONED; | |
46 | unsigned const create_event_initial_set = 0x00000002; | |
47 | unsigned const create_event_manual_reset = 0x00000001; | |
48 | unsigned const event_all_access = EVENT_ALL_ACCESS; | |
49 | unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS; | |
50 | ||
51 | ||
52 | # ifdef BOOST_NO_ANSI_APIS | |
53 | # if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA | |
54 | using ::CreateMutexW; | |
55 | using ::CreateEventW; | |
56 | using ::CreateSemaphoreW; | |
57 | # else | |
58 | using ::CreateMutexExW; | |
59 | using ::CreateEventExW; | |
60 | using ::CreateSemaphoreExW; | |
61 | # endif | |
62 | using ::OpenEventW; | |
63 | using ::GetModuleHandleW; | |
64 | # else | |
65 | using ::CreateMutexA; | |
66 | using ::CreateEventA; | |
67 | using ::OpenEventA; | |
68 | using ::CreateSemaphoreA; | |
69 | using ::GetModuleHandleA; | |
70 | # endif | |
71 | #if BOOST_PLAT_WINDOWS_RUNTIME | |
72 | using ::GetNativeSystemInfo; | |
73 | using ::GetTickCount64; | |
74 | #else | |
75 | using ::GetSystemInfo; | |
76 | using ::GetTickCount; | |
77 | #endif | |
78 | using ::CloseHandle; | |
79 | using ::ReleaseMutex; | |
80 | using ::ReleaseSemaphore; | |
81 | using ::SetEvent; | |
82 | using ::ResetEvent; | |
83 | using ::WaitForMultipleObjectsEx; | |
84 | using ::WaitForSingleObjectEx; | |
85 | using ::GetCurrentProcessId; | |
86 | using ::GetCurrentThreadId; | |
87 | using ::GetCurrentThread; | |
88 | using ::GetCurrentProcess; | |
89 | using ::DuplicateHandle; | |
90 | #if !BOOST_PLAT_WINDOWS_RUNTIME | |
91 | using ::SleepEx; | |
92 | using ::Sleep; | |
93 | using ::QueueUserAPC; | |
94 | using ::GetProcAddress; | |
95 | #endif | |
96 | } | |
97 | } | |
98 | } | |
99 | #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) | |
100 | ||
101 | # ifdef UNDER_CE | |
102 | # ifndef WINAPI | |
103 | # ifndef _WIN32_WCE_EMULATION | |
104 | # define WINAPI __cdecl // Note this doesn't match the desktop definition | |
105 | # else | |
106 | # define WINAPI __stdcall | |
107 | # endif | |
108 | # endif | |
109 | ||
110 | # ifdef __cplusplus | |
111 | extern "C" { | |
112 | # endif | |
113 | typedef int BOOL; | |
114 | typedef unsigned long DWORD; | |
115 | typedef void* HANDLE; | |
116 | # include <kfuncs.h> | |
117 | # ifdef __cplusplus | |
118 | } | |
119 | # endif | |
120 | # endif | |
121 | ||
122 | # ifdef __cplusplus | |
123 | extern "C" { | |
124 | # endif | |
125 | struct _SYSTEM_INFO; | |
126 | # ifdef __cplusplus | |
127 | } | |
128 | #endif | |
129 | ||
130 | namespace boost | |
131 | { | |
132 | namespace detail | |
133 | { | |
134 | namespace win32 | |
135 | { | |
136 | # ifdef _WIN64 | |
137 | typedef unsigned __int64 ulong_ptr; | |
138 | # else | |
139 | typedef unsigned long ulong_ptr; | |
140 | # endif | |
141 | typedef void* handle; | |
142 | typedef _SYSTEM_INFO system_info; | |
143 | typedef unsigned __int64 ticks_type; | |
144 | typedef int (__stdcall *farproc_t)(); | |
145 | unsigned const infinite=~0U; | |
146 | unsigned const timeout=258U; | |
147 | handle const invalid_handle_value=(handle)(-1); | |
148 | unsigned const event_modify_state=2; | |
149 | unsigned const synchronize=0x100000u; | |
150 | unsigned const wait_abandoned=0x00000080u; | |
151 | unsigned const create_event_initial_set = 0x00000002; | |
152 | unsigned const create_event_manual_reset = 0x00000001; | |
153 | unsigned const event_all_access = 0x1F0003; | |
154 | unsigned const semaphore_all_access = 0x1F0003; | |
155 | ||
156 | extern "C" | |
157 | { | |
158 | struct _SECURITY_ATTRIBUTES; | |
159 | # ifdef BOOST_NO_ANSI_APIS | |
160 | # if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA | |
161 | __declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*); | |
162 | __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*); | |
163 | __declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*); | |
164 | # else | |
165 | __declspec(dllimport) void* __stdcall CreateMutexExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long); | |
166 | __declspec(dllimport) void* __stdcall CreateEventExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long); | |
167 | __declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long); | |
168 | # endif | |
169 | __declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*); | |
170 | __declspec(dllimport) void* __stdcall GetModuleHandleW(wchar_t const*); | |
171 | # else | |
172 | __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*); | |
173 | __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*); | |
174 | __declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*); | |
175 | __declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*); | |
176 | __declspec(dllimport) void* __stdcall GetModuleHandleA(char const*); | |
177 | # endif | |
178 | #if BOOST_PLAT_WINDOWS_RUNTIME | |
179 | __declspec(dllimport) void __stdcall GetNativeSystemInfo(_SYSTEM_INFO*); | |
180 | __declspec(dllimport) ticks_type __stdcall GetTickCount64(); | |
181 | #else | |
182 | __declspec(dllimport) void __stdcall GetSystemInfo(_SYSTEM_INFO*); | |
183 | __declspec(dllimport) unsigned long __stdcall GetTickCount(); | |
184 | #endif | |
185 | __declspec(dllimport) int __stdcall CloseHandle(void*); | |
186 | __declspec(dllimport) int __stdcall ReleaseMutex(void*); | |
187 | __declspec(dllimport) unsigned long __stdcall WaitForSingleObjectEx(void*,unsigned long,int); | |
188 | __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjectsEx(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds,int bAlertable); | |
189 | __declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*); | |
190 | __declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long); | |
191 | #if !BOOST_PLAT_WINDOWS_RUNTIME | |
192 | __declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int); | |
193 | __declspec(dllimport) void __stdcall Sleep(unsigned long); | |
194 | typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr); | |
195 | __declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr); | |
196 | __declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char *); | |
197 | #endif | |
198 | ||
199 | # ifndef UNDER_CE | |
200 | __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId(); | |
201 | __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(); | |
202 | __declspec(dllimport) void* __stdcall GetCurrentThread(); | |
203 | __declspec(dllimport) void* __stdcall GetCurrentProcess(); | |
204 | __declspec(dllimport) int __stdcall SetEvent(void*); | |
205 | __declspec(dllimport) int __stdcall ResetEvent(void*); | |
206 | # else | |
207 | using ::GetCurrentProcessId; | |
208 | using ::GetCurrentThreadId; | |
209 | using ::GetCurrentThread; | |
210 | using ::GetCurrentProcess; | |
211 | using ::SetEvent; | |
212 | using ::ResetEvent; | |
213 | # endif | |
214 | } | |
215 | } | |
216 | } | |
217 | } | |
218 | #else | |
219 | # error "Win32 functions not available" | |
220 | #endif | |
221 | ||
222 | #include <boost/config/abi_prefix.hpp> | |
223 | ||
224 | namespace boost | |
225 | { | |
226 | namespace detail | |
227 | { | |
228 | namespace win32 | |
229 | { | |
230 | namespace detail { typedef ticks_type (__stdcall *gettickcount64_t)(); } | |
231 | #if !BOOST_PLAT_WINDOWS_RUNTIME | |
232 | extern "C" | |
233 | { | |
234 | #ifdef _MSC_VER | |
235 | long _InterlockedCompareExchange(long volatile *, long, long); | |
236 | #pragma intrinsic(_InterlockedCompareExchange) | |
237 | #elif defined(__MINGW64_VERSION_MAJOR) | |
238 | long _InterlockedCompareExchange(long volatile *, long, long); | |
239 | #else | |
240 | // Mingw doesn't provide intrinsics | |
241 | #define _InterlockedCompareExchange InterlockedCompareExchange | |
242 | #endif | |
243 | } | |
244 | // Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar | |
245 | inline ticks_type __stdcall GetTickCount64emulation() | |
246 | { | |
247 | static volatile long count = 0xFFFFFFFF; | |
248 | unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone; | |
249 | ticks_type current_tick64; | |
250 | ||
251 | previous_count = (unsigned long) _InterlockedCompareExchange(&count, 0, 0); | |
252 | current_tick32 = GetTickCount(); | |
253 | ||
254 | if(previous_count == 0xFFFFFFFF) | |
255 | { | |
256 | // count has never been written | |
257 | unsigned long initial_count; | |
258 | initial_count = current_tick32 >> 28; | |
259 | previous_count = (unsigned long) _InterlockedCompareExchange(&count, initial_count, 0xFFFFFFFF); | |
260 | ||
261 | current_tick64 = initial_count; | |
262 | current_tick64 <<= 28; | |
263 | current_tick64 += current_tick32 & 0x0FFFFFFF; | |
264 | return current_tick64; | |
265 | } | |
266 | ||
267 | previous_count_zone = previous_count & 15; | |
268 | current_tick32_zone = current_tick32 >> 28; | |
269 | ||
270 | if(current_tick32_zone == previous_count_zone) | |
271 | { | |
272 | // The top four bits of the 32-bit tick count haven't changed since count was last written. | |
273 | current_tick64 = previous_count; | |
274 | current_tick64 <<= 28; | |
275 | current_tick64 += current_tick32 & 0x0FFFFFFF; | |
276 | return current_tick64; | |
277 | } | |
278 | ||
279 | if(current_tick32_zone == previous_count_zone + 1 || (current_tick32_zone == 0 && previous_count_zone == 15)) | |
280 | { | |
281 | // The top four bits of the 32-bit tick count have been incremented since count was last written. | |
282 | _InterlockedCompareExchange(&count, previous_count + 1, previous_count); | |
283 | current_tick64 = previous_count + 1; | |
284 | current_tick64 <<= 28; | |
285 | current_tick64 += current_tick32 & 0x0FFFFFFF; | |
286 | return current_tick64; | |
287 | } | |
288 | ||
289 | // Oops, we weren't called often enough, we're stuck | |
290 | return 0xFFFFFFFF; | |
291 | } | |
292 | #else | |
293 | #endif | |
294 | inline detail::gettickcount64_t GetTickCount64_() | |
295 | { | |
296 | static detail::gettickcount64_t gettickcount64impl; | |
297 | if(gettickcount64impl) | |
298 | return gettickcount64impl; | |
299 | ||
300 | // GetTickCount and GetModuleHandle are not allowed in the Windows Runtime, | |
301 | // and kernel32 isn't used in Windows Phone. | |
302 | #if BOOST_PLAT_WINDOWS_RUNTIME | |
303 | gettickcount64impl = &GetTickCount64; | |
304 | #else | |
305 | farproc_t addr=GetProcAddress( | |
306 | #if !defined(BOOST_NO_ANSI_APIS) | |
307 | GetModuleHandleA("KERNEL32.DLL"), | |
308 | #else | |
309 | GetModuleHandleW(L"KERNEL32.DLL"), | |
310 | #endif | |
311 | "GetTickCount64"); | |
312 | if(addr) | |
313 | gettickcount64impl=(detail::gettickcount64_t) addr; | |
314 | else | |
315 | gettickcount64impl=&GetTickCount64emulation; | |
316 | #endif | |
317 | return gettickcount64impl; | |
318 | } | |
319 | ||
320 | enum event_type | |
321 | { | |
322 | auto_reset_event=false, | |
323 | manual_reset_event=true | |
324 | }; | |
325 | ||
326 | enum initial_event_state | |
327 | { | |
328 | event_initially_reset=false, | |
329 | event_initially_set=true | |
330 | }; | |
331 | ||
332 | inline handle create_event( | |
333 | #if !defined(BOOST_NO_ANSI_APIS) | |
334 | const char *mutex_name, | |
335 | #else | |
336 | const wchar_t *mutex_name, | |
337 | #endif | |
338 | event_type type, | |
339 | initial_event_state state) | |
340 | { | |
341 | #if !defined(BOOST_NO_ANSI_APIS) | |
342 | handle const res = win32::CreateEventA(0, type, state, mutex_name); | |
343 | #elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA | |
344 | handle const res = win32::CreateEventW(0, type, state, mutex_name); | |
345 | #else | |
346 | handle const res = win32::CreateEventExW( | |
347 | 0, | |
348 | mutex_name, | |
349 | type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0, | |
350 | event_all_access); | |
351 | #endif | |
352 | return res; | |
353 | } | |
354 | ||
355 | inline handle create_anonymous_event(event_type type,initial_event_state state) | |
356 | { | |
357 | handle const res = create_event(0, type, state); | |
358 | if(!res) | |
359 | { | |
360 | boost::throw_exception(thread_resource_error()); | |
361 | } | |
362 | return res; | |
363 | } | |
364 | ||
365 | inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count) | |
366 | { | |
367 | #if !defined(BOOST_NO_ANSI_APIS) | |
368 | handle const res=win32::CreateSemaphoreA(0,initial_count,max_count,0); | |
369 | #else | |
370 | #if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA | |
371 | handle const res=win32::CreateSemaphoreEx(0,initial_count,max_count,0,0); | |
372 | #else | |
373 | handle const res=win32::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access); | |
374 | #endif | |
375 | #endif | |
376 | return res; | |
377 | } | |
378 | ||
379 | inline handle create_anonymous_semaphore(long initial_count,long max_count) | |
380 | { | |
381 | handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count); | |
382 | if(!res) | |
383 | { | |
384 | boost::throw_exception(thread_resource_error()); | |
385 | } | |
386 | return res; | |
387 | } | |
388 | ||
389 | inline handle duplicate_handle(handle source) | |
390 | { | |
391 | handle const current_process=GetCurrentProcess(); | |
392 | long const same_access_flag=2; | |
393 | handle new_handle=0; | |
394 | bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0; | |
395 | if(!success) | |
396 | { | |
397 | boost::throw_exception(thread_resource_error()); | |
398 | } | |
399 | return new_handle; | |
400 | } | |
401 | ||
402 | inline void release_semaphore(handle semaphore,long count) | |
403 | { | |
404 | BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0); | |
405 | } | |
406 | ||
407 | inline void get_system_info(system_info *info) | |
408 | { | |
409 | #if BOOST_PLAT_WINDOWS_RUNTIME | |
410 | win32::GetNativeSystemInfo(info); | |
411 | #else | |
412 | win32::GetSystemInfo(info); | |
413 | #endif | |
414 | } | |
415 | ||
416 | inline void sleep(unsigned long milliseconds) | |
417 | { | |
418 | if(milliseconds == 0) | |
419 | { | |
420 | #if BOOST_PLAT_WINDOWS_RUNTIME | |
421 | std::this_thread::yield(); | |
422 | #else | |
423 | ::boost::detail::win32::Sleep(0); | |
424 | #endif | |
425 | } | |
426 | else | |
427 | { | |
428 | #if BOOST_PLAT_WINDOWS_RUNTIME | |
429 | ::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0); | |
430 | #else | |
431 | ::boost::detail::win32::Sleep(milliseconds); | |
432 | #endif | |
433 | } | |
434 | } | |
435 | ||
436 | #if BOOST_PLAT_WINDOWS_RUNTIME | |
437 | class BOOST_THREAD_DECL scoped_winrt_thread | |
438 | { | |
439 | public: | |
440 | scoped_winrt_thread() : m_completionHandle(invalid_handle_value) | |
441 | {} | |
442 | ||
443 | ~scoped_winrt_thread() | |
444 | { | |
445 | if (m_completionHandle != ::boost::detail::win32::invalid_handle_value) | |
446 | { | |
447 | CloseHandle(m_completionHandle); | |
448 | } | |
449 | } | |
450 | ||
451 | typedef unsigned(__stdcall * thread_func)(void *); | |
452 | bool start(thread_func address, void *parameter, unsigned int *thrdId); | |
453 | ||
454 | handle waitable_handle() const | |
455 | { | |
456 | BOOST_ASSERT(m_completionHandle != ::boost::detail::win32::invalid_handle_value); | |
457 | return m_completionHandle; | |
458 | } | |
459 | ||
460 | private: | |
461 | handle m_completionHandle; | |
462 | }; | |
463 | #endif | |
464 | class BOOST_THREAD_DECL handle_manager | |
465 | { | |
466 | private: | |
467 | handle handle_to_manage; | |
468 | handle_manager(handle_manager&); | |
469 | handle_manager& operator=(handle_manager&); | |
470 | ||
471 | void cleanup() | |
472 | { | |
473 | if(handle_to_manage && handle_to_manage!=invalid_handle_value) | |
474 | { | |
475 | BOOST_VERIFY(CloseHandle(handle_to_manage)); | |
476 | } | |
477 | } | |
478 | ||
479 | public: | |
480 | explicit handle_manager(handle handle_to_manage_): | |
481 | handle_to_manage(handle_to_manage_) | |
482 | {} | |
483 | handle_manager(): | |
484 | handle_to_manage(0) | |
485 | {} | |
486 | ||
487 | handle_manager& operator=(handle new_handle) | |
488 | { | |
489 | cleanup(); | |
490 | handle_to_manage=new_handle; | |
491 | return *this; | |
492 | } | |
493 | ||
494 | operator handle() const | |
495 | { | |
496 | return handle_to_manage; | |
497 | } | |
498 | ||
499 | handle duplicate() const | |
500 | { | |
501 | return duplicate_handle(handle_to_manage); | |
502 | } | |
503 | ||
504 | void swap(handle_manager& other) | |
505 | { | |
506 | std::swap(handle_to_manage,other.handle_to_manage); | |
507 | } | |
508 | ||
509 | handle release() | |
510 | { | |
511 | handle const res=handle_to_manage; | |
512 | handle_to_manage=0; | |
513 | return res; | |
514 | } | |
515 | ||
516 | bool operator!() const | |
517 | { | |
518 | return !handle_to_manage; | |
519 | } | |
520 | ||
521 | ~handle_manager() | |
522 | { | |
523 | cleanup(); | |
524 | } | |
525 | }; | |
526 | } | |
527 | } | |
528 | } | |
529 | ||
530 | #if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE) | |
531 | ||
532 | namespace boost | |
533 | { | |
534 | namespace detail | |
535 | { | |
536 | namespace win32 | |
537 | { | |
538 | #if _MSC_VER==1400 | |
539 | extern "C" unsigned char _interlockedbittestandset(long *a,long b); | |
540 | extern "C" unsigned char _interlockedbittestandreset(long *a,long b); | |
541 | #else | |
542 | extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b); | |
543 | extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b); | |
544 | #endif | |
545 | ||
546 | #pragma intrinsic(_interlockedbittestandset) | |
547 | #pragma intrinsic(_interlockedbittestandreset) | |
548 | ||
549 | inline bool interlocked_bit_test_and_set(long* x,long bit) | |
550 | { | |
551 | return _interlockedbittestandset(x,bit)!=0; | |
552 | } | |
553 | ||
554 | inline bool interlocked_bit_test_and_reset(long* x,long bit) | |
555 | { | |
556 | return _interlockedbittestandreset(x,bit)!=0; | |
557 | } | |
558 | ||
559 | } | |
560 | } | |
561 | } | |
562 | #define BOOST_THREAD_BTS_DEFINED | |
563 | #elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86) | |
564 | namespace boost | |
565 | { | |
566 | namespace detail | |
567 | { | |
568 | namespace win32 | |
569 | { | |
570 | inline bool interlocked_bit_test_and_set(long* x,long bit) | |
571 | { | |
572 | #ifndef BOOST_INTEL_CXX_VERSION | |
573 | __asm { | |
574 | mov eax,bit; | |
575 | mov edx,x; | |
576 | lock bts [edx],eax; | |
577 | setc al; | |
578 | }; | |
579 | #else | |
580 | bool ret; | |
581 | __asm { | |
582 | mov eax,bit | |
583 | mov edx,x | |
584 | lock bts [edx],eax | |
585 | setc al | |
586 | mov ret, al | |
587 | }; | |
588 | return ret; | |
589 | ||
590 | #endif | |
591 | } | |
592 | ||
593 | inline bool interlocked_bit_test_and_reset(long* x,long bit) | |
594 | { | |
595 | #ifndef BOOST_INTEL_CXX_VERSION | |
596 | __asm { | |
597 | mov eax,bit; | |
598 | mov edx,x; | |
599 | lock btr [edx],eax; | |
600 | setc al; | |
601 | }; | |
602 | #else | |
603 | bool ret; | |
604 | __asm { | |
605 | mov eax,bit | |
606 | mov edx,x | |
607 | lock btr [edx],eax | |
608 | setc al | |
609 | mov ret, al | |
610 | }; | |
611 | return ret; | |
612 | ||
613 | #endif | |
614 | } | |
615 | ||
616 | } | |
617 | } | |
618 | } | |
619 | #define BOOST_THREAD_BTS_DEFINED | |
620 | #endif | |
621 | ||
622 | #ifndef BOOST_THREAD_BTS_DEFINED | |
623 | ||
624 | namespace boost | |
625 | { | |
626 | namespace detail | |
627 | { | |
628 | namespace win32 | |
629 | { | |
630 | inline bool interlocked_bit_test_and_set(long* x,long bit) | |
631 | { | |
632 | long const value=1<<bit; | |
633 | long old=*x; | |
634 | do | |
635 | { | |
636 | long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old); | |
637 | if(current==old) | |
638 | { | |
639 | break; | |
640 | } | |
641 | old=current; | |
642 | } | |
643 | while(true) ; | |
644 | return (old&value)!=0; | |
645 | } | |
646 | ||
647 | inline bool interlocked_bit_test_and_reset(long* x,long bit) | |
648 | { | |
649 | long const value=1<<bit; | |
650 | long old=*x; | |
651 | do | |
652 | { | |
653 | long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old); | |
654 | if(current==old) | |
655 | { | |
656 | break; | |
657 | } | |
658 | old=current; | |
659 | } | |
660 | while(true) ; | |
661 | return (old&value)!=0; | |
662 | } | |
663 | } | |
664 | } | |
665 | } | |
666 | #endif | |
667 | ||
668 | #include <boost/config/abi_suffix.hpp> | |
669 | ||
670 | #endif |