123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472 |
- #ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP
- #define BOOST_WIN32_THREAD_PRIMITIVES_HPP
- // win32_thread_primitives.hpp
- //
- // (C) Copyright 2005-7 Anthony Williams
- // (C) Copyright 2007 David Deakins
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #include <boost/thread/detail/config.hpp>
- #include <boost/throw_exception.hpp>
- #include <boost/assert.hpp>
- #include <boost/thread/exceptions.hpp>
- #include <boost/detail/interlocked.hpp>
- //#include <boost/detail/winapi/synchronization.hpp>
- #include <algorithm>
- #ifndef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
- #if _WIN32_WINNT >= 0x0600 && ! defined _WIN32_WINNT_WS08
- #define BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
- #endif
- #endif
- #if defined( BOOST_USE_WINDOWS_H )
- # include <windows.h>
- namespace boost
- {
- namespace detail
- {
- namespace win32
- {
- #ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
- typedef unsigned long long ticks_type;
- #else
- typedef unsigned long ticks_type;
- #endif
- typedef ULONG_PTR ulong_ptr;
- typedef HANDLE handle;
- unsigned const infinite=INFINITE;
- unsigned const timeout=WAIT_TIMEOUT;
- handle const invalid_handle_value=INVALID_HANDLE_VALUE;
- unsigned const event_modify_state=EVENT_MODIFY_STATE;
- unsigned const synchronize=SYNCHRONIZE;
- unsigned const wait_abandoned=WAIT_ABANDONED;
- # ifdef BOOST_NO_ANSI_APIS
- using ::CreateMutexW;
- using ::CreateEventW;
- using ::OpenEventW;
- using ::CreateSemaphoreW;
- # else
- using ::CreateMutexA;
- using ::CreateEventA;
- using ::OpenEventA;
- using ::CreateSemaphoreA;
- # endif
- using ::CloseHandle;
- using ::ReleaseMutex;
- using ::ReleaseSemaphore;
- using ::SetEvent;
- using ::ResetEvent;
- using ::WaitForMultipleObjects;
- using ::WaitForSingleObject;
- using ::GetCurrentProcessId;
- using ::GetCurrentThreadId;
- using ::GetCurrentThread;
- using ::GetCurrentProcess;
- using ::DuplicateHandle;
- using ::SleepEx;
- using ::Sleep;
- using ::QueueUserAPC;
- using ::GetTickCount;
- #ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
- using ::GetTickCount64;
- #else
- inline ticks_type GetTickCount64() { return GetTickCount(); }
- #endif
- }
- }
- }
- #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
- # ifdef UNDER_CE
- # ifndef WINAPI
- # ifndef _WIN32_WCE_EMULATION
- # define WINAPI __cdecl // Note this doesn't match the desktop definition
- # else
- # define WINAPI __stdcall
- # endif
- # endif
- # ifdef __cplusplus
- extern "C" {
- # endif
- typedef int BOOL;
- typedef unsigned long DWORD;
- typedef void* HANDLE;
- # include <kfuncs.h>
- # ifdef __cplusplus
- }
- # endif
- # endif
- namespace boost
- {
- namespace detail
- {
- namespace win32
- {
- #ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
- typedef unsigned long long ticks_type;
- #else
- typedef unsigned long ticks_type;
- #endif
- # ifdef _WIN64
- typedef unsigned __int64 ulong_ptr;
- # else
- typedef unsigned long ulong_ptr;
- # endif
- typedef void* handle;
- unsigned const infinite=~0U;
- unsigned const timeout=258U;
- handle const invalid_handle_value=(handle)(-1);
- unsigned const event_modify_state=2;
- unsigned const synchronize=0x100000u;
- unsigned const wait_abandoned=0x00000080u;
- extern "C"
- {
- struct _SECURITY_ATTRIBUTES;
- # ifdef BOOST_NO_ANSI_APIS
- __declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
- __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
- __declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
- __declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
- # else
- __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
- __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
- __declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
- __declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
- # endif
- __declspec(dllimport) int __stdcall CloseHandle(void*);
- __declspec(dllimport) int __stdcall ReleaseMutex(void*);
- __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long);
- __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
- __declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
- __declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
- __declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
- __declspec(dllimport) void __stdcall Sleep(unsigned long);
- typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
- __declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
- __declspec(dllimport) unsigned long __stdcall GetTickCount();
- # ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
- __declspec(dllimport) ticks_type __stdcall GetTickCount64();
- # endif
- # ifndef UNDER_CE
- __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
- __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
- __declspec(dllimport) void* __stdcall GetCurrentThread();
- __declspec(dllimport) void* __stdcall GetCurrentProcess();
- __declspec(dllimport) int __stdcall SetEvent(void*);
- __declspec(dllimport) int __stdcall ResetEvent(void*);
- # else
- using ::GetCurrentProcessId;
- using ::GetCurrentThreadId;
- using ::GetCurrentThread;
- using ::GetCurrentProcess;
- using ::SetEvent;
- using ::ResetEvent;
- # endif
- }
- # ifndef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64
- inline ticks_type GetTickCount64() { return GetTickCount(); }
- # endif
- }
- }
- }
- #else
- # error "Win32 functions not available"
- #endif
- #include <boost/config/abi_prefix.hpp>
- namespace boost
- {
- namespace detail
- {
- namespace win32
- {
- enum event_type
- {
- auto_reset_event=false,
- manual_reset_event=true
- };
- enum initial_event_state
- {
- event_initially_reset=false,
- event_initially_set=true
- };
- inline handle create_anonymous_event(event_type type,initial_event_state state)
- {
- #if !defined(BOOST_NO_ANSI_APIS)
- handle const res=win32::CreateEventA(0,type,state,0);
- #else
- handle const res=win32::CreateEventW(0,type,state,0);
- #endif
- if(!res)
- {
- boost::throw_exception(thread_resource_error());
- }
- return res;
- }
- inline handle create_anonymous_semaphore(long initial_count,long max_count)
- {
- #if !defined(BOOST_NO_ANSI_APIS)
- handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
- #else
- handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
- #endif
- if(!res)
- {
- boost::throw_exception(thread_resource_error());
- }
- return res;
- }
- inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
- {
- #if !defined(BOOST_NO_ANSI_APIS)
- handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
- #else
- handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
- #endif
- return res;
- }
- inline handle duplicate_handle(handle source)
- {
- handle const current_process=GetCurrentProcess();
- long const same_access_flag=2;
- handle new_handle=0;
- bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
- if(!success)
- {
- boost::throw_exception(thread_resource_error());
- }
- return new_handle;
- }
- inline void release_semaphore(handle semaphore,long count)
- {
- BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
- }
- class BOOST_THREAD_DECL handle_manager
- {
- private:
- handle handle_to_manage;
- handle_manager(handle_manager&);
- handle_manager& operator=(handle_manager&);
- void cleanup()
- {
- if(handle_to_manage && handle_to_manage!=invalid_handle_value)
- {
- BOOST_VERIFY(CloseHandle(handle_to_manage));
- }
- }
- public:
- explicit handle_manager(handle handle_to_manage_):
- handle_to_manage(handle_to_manage_)
- {}
- handle_manager():
- handle_to_manage(0)
- {}
- handle_manager& operator=(handle new_handle)
- {
- cleanup();
- handle_to_manage=new_handle;
- return *this;
- }
- operator handle() const
- {
- return handle_to_manage;
- }
- handle duplicate() const
- {
- return duplicate_handle(handle_to_manage);
- }
- void swap(handle_manager& other)
- {
- std::swap(handle_to_manage,other.handle_to_manage);
- }
- handle release()
- {
- handle const res=handle_to_manage;
- handle_to_manage=0;
- return res;
- }
- bool operator!() const
- {
- return !handle_to_manage;
- }
- ~handle_manager()
- {
- cleanup();
- }
- };
- }
- }
- }
- #if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE)
- namespace boost
- {
- namespace detail
- {
- namespace win32
- {
- #if _MSC_VER==1400
- extern "C" unsigned char _interlockedbittestandset(long *a,long b);
- extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
- #else
- extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b);
- extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b);
- #endif
- #pragma intrinsic(_interlockedbittestandset)
- #pragma intrinsic(_interlockedbittestandreset)
- inline bool interlocked_bit_test_and_set(long* x,long bit)
- {
- return _interlockedbittestandset(x,bit)!=0;
- }
- inline bool interlocked_bit_test_and_reset(long* x,long bit)
- {
- return _interlockedbittestandreset(x,bit)!=0;
- }
- }
- }
- }
- #define BOOST_THREAD_BTS_DEFINED
- #elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86)
- namespace boost
- {
- namespace detail
- {
- namespace win32
- {
- inline bool interlocked_bit_test_and_set(long* x,long bit)
- {
- #ifndef BOOST_INTEL_CXX_VERSION
- __asm {
- mov eax,bit;
- mov edx,x;
- lock bts [edx],eax;
- setc al;
- };
- #else
- bool ret;
- __asm {
- mov eax,bit
- mov edx,x
- lock bts [edx],eax
- setc al
- mov ret, al
- };
- return ret;
- #endif
- }
- inline bool interlocked_bit_test_and_reset(long* x,long bit)
- {
- #ifndef BOOST_INTEL_CXX_VERSION
- __asm {
- mov eax,bit;
- mov edx,x;
- lock btr [edx],eax;
- setc al;
- };
- #else
- bool ret;
- __asm {
- mov eax,bit
- mov edx,x
- lock btr [edx],eax
- setc al
- mov ret, al
- };
- return ret;
- #endif
- }
- }
- }
- }
- #define BOOST_THREAD_BTS_DEFINED
- #endif
- #ifndef BOOST_THREAD_BTS_DEFINED
- namespace boost
- {
- namespace detail
- {
- namespace win32
- {
- inline bool interlocked_bit_test_and_set(long* x,long bit)
- {
- long const value=1<<bit;
- long old=*x;
- do
- {
- long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old);
- if(current==old)
- {
- break;
- }
- old=current;
- }
- while(true);
- return (old&value)!=0;
- }
- inline bool interlocked_bit_test_and_reset(long* x,long bit)
- {
- long const value=1<<bit;
- long old=*x;
- do
- {
- long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old);
- if(current==old)
- {
- break;
- }
- old=current;
- }
- while(true);
- return (old&value)!=0;
- }
- }
- }
- }
- #endif
- #include <boost/config/abi_suffix.hpp>
- #endif
|