You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
407 lines
13 KiB
407 lines
13 KiB
#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
|
|
|