diff options
Diffstat (limited to '3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp | 95 |
1 files changed, 88 insertions, 7 deletions
diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp index c0dba11..fcf59b3 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp @@ -15,6 +15,7 @@ #include <boost/assert.hpp> #include <boost/thread/exceptions.hpp> #include <boost/detail/interlocked.hpp> +//#include <boost/detail/winapi/synchronization.hpp> #include <algorithm> #if defined( BOOST_USE_WINDOWS_H ) @@ -26,13 +27,14 @@ namespace boost { 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; + unsigned const wait_abandoned=WAIT_ABANDONED; + # ifdef BOOST_NO_ANSI_APIS using ::CreateMutexW; @@ -60,7 +62,6 @@ namespace boost using ::SleepEx; using ::Sleep; using ::QueueUserAPC; - using ::GetTickCount; } } } @@ -88,13 +89,13 @@ typedef void* HANDLE; # endif # endif + namespace boost { namespace detail { namespace win32 { - # ifdef _WIN64 typedef unsigned __int64 ulong_ptr; # else @@ -106,6 +107,7 @@ namespace boost handle const invalid_handle_value=(handle)(-1); unsigned const event_modify_state=2; unsigned const synchronize=0x100000u; + unsigned const wait_abandoned=0x00000080u; extern "C" { @@ -132,8 +134,6 @@ namespace boost 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(); @@ -165,7 +165,88 @@ namespace boost { namespace win32 { - enum event_type + typedef unsigned __int64 ticks_type; + namespace detail { typedef int (__stdcall *farproc_t)(); typedef ticks_type (__stdcall *gettickcount64_t)(); } + extern "C" + { + __declspec(dllimport) detail::farproc_t __stdcall GetProcAddress(void *, const char *); +#if !defined(BOOST_NO_ANSI_APIS) + __declspec(dllimport) void * __stdcall GetModuleHandleA(const char *); +#else + __declspec(dllimport) void * __stdcall GetModuleHandleW(const wchar_t *); +#endif + int __stdcall GetTickCount(); + long _InterlockedCompareExchange(long volatile *, long, long); +#pragma intrinsic(_InterlockedCompareExchange) + } + // Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar + inline ticks_type __stdcall GetTickCount64emulation() + { + static volatile long count = 0xFFFFFFFF; + unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone; + ticks_type current_tick64; + + previous_count = (unsigned long) _InterlockedCompareExchange(&count, 0, 0); + current_tick32 = GetTickCount(); + + if(previous_count == 0xFFFFFFFF) + { + // count has never been written + unsigned long initial_count; + initial_count = current_tick32 >> 28; + previous_count = (unsigned long) _InterlockedCompareExchange(&count, initial_count, 0xFFFFFFFF); + + current_tick64 = initial_count; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + previous_count_zone = previous_count & 15; + current_tick32_zone = current_tick32 >> 28; + + if(current_tick32_zone == previous_count_zone) + { + // The top four bits of the 32-bit tick count haven't changed since count was last written. + current_tick64 = previous_count; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + if(current_tick32_zone == previous_count_zone + 1 || (current_tick32_zone == 0 && previous_count_zone == 15)) + { + // The top four bits of the 32-bit tick count have been incremented since count was last written. + _InterlockedCompareExchange(&count, previous_count + 1, previous_count); + current_tick64 = previous_count + 1; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + // Oops, we weren't called often enough, we're stuck + return 0xFFFFFFFF; + } + inline detail::gettickcount64_t GetTickCount64() + { + static detail::gettickcount64_t gettickcount64impl; + if(gettickcount64impl) + return gettickcount64impl; + detail::farproc_t addr=GetProcAddress( +#if !defined(BOOST_NO_ANSI_APIS) + GetModuleHandleA("KERNEL32.DLL"), +#else + GetModuleHandleW(L"KERNEL32.DLL"), +#endif + "GetTickCount64"); + if(addr) + gettickcount64impl=(detail::gettickcount64_t) addr; + else + gettickcount64impl=&GetTickCount64emulation; + return gettickcount64impl; + } + + enum event_type { auto_reset_event=false, manual_reset_event=true @@ -232,7 +313,7 @@ namespace boost BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0); } - class handle_manager + class BOOST_THREAD_DECL handle_manager { private: handle handle_to_manage; |