#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/config.hpp> | |
#include <boost/throw_exception.hpp> | |
#include <boost/assert.hpp> | |
#include <boost/thread/exceptions.hpp> | |
#include <boost/detail/interlocked.hpp> | |
#include <algorithm> | |
#if defined( BOOST_USE_WINDOWS_H ) | |
# include <windows.h> | |
namespace boost | |
{ | |
namespace detail | |
{ | |
namespace win32 | |
{ | |
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; | |
# 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; | |
} | |
} | |
} | |
#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 _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; | |
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(); | |
# 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 | |
} | |
} | |
} | |
} | |
#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 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 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) | |
{ | |
__asm { | |
mov eax,bit; | |
mov edx,x; | |
lock bts [edx],eax; | |
setc al; | |
}; | |
} | |
inline bool interlocked_bit_test_and_reset(long* x,long bit) | |
{ | |
__asm { | |
mov eax,bit; | |
mov edx,x; | |
lock btr [edx],eax; | |
setc al; | |
}; | |
} | |
} | |
} | |
} | |
#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 |