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