summaryrefslogtreecommitdiff
path: root/libs/thread/src
diff options
context:
space:
mode:
Diffstat (limited to 'libs/thread/src')
-rw-r--r--libs/thread/src/future.cpp2
-rw-r--r--libs/thread/src/pthread/thread.cpp13
-rw-r--r--libs/thread/src/pthread/timeconv.inl151
-rw-r--r--libs/thread/src/win32/thread.cpp137
-rw-r--r--libs/thread/src/win32/timeconv.inl130
-rw-r--r--libs/thread/src/win32/tss_dll.cpp8
6 files changed, 96 insertions, 345 deletions
diff --git a/libs/thread/src/future.cpp b/libs/thread/src/future.cpp
index 0b990c101..4aeac94a1 100644
--- a/libs/thread/src/future.cpp
+++ b/libs/thread/src/future.cpp
@@ -7,7 +7,7 @@
#ifndef BOOST_NO_EXCEPTIONS
-#include <boost/thread/future_error_code.hpp>
+#include <boost/thread/futures/future_error_code.hpp>
#include <string>
namespace boost
diff --git a/libs/thread/src/pthread/thread.cpp b/libs/thread/src/pthread/thread.cpp
index 4eab832b4..bbd25493f 100644
--- a/libs/thread/src/pthread/thread.cpp
+++ b/libs/thread/src/pthread/thread.cpp
@@ -36,8 +36,6 @@
#include <set>
#include <vector>
-#include "./timeconv.inl"
-
namespace boost
{
namespace detail
@@ -98,13 +96,10 @@ namespace boost
}
delete current_node;
}
- for(std::map<void const*,tss_data_node>::iterator next=thread_info->tss_data.begin(),
- current,
- end=thread_info->tss_data.end();
- next!=end;)
+ while (!thread_info->tss_data.empty())
{
- current=next;
- ++next;
+ std::map<void const*,detail::tss_data_node>::iterator current
+ = thread_info->tss_data.begin();
if(current->second.func && (current->second.value!=0))
{
(*current->second.func)(current->second.value);
@@ -164,7 +159,7 @@ namespace boost
static void* thread_proxy(void* param)
{
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
- thread_info->self.reset();
+ //thread_info->self.reset();
detail::set_current_thread_data(thread_info.get());
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
BOOST_TRY
diff --git a/libs/thread/src/pthread/timeconv.inl b/libs/thread/src/pthread/timeconv.inl
deleted file mode 100644
index d81f31ba2..000000000
--- a/libs/thread/src/pthread/timeconv.inl
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-// Copyright (C) 2009 Anthony Williams
-//
-// 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
-
-#include <boost/assert.hpp>
-
-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;
-
-#if defined BOOST_THREAD_USES_DATETIME
-inline void to_time(int milliseconds, boost::xtime& xt)
-{
- int res = 0;
- res = boost::xtime_get(&xt, boost::TIME_UTC_);
- BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
-
- 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;
- }
-}
-#endif
-#if defined(BOOST_HAS_PTHREADS)
-#if defined BOOST_THREAD_USES_DATETIME
-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;
- }
-}
-#endif
-inline void to_time(int milliseconds, timespec& ts)
-{
-#if defined BOOST_THREAD_USES_DATETIME
- boost::xtime xt;
- to_time(milliseconds, xt);
- to_timespec(xt, ts);
-#else
- ts.tv_sec += (milliseconds / MILLISECONDS_PER_SECOND);
- ts.tv_nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
- NANOSECONDS_PER_MILLISECOND);
-
- if (ts.tv_nsec >= NANOSECONDS_PER_SECOND)
- {
- ++ts.tv_sec;
- ts.tv_nsec -= NANOSECONDS_PER_SECOND;
- }
-#endif
-}
-
-#if defined BOOST_THREAD_USES_DATETIME
-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_);
- BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
-
- 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
-#endif
-
-#if defined BOOST_THREAD_USES_DATETIME
-inline void to_duration(boost::xtime xt, int& milliseconds)
-{
- boost::xtime cur;
- int res = 0;
- res = boost::xtime_get(&cur, boost::TIME_UTC_);
- BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
-
- 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_);
- BOOST_ASSERT(res == boost::TIME_UTC_); (void)res;
-
- 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);
- }
-}
-#endif
-}
-
-// Change Log:
-// 1 Jun 01 Initial creation.
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)