diff options
Diffstat (limited to 'libs/thread/src/win32')
-rw-r--r-- | libs/thread/src/win32/thread.cpp | 137 | ||||
-rw-r--r-- | libs/thread/src/win32/timeconv.inl | 130 | ||||
-rw-r--r-- | libs/thread/src/win32/tss_dll.cpp | 8 |
3 files changed, 91 insertions, 184 deletions
diff --git a/libs/thread/src/win32/thread.cpp b/libs/thread/src/win32/thread.cpp index ed2c10bfa..f23cf29a1 100644 --- a/libs/thread/src/win32/thread.cpp +++ b/libs/thread/src/win32/thread.cpp @@ -44,7 +44,7 @@ #include <wrl\ftm.h> #include <windows.system.threading.h> #pragma comment(lib, "runtimeobject.lib") -#endif +#endif namespace boost { @@ -198,7 +198,7 @@ namespace boost namespace detail { std::atomic_uint threadCount; - + bool win32::scoped_winrt_thread::start(thread_func address, void *parameter, unsigned int *thrdId) { Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IThreadPoolStatics> threadPoolFactory; @@ -220,7 +220,7 @@ namespace boost m_completionHandle = completionHandle; // Create new work item. - Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem = + Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem = Microsoft::WRL::Callback<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::System::Threading::IWorkItemHandler, Microsoft::WRL::FtmBase>> ([address, parameter, completionHandle](ABI::Windows::Foundation::IAsyncAction *) { @@ -274,13 +274,10 @@ namespace boost } boost::detail::heap_delete(current_node); } - for(std::map<void const*,detail::tss_data_node>::iterator next=current_thread_data->tss_data.begin(), - current, - end=current_thread_data->tss_data.end(); - next!=end;) + while (!current_thread_data->tss_data.empty()) { - current=next; - ++next; + std::map<void const*,detail::tss_data_node>::iterator current + = current_thread_data->tss_data.begin(); if(current->second.func && (current->second.value!=0)) { (*current->second.func)(current->second.value); @@ -346,7 +343,7 @@ namespace boost return true; #endif } - + bool thread::start_thread_noexcept(const attributes& attr) { #if BOOST_PLAT_WINDOWS_RUNTIME @@ -367,7 +364,7 @@ namespace boost return true; #endif } - + thread::thread(detail::thread_data_ptr data): thread_info(data) {} @@ -529,11 +526,10 @@ namespace boost unsigned thread::physical_concurrency() BOOST_NOEXCEPT { -#if BOOST_PLAT_WINDOWS_RUNTIME +#if BOOST_PLAT_WINDOWS_RUNTIME || (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) return hardware_concurrency(); #else unsigned cores = 0; -#if !(defined(__MINGW32__) || defined (__MINGW64__)) DWORD size = 0; GetLogicalProcessorInformation(NULL, &size); @@ -550,7 +546,6 @@ namespace boost if (buffer[i].Relationship == RelationProcessorCore) ++cores; } -#endif return cores; #endif } @@ -633,10 +628,60 @@ namespace boost } } - +#ifndef UNDER_CE +#if !BOOST_PLAT_WINDOWS_RUNTIME + namespace detail_ + { + typedef struct _REASON_CONTEXT { + ULONG Version; + DWORD Flags; + union { + LPWSTR SimpleReasonString; + struct { + HMODULE LocalizedReasonModule; + ULONG LocalizedReasonId; + ULONG ReasonStringCount; + LPWSTR *ReasonStrings; + } Detailed; + } Reason; + } REASON_CONTEXT, *PREASON_CONTEXT; + static REASON_CONTEXT default_reason_context={0/*POWER_REQUEST_CONTEXT_VERSION*/, 0x00000001/*POWER_REQUEST_CONTEXT_SIMPLE_STRING*/, (LPWSTR)L"generic"}; + typedef BOOL (WINAPI *setwaitabletimerex_t)(HANDLE, const LARGE_INTEGER *, LONG, PTIMERAPCROUTINE, LPVOID, PREASON_CONTEXT, ULONG); + static inline BOOL WINAPI SetWaitableTimerEx_emulation(HANDLE hTimer, const LARGE_INTEGER *lpDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, ULONG TolerableDelay) + { + return SetWaitableTimer(hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine, FALSE); + } +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 6387) // MSVC sanitiser warns that GetModuleHandleA() might fail +#endif + static inline setwaitabletimerex_t SetWaitableTimerEx() + { + static setwaitabletimerex_t setwaitabletimerex_impl; + if(setwaitabletimerex_impl) + return setwaitabletimerex_impl; + void (*addr)()=(void (*)()) GetProcAddress( +#if !defined(BOOST_NO_ANSI_APIS) + GetModuleHandleA("KERNEL32.DLL"), +#else + GetModuleHandleW(L"KERNEL32.DLL"), +#endif + "SetWaitableTimerEx"); + if(addr) + setwaitabletimerex_impl=(setwaitabletimerex_t) addr; + else + setwaitabletimerex_impl=&SetWaitableTimerEx_emulation; + return setwaitabletimerex_impl; + } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } +#endif +#endif bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time) { - detail::win32::handle handles[3]={0}; + detail::win32::handle handles[4]={0}; unsigned handle_count=0; unsigned wait_handle_index=~0U; #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS @@ -659,32 +704,24 @@ namespace boost #ifndef UNDER_CE #if !BOOST_PLAT_WINDOWS_RUNTIME - unsigned const min_timer_wait_period=20; - + // Preferentially use coalescing timers for better power consumption and timer accuracy if(!target_time.is_sentinel()) { detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds(); - if(time_left.milliseconds > min_timer_wait_period) + timer_handle=CreateWaitableTimer(NULL,false,NULL); + if(timer_handle!=0) { - // for a long-enough timeout, use a waitable timer (which tracks clock changes) - timer_handle=CreateWaitableTimer(NULL,false,NULL); - if(timer_handle!=0) + ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26 + if(time_left.milliseconds/20>tolerable) // 5% + tolerable=time_left.milliseconds/20; + LARGE_INTEGER due_time=get_due_time(target_time); + bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0; + if(set_time_succeeded) { - LARGE_INTEGER due_time=get_due_time(target_time); - - bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0; - if(set_time_succeeded) - { - timeout_index=handle_count; - handles[handle_count++]=timer_handle; - } + timeout_index=handle_count; + handles[handle_count++]=timer_handle; } } - else if(!target_time.relative) - { - // convert short absolute-time timeouts into relative ones, so we don't race against clock changes - target_time=detail::timeout(time_left.milliseconds); - } } #endif #endif @@ -751,32 +788,24 @@ namespace boost #ifndef UNDER_CE #if !BOOST_PLAT_WINDOWS_RUNTIME - unsigned const min_timer_wait_period=20; - + // Preferentially use coalescing timers for better power consumption and timer accuracy if(!target_time.is_sentinel()) { detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds(); - if(time_left.milliseconds > min_timer_wait_period) + timer_handle=CreateWaitableTimer(NULL,false,NULL); + if(timer_handle!=0) { - // for a long-enough timeout, use a waitable timer (which tracks clock changes) - timer_handle=CreateWaitableTimer(NULL,false,NULL); - if(timer_handle!=0) + ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26 + if(time_left.milliseconds/20>tolerable) // 5% + tolerable=time_left.milliseconds/20; + LARGE_INTEGER due_time=get_due_time(target_time); + bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,&detail_::default_reason_context,tolerable)!=0; + if(set_time_succeeded) { - LARGE_INTEGER due_time=get_due_time(target_time); - - bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0; - if(set_time_succeeded) - { - timeout_index=handle_count; - handles[handle_count++]=timer_handle; - } + timeout_index=handle_count; + handles[handle_count++]=timer_handle; } } - else if(!target_time.relative) - { - // convert short absolute-time timeouts into relative ones, so we don't race against clock changes - target_time=detail::timeout(time_left.milliseconds); - } } #endif #endif diff --git a/libs/thread/src/win32/timeconv.inl b/libs/thread/src/win32/timeconv.inl deleted file mode 100644 index c6467832a..000000000 --- a/libs/thread/src/win32/timeconv.inl +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (C) 2001-2003 -// William E. Kempf -// -// 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) - -// boostinspect:nounnamed - -namespace { -const int MILLISECONDS_PER_SECOND = 1000; -const int NANOSECONDS_PER_SECOND = 1000000000; -const int NANOSECONDS_PER_MILLISECOND = 1000000; - -const int MICROSECONDS_PER_SECOND = 1000000; -const int NANOSECONDS_PER_MICROSECOND = 1000; - -inline void to_time(int milliseconds, boost::xtime& xt) -{ - int res = 0; - res = boost::xtime_get(&xt, boost::TIME_UTC_); - assert(res == boost::TIME_UTC_); - - xt.sec += (milliseconds / MILLISECONDS_PER_SECOND); - xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * - NANOSECONDS_PER_MILLISECOND); - - if (xt.nsec >= NANOSECONDS_PER_SECOND) - { - ++xt.sec; - xt.nsec -= NANOSECONDS_PER_SECOND; - } -} - -#if defined(BOOST_HAS_PTHREADS) -inline void to_timespec(const boost::xtime& xt, timespec& ts) -{ - ts.tv_sec = static_cast<int>(xt.sec); - ts.tv_nsec = static_cast<int>(xt.nsec); - if(ts.tv_nsec >= NANOSECONDS_PER_SECOND) - { - ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; - ts.tv_nsec %= NANOSECONDS_PER_SECOND; - } -} - -inline void to_time(int milliseconds, timespec& ts) -{ - boost::xtime xt; - to_time(milliseconds, xt); - to_timespec(xt, ts); -} - -inline void to_timespec_duration(const boost::xtime& xt, timespec& ts) -{ - boost::xtime cur; - int res = 0; - res = boost::xtime_get(&cur, boost::TIME_UTC_); - assert(res == boost::TIME_UTC_); - - if (boost::xtime_cmp(xt, cur) <= 0) - { - ts.tv_sec = 0; - ts.tv_nsec = 0; - } - else - { - ts.tv_sec = xt.sec - cur.sec; - ts.tv_nsec = xt.nsec - cur.nsec; - - if( ts.tv_nsec < 0 ) - { - ts.tv_sec -= 1; - ts.tv_nsec += NANOSECONDS_PER_SECOND; - } - if(ts.tv_nsec >= NANOSECONDS_PER_SECOND) - { - ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; - ts.tv_nsec %= NANOSECONDS_PER_SECOND; - } - } -} -#endif - -inline void to_duration(boost::xtime xt, int& milliseconds) -{ - boost::xtime cur; - int res = 0; - res = boost::xtime_get(&cur, boost::TIME_UTC_); - assert(res == boost::TIME_UTC_); - - if (boost::xtime_cmp(xt, cur) <= 0) - milliseconds = 0; - else - { - if (cur.nsec > xt.nsec) - { - xt.nsec += NANOSECONDS_PER_SECOND; - --xt.sec; - } - milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) + - (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) / - NANOSECONDS_PER_MILLISECOND); - } -} - -inline void to_microduration(boost::xtime xt, int& microseconds) -{ - boost::xtime cur; - int res = 0; - res = boost::xtime_get(&cur, boost::TIME_UTC_); - assert(res == boost::TIME_UTC_); - - if (boost::xtime_cmp(xt, cur) <= 0) - microseconds = 0; - else - { - if (cur.nsec > xt.nsec) - { - xt.nsec += NANOSECONDS_PER_SECOND; - --xt.sec; - } - microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) + - (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) / - NANOSECONDS_PER_MICROSECOND); - } -} -} - -// Change Log: -// 1 Jun 01 Initial creation. diff --git a/libs/thread/src/win32/tss_dll.cpp b/libs/thread/src/win32/tss_dll.cpp index 2dc019f4b..e0b73e0fc 100644 --- a/libs/thread/src/win32/tss_dll.cpp +++ b/libs/thread/src/win32/tss_dll.cpp @@ -73,5 +73,13 @@ namespace boost } } +#else //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL) + +#ifdef _MSC_VER +// Prevent LNK4221 warning with link=static +namespace boost { namespace link_static_warning_inhibit { + extern __declspec(dllexport) void foo() { } +} } +#endif #endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL) |