• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 #include <boost/winapi/config.hpp>
21 #include <boost/winapi/basic_types.hpp>
22 #include <boost/winapi/semaphore.hpp>
23 #include <boost/winapi/system.hpp>
24 #include <boost/winapi/event.hpp>
25 #include <boost/winapi/thread.hpp>
26 #include <boost/winapi/get_current_thread.hpp>
27 #include <boost/winapi/get_current_thread_id.hpp>
28 #include <boost/winapi/get_current_process.hpp>
29 #include <boost/winapi/get_current_process_id.hpp>
30 #include <boost/winapi/wait.hpp>
31 #include <boost/winapi/handles.hpp>
32 #include <boost/winapi/access_rights.hpp>
33 
34 //#include <boost/winapi/synchronization.hpp>
35 #include <boost/thread/win32/interlocked_read.hpp>
36 #include <algorithm>
37 
38 #if BOOST_PLAT_WINDOWS_RUNTIME
39 #include <thread>
40 #endif
41 
42 namespace boost
43 {
44     namespace detail
45     {
46         namespace win32
47         {
48             typedef ::boost::winapi::HANDLE_ handle;
49             typedef ::boost::winapi::SYSTEM_INFO_ system_info;
50             typedef ::boost::winapi::ULONGLONG_ ticks_type;
51             unsigned const infinite=::boost::winapi::INFINITE_;
52             unsigned const timeout=::boost::winapi::WAIT_TIMEOUT_;
53             handle const invalid_handle_value=::boost::winapi::INVALID_HANDLE_VALUE_;
54             unsigned const event_modify_state=::boost::winapi::EVENT_MODIFY_STATE_;
55             unsigned const synchronize=::boost::winapi::SYNCHRONIZE_;
56             unsigned const wait_abandoned=::boost::winapi::WAIT_ABANDONED_;
57             unsigned const create_event_initial_set = 0x00000002;
58             unsigned const create_event_manual_reset = 0x00000001;
59             unsigned const event_all_access = ::boost::winapi::EVENT_ALL_ACCESS_;
60             unsigned const semaphore_all_access = boost::winapi::SEMAPHORE_ALL_ACCESS_;
61         }
62     }
63 }
64 
65 #include <boost/config/abi_prefix.hpp>
66 
67 namespace boost
68 {
69     namespace detail
70     {
71         namespace win32
72         {
73             namespace detail { typedef ticks_type (BOOST_WINAPI_WINAPI_CC *gettickcount64_t)(); }
74             extern BOOST_THREAD_DECL boost::detail::win32::detail::gettickcount64_t gettickcount64;
75 
76             enum event_type
77             {
78                 auto_reset_event=false,
79                 manual_reset_event=true
80             };
81 
82             enum initial_event_state
83             {
84                 event_initially_reset=false,
85                 event_initially_set=true
86             };
87 
create_event(const char * mutex_name,event_type type,initial_event_state state)88             inline handle create_event(
89 #if !defined(BOOST_NO_ANSI_APIS)
90                 const char *mutex_name,
91 #else
92                 const wchar_t *mutex_name,
93 #endif
94                 event_type type,
95                 initial_event_state state)
96             {
97 #if !defined(BOOST_NO_ANSI_APIS)
98                 handle const res = ::boost::winapi::CreateEventA(0, type, state, mutex_name);
99 #elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
100                 handle const res = ::boost::winapi::CreateEventW(0, type, state, mutex_name);
101 #else
102                 handle const res = ::boost::winapi::CreateEventExW(
103                     0,
104                     mutex_name,
105                     (type ? create_event_manual_reset : 0) | (state ? create_event_initial_set : 0),
106                     event_all_access);
107 #endif
108                 return res;
109             }
110 
create_anonymous_event(event_type type,initial_event_state state)111             inline handle create_anonymous_event(event_type type,initial_event_state state)
112             {
113                 handle const res = create_event(0, type, state);
114                 if(!res)
115                 {
116                     boost::throw_exception(thread_resource_error());
117                 }
118                 return res;
119             }
120 
create_anonymous_semaphore_nothrow(long initial_count,long max_count)121             inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
122             {
123 #if !defined(BOOST_NO_ANSI_APIS)
124                 handle const res=::boost::winapi::CreateSemaphoreA(0,initial_count,max_count,0);
125 #else
126 #if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
127                 handle const res=::boost::winapi::CreateSemaphoreEx(0,initial_count,max_count,0,0);
128 #else
129                 handle const res=::boost::winapi::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
130 #endif
131 #endif
132                 return res;
133             }
134 
create_anonymous_semaphore(long initial_count,long max_count)135             inline handle create_anonymous_semaphore(long initial_count,long max_count)
136             {
137                 handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count);
138                 if(!res)
139                 {
140                     boost::throw_exception(thread_resource_error());
141                 }
142                 return res;
143             }
144 
duplicate_handle(handle source)145             inline handle duplicate_handle(handle source)
146             {
147                 handle const current_process=::boost::winapi::GetCurrentProcess();
148                 long const same_access_flag=2;
149                 handle new_handle=0;
150                 bool const success=::boost::winapi::DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
151                 if(!success)
152                 {
153                     boost::throw_exception(thread_resource_error());
154                 }
155                 return new_handle;
156             }
157 
release_semaphore(handle semaphore,long count)158             inline void release_semaphore(handle semaphore,long count)
159             {
160                 BOOST_VERIFY(::boost::winapi::ReleaseSemaphore(semaphore,count,0)!=0);
161             }
162 
get_system_info(system_info * info)163             inline void get_system_info(system_info *info)
164             {
165 #if BOOST_PLAT_WINDOWS_RUNTIME
166                 ::boost::winapi::GetNativeSystemInfo(info);
167 #else
168                 ::boost::winapi::GetSystemInfo(info);
169 #endif
170             }
171 
sleep(unsigned long milliseconds)172             inline void sleep(unsigned long milliseconds)
173             {
174                 if(milliseconds == 0)
175                 {
176 #if BOOST_PLAT_WINDOWS_RUNTIME
177                     std::this_thread::yield();
178 #else
179                     ::boost::winapi::Sleep(0);
180 #endif
181                 }
182                 else
183                 {
184 #if BOOST_PLAT_WINDOWS_RUNTIME
185                     ::boost::winapi::WaitForSingleObjectEx(::boost::winapi::GetCurrentThread(), milliseconds, 0);
186 #else
187                     ::boost::winapi::Sleep(milliseconds);
188 #endif
189                 }
190             }
191 
192 #if BOOST_PLAT_WINDOWS_RUNTIME
193             class BOOST_THREAD_DECL scoped_winrt_thread
194             {
195             public:
scoped_winrt_thread()196                 scoped_winrt_thread() : m_completionHandle(invalid_handle_value)
197                 {}
198 
~scoped_winrt_thread()199                 ~scoped_winrt_thread()
200                 {
201                     if (m_completionHandle != ::boost::detail::win32::invalid_handle_value)
202                     {
203                         ::boost::winapi::CloseHandle(m_completionHandle);
204                     }
205                 }
206 
207                 typedef unsigned(__stdcall * thread_func)(void *);
208                 bool start(thread_func address, void *parameter, unsigned int *thrdId);
209 
waitable_handle() const210                 handle waitable_handle() const
211                 {
212                     BOOST_ASSERT(m_completionHandle != ::boost::detail::win32::invalid_handle_value);
213                     return m_completionHandle;
214                 }
215 
216             private:
217                 handle m_completionHandle;
218             };
219 #endif
220             class BOOST_THREAD_DECL handle_manager
221             {
222             private:
223                 handle handle_to_manage;
224                 handle_manager(handle_manager&);
225                 handle_manager& operator=(handle_manager&);
226 
cleanup()227                 void cleanup()
228                 {
229                     if(handle_to_manage && handle_to_manage!=invalid_handle_value)
230                     {
231                         BOOST_VERIFY(::boost::winapi::CloseHandle(handle_to_manage));
232                     }
233                 }
234 
235             public:
handle_manager(handle handle_to_manage_)236                 explicit handle_manager(handle handle_to_manage_):
237                     handle_to_manage(handle_to_manage_)
238                 {}
handle_manager()239                 handle_manager():
240                     handle_to_manage(0)
241                 {}
242 
operator =(handle new_handle)243                 handle_manager& operator=(handle new_handle)
244                 {
245                     cleanup();
246                     handle_to_manage=new_handle;
247                     return *this;
248                 }
249 
operator handle() const250                 operator handle() const
251                 {
252                     return handle_to_manage;
253                 }
254 
duplicate() const255                 handle duplicate() const
256                 {
257                     return duplicate_handle(handle_to_manage);
258                 }
259 
swap(handle_manager & other)260                 void swap(handle_manager& other)
261                 {
262                     std::swap(handle_to_manage,other.handle_to_manage);
263                 }
264 
release()265                 handle release()
266                 {
267                     handle const res=handle_to_manage;
268                     handle_to_manage=0;
269                     return res;
270                 }
271 
operator !() const272                 bool operator!() const
273                 {
274                     return !handle_to_manage;
275                 }
276 
~handle_manager()277                 ~handle_manager()
278                 {
279                     cleanup();
280                 }
281             };
282         }
283     }
284 }
285 
286 #if defined(BOOST_MSVC) && (_MSC_VER>=1400)  && !defined(UNDER_CE)
287 
288 namespace boost
289 {
290     namespace detail
291     {
292         namespace win32
293         {
294 #if _MSC_VER==1400
295             extern "C" unsigned char _interlockedbittestandset(long *a,long b);
296             extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
297 #else
298             extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b);
299             extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b);
300 #endif
301 
302 #pragma intrinsic(_interlockedbittestandset)
303 #pragma intrinsic(_interlockedbittestandreset)
304 
interlocked_bit_test_and_set(long * x,long bit)305             inline bool interlocked_bit_test_and_set(long* x,long bit)
306             {
307                 return _interlockedbittestandset(x,bit)!=0;
308             }
309 
interlocked_bit_test_and_reset(long * x,long bit)310             inline bool interlocked_bit_test_and_reset(long* x,long bit)
311             {
312                 return _interlockedbittestandreset(x,bit)!=0;
313             }
314 
315         }
316     }
317 }
318 #define BOOST_THREAD_BTS_DEFINED
319 #elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86)
320 namespace boost
321 {
322     namespace detail
323     {
324         namespace win32
325         {
interlocked_bit_test_and_set(long * x,long bit)326             inline bool interlocked_bit_test_and_set(long* x,long bit)
327             {
328 #ifndef BOOST_INTEL_CXX_VERSION
329                 __asm {
330                     mov eax,bit;
331                     mov edx,x;
332                     lock bts [edx],eax;
333                     setc al;
334                 };
335 #else
336                 bool ret;
337                 __asm {
338                     mov eax,bit
339                     mov edx,x
340                     lock bts [edx],eax
341                     setc al
342                     mov ret, al
343                 };
344                 return ret;
345 
346 #endif
347             }
348 
interlocked_bit_test_and_reset(long * x,long bit)349             inline bool interlocked_bit_test_and_reset(long* x,long bit)
350             {
351 #ifndef BOOST_INTEL_CXX_VERSION
352                 __asm {
353                     mov eax,bit;
354                     mov edx,x;
355                     lock btr [edx],eax;
356                     setc al;
357                 };
358 #else
359                 bool ret;
360                 __asm {
361                     mov eax,bit
362                     mov edx,x
363                     lock btr [edx],eax
364                     setc al
365                     mov ret, al
366                 };
367                 return ret;
368 
369 #endif
370             }
371 
372         }
373     }
374 }
375 #define BOOST_THREAD_BTS_DEFINED
376 #endif
377 
378 #ifndef BOOST_THREAD_BTS_DEFINED
379 
380 namespace boost
381 {
382     namespace detail
383     {
384         namespace win32
385         {
interlocked_bit_test_and_set(long * x,long bit)386             inline bool interlocked_bit_test_and_set(long* x,long bit)
387             {
388                 long const value=1<<bit;
389                 long old=*x;
390                 do
391                 {
392                     long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old);
393                     if(current==old)
394                     {
395                         break;
396                     }
397                     old=current;
398                 }
399                 while(true) ;
400                 return (old&value)!=0;
401             }
402 
interlocked_bit_test_and_reset(long * x,long bit)403             inline bool interlocked_bit_test_and_reset(long* x,long bit)
404             {
405                 long const value=1<<bit;
406                 long old=*x;
407                 do
408                 {
409                     long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old);
410                     if(current==old)
411                     {
412                         break;
413                     }
414                     old=current;
415                 }
416                 while(true) ;
417                 return (old&value)!=0;
418             }
419         }
420     }
421 }
422 #endif
423 
424 #include <boost/config/abi_suffix.hpp>
425 
426 #endif
427