summaryrefslogtreecommitdiff
path: root/boost/thread
diff options
context:
space:
mode:
Diffstat (limited to 'boost/thread')
-rw-r--r--boost/thread/detail/config.hpp2
-rw-r--r--boost/thread/detail/thread.hpp15
-rw-r--r--boost/thread/exceptions.hpp16
-rw-r--r--boost/thread/executors/executor.hpp2
-rw-r--r--boost/thread/executors/generic_executor_ref.hpp2
-rw-r--r--boost/thread/executors/loop_executor.hpp40
-rw-r--r--boost/thread/future.hpp4
-rw-r--r--boost/thread/futures/wait_for_all.hpp2
-rw-r--r--boost/thread/pthread/condition_variable_fwd.hpp16
-rw-r--r--boost/thread/pthread/timespec.hpp29
-rw-r--r--boost/thread/scoped_thread.hpp38
-rw-r--r--boost/thread/thread_functors.hpp21
-rw-r--r--boost/thread/thread_guard.hpp6
-rw-r--r--boost/thread/win32/interlocked_read.hpp151
-rw-r--r--boost/thread/win32/thread_primitives.hpp14
15 files changed, 285 insertions, 73 deletions
diff --git a/boost/thread/detail/config.hpp b/boost/thread/detail/config.hpp
index b060b81c95..6d1595ebc7 100644
--- a/boost/thread/detail/config.hpp
+++ b/boost/thread/detail/config.hpp
@@ -12,6 +12,8 @@
#include <boost/detail/workaround.hpp>
#include <boost/thread/detail/platform.hpp>
+//#define BOOST_THREAD_USEFIXES_TIMESPEC
+//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
// ATTRIBUTE_MAY_ALIAS
diff --git a/boost/thread/detail/thread.hpp b/boost/thread/detail/thread.hpp
index 9e7e8b8f5e..bd2f149a0e 100644
--- a/boost/thread/detail/thread.hpp
+++ b/boost/thread/detail/thread.hpp
@@ -482,13 +482,20 @@ namespace boost
return try_join_until(chrono::steady_clock::now() + rel_time);
}
#endif
+
+#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) && defined(BOOST_THREAD_USEFIXES_TIMESPEC)
+ typedef chrono::steady_clock my_clock_t;
+#else
+ typedef chrono::system_clock my_clock_t;
+#endif
+
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
bool joined= false;
do {
- system_clock::time_point s_now = system_clock::now();
+ my_clock_t::time_point s_now = my_clock_t::now();
typename Clock::duration d = ceil<nanoseconds>(t-Clock::now());
if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached
joined = try_join_until(s_now + d);
@@ -496,10 +503,10 @@ namespace boost
return true;
}
template <class Duration>
- bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t)
+ bool try_join_until(const chrono::time_point<my_clock_t, Duration>& t)
{
using namespace chrono;
- typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
+ typedef time_point<my_clock_t, nanoseconds> nano_sys_tmpt;
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
#endif
@@ -514,7 +521,7 @@ namespace boost
//}
#ifdef BOOST_THREAD_USES_CHRONO
- bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
+ bool try_join_until(const chrono::time_point<my_clock_t, chrono::nanoseconds>& tp)
{
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
return do_try_join_until(rel_time.count());
diff --git a/boost/thread/exceptions.hpp b/boost/thread/exceptions.hpp
index d97465b754..a3934f0799 100644
--- a/boost/thread/exceptions.hpp
+++ b/boost/thread/exceptions.hpp
@@ -40,19 +40,19 @@ namespace boost
typedef system::system_error base_type;
public:
thread_exception()
- : base_type(0,system::system_category())
+ : base_type(0,system::generic_category())
{}
thread_exception(int sys_error_code)
- : base_type(sys_error_code, system::system_category())
+ : base_type(sys_error_code, system::generic_category())
{}
thread_exception( int ev, const char * what_arg )
- : base_type(system::error_code(ev, system::system_category()), what_arg)
+ : base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
thread_exception( int ev, const std::string & what_arg )
- : base_type(system::error_code(ev, system::system_category()), what_arg)
+ : base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
@@ -74,18 +74,18 @@ namespace boost
typedef system::system_error base_type;
public:
condition_error()
- : base_type(system::error_code(0, system::system_category()), "Condition error")
+ : base_type(system::error_code(0, system::generic_category()), "Condition error")
{}
condition_error( int ev )
- : base_type(system::error_code(ev, system::system_category()), "Condition error")
+ : base_type(system::error_code(ev, system::generic_category()), "Condition error")
{
}
condition_error( int ev, const char * what_arg )
- : base_type(system::error_code(ev, system::system_category()), what_arg)
+ : base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
condition_error( int ev, const std::string & what_arg )
- : base_type(system::error_code(ev, system::system_category()), what_arg)
+ : base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
};
diff --git a/boost/thread/executors/executor.hpp b/boost/thread/executors/executor.hpp
index 96198201f0..1c751dd094 100644
--- a/boost/thread/executors/executor.hpp
+++ b/boost/thread/executors/executor.hpp
@@ -38,7 +38,7 @@ namespace boost
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
- virtual ~executor() {};
+ virtual ~executor() {}
/**
* \par Effects
diff --git a/boost/thread/executors/generic_executor_ref.hpp b/boost/thread/executors/generic_executor_ref.hpp
index da0382c160..1353dd3277 100644
--- a/boost/thread/executors/generic_executor_ref.hpp
+++ b/boost/thread/executors/generic_executor_ref.hpp
@@ -41,7 +41,7 @@ namespace boost
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
- ~executor_ref() {};
+ ~executor_ref() {}
/**
* \par Effects
diff --git a/boost/thread/executors/loop_executor.hpp b/boost/thread/executors/loop_executor.hpp
index b08ff76f57..aee7a8d477 100644
--- a/boost/thread/executors/loop_executor.hpp
+++ b/boost/thread/executors/loop_executor.hpp
@@ -16,6 +16,7 @@
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
+#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -41,14 +42,32 @@ namespace executors
*/
bool try_executing_one()
{
+ return execute_one(/*wait:*/false);
+ }
+
+ private:
+ /**
+ * Effects: Execute one task.
+ * Remark: If wait is true, waits until a task is available or the executor
+ * is closed. If wait is false, returns false immediately if no
+ * task is available.
+ * Returns: whether a task has been executed (if wait is true, only returns false if closed).
+ * Throws: whatever the current task constructor throws or the task() throws.
+ */
+ bool execute_one(bool wait)
+ {
work task;
try
{
- if (work_queue.try_pull(task) == queue_op_status::success)
+ queue_op_status status = wait ?
+ work_queue.wait_pull(task) :
+ work_queue.try_pull(task);
+ if (status == queue_op_status::success)
{
task();
return true;
}
+ BOOST_ASSERT(!wait || status == queue_op_status::closed);
return false;
}
catch (...)
@@ -57,21 +76,6 @@ namespace executors
//return false;
}
}
- private:
- /**
- * Effects: schedule one task or yields
- * Throws: whatever the current task constructor throws or the task() throws.
- */
- void schedule_one_or_yield()
- {
- if ( ! try_executing_one())
- {
- this_thread::yield();
- }
- }
-
-
-
public:
/// loop_executor is not copyable.
@@ -101,10 +105,10 @@ namespace executors
*/
void loop()
{
- while (!closed())
+ while (execute_one(/*wait:*/true))
{
- schedule_one_or_yield();
}
+ BOOST_ASSERT(closed());
while (try_executing_one())
{
}
diff --git a/boost/thread/future.hpp b/boost/thread/future.hpp
index b98ff3d338..59712c7e2f 100644
--- a/boost/thread/future.hpp
+++ b/boost/thread/future.hpp
@@ -1355,7 +1355,7 @@ namespace boost
boost::throw_exception(future_uninitialized());
}
return future_->mutex;
- };
+ }
notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
{
@@ -5656,5 +5656,5 @@ namespace detail
#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
}
-#endif // BOOST_NO_EXCEPTION
+#endif // BOOST_NO_EXCEPTIONS
#endif // header
diff --git a/boost/thread/futures/wait_for_all.hpp b/boost/thread/futures/wait_for_all.hpp
index 90cc2b77cb..398eb4adee 100644
--- a/boost/thread/futures/wait_for_all.hpp
+++ b/boost/thread/futures/wait_for_all.hpp
@@ -60,7 +60,7 @@ namespace boost
}
#else
template<typename F1, typename... Fs>
- void wait_for_all(F1& f1, Fs&... fs)
+ typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1, Fs&... fs)
{
bool dummy[] = { (f1.wait(), true), (fs.wait(), true)... };
diff --git a/boost/thread/pthread/condition_variable_fwd.hpp b/boost/thread/pthread/condition_variable_fwd.hpp
index 652a8c0baa..802a5cc674 100644
--- a/boost/thread/pthread/condition_variable_fwd.hpp
+++ b/boost/thread/pthread/condition_variable_fwd.hpp
@@ -17,6 +17,7 @@
#if defined BOOST_THREAD_USES_DATETIME
#include <boost/thread/xtime.hpp>
#endif
+
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
@@ -68,7 +69,20 @@ namespace boost
unique_lock<mutex>& lock,
struct timespec const &timeout)
{
- return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now()));
+#if ! defined BOOST_THREAD_USEFIXES_TIMESPEC
+ return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now()));
+#elif ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+ //using namespace chrono;
+ //nanoseconds ns = chrono::system_clock::now().time_since_epoch();
+
+ struct timespec ts = boost::detail::timespec_now_realtime();
+ //ts.tv_sec = static_cast<long>(chrono::duration_cast<chrono::seconds>(ns).count());
+ //ts.tv_nsec = static_cast<long>((ns - chrono::duration_cast<chrono::seconds>(ns)).count());
+ return do_wait_until(lock, boost::detail::timespec_plus(timeout, ts));
+#else
+ // old behavior was fine for monotonic
+ return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_realtime()));
+#endif
}
public:
diff --git a/boost/thread/pthread/timespec.hpp b/boost/thread/pthread/timespec.hpp
index 82f50f6ca7..74583ed0eb 100644
--- a/boost/thread/pthread/timespec.hpp
+++ b/boost/thread/pthread/timespec.hpp
@@ -75,6 +75,33 @@ namespace boost
{
timespec ts;
+#if defined CLOCK_MONOTONIC && defined BOOST_THREAD_USEFIXES_TIMESPEC
+ if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
+ {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
+ }
+#elif defined(BOOST_THREAD_TIMESPEC_MAC_API)
+ timeval tv;
+ ::gettimeofday(&tv, 0);
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+#else
+ if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
+ {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
+ }
+#endif
+ return ts;
+ }
+
+ inline timespec timespec_now_realtime()
+ {
+ timespec ts;
+
#if defined(BOOST_THREAD_TIMESPEC_MAC_API)
timeval tv;
::gettimeofday(&tv, 0);
@@ -83,6 +110,8 @@ namespace boost
#else
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
{
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
}
#endif
diff --git a/boost/thread/scoped_thread.hpp b/boost/thread/scoped_thread.hpp
index c2da919728..6cda931a5f 100644
--- a/boost/thread/scoped_thread.hpp
+++ b/boost/thread/scoped_thread.hpp
@@ -34,10 +34,10 @@ namespace boost
* boost::strict_scoped_thread<> t((boost::thread(F)));
*
*/
- template <class CallableThread = join_if_joinable>
+ template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
class strict_scoped_thread
{
- thread t_;
+ Thread t_;
struct dummy;
public:
@@ -47,13 +47,13 @@ namespace boost
*
*/
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type>
+ template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type>
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
#else
template <class F>
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f,
- typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type=0) :
+ typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type=0) :
t_(boost::forward<F>(f)) {}
template <class F, class A1>
strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
@@ -73,7 +73,7 @@ namespace boost
*
* Effects: move the thread to own @c t.
*/
- explicit strict_scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT :
+ explicit strict_scoped_thread(BOOST_THREAD_RV_REF(Thread) t) BOOST_NOEXCEPT :
t_(boost::move(t))
{
}
@@ -111,14 +111,15 @@ namespace boost
* t.interrupt();
*
*/
- template <class CallableThread = join_if_joinable>
+ template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
class scoped_thread
{
- thread t_;
+ Thread t_;
struct dummy;
public:
- typedef thread::id id;
+ typedef typename Thread::id id;
+ typedef typename Thread::native_handle_type native_handle_type;
BOOST_THREAD_MOVABLE_ONLY( scoped_thread) /// Movable only
@@ -137,13 +138,13 @@ namespace boost
*/
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type>
+ template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type>
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
#else
template <class F>
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f,
- typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type=0) :
+ typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type=0) :
t_(boost::forward<F>(f)) {}
template <class F, class A1>
scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
@@ -163,12 +164,12 @@ namespace boost
*
* Effects: move the thread to own @c t.
*/
- explicit scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT :
+ explicit scoped_thread(BOOST_THREAD_RV_REF(Thread) t) BOOST_NOEXCEPT :
t_(boost::move(t))
{
}
-// explicit operator thread()
+// explicit operator Thread()
// {
// return boost::move(t_);
// }
@@ -213,7 +214,7 @@ namespace boost
}
// forwarded thread functions
- inline thread::id get_id() const BOOST_NOEXCEPT
+ inline id get_id() const BOOST_NOEXCEPT
{
return t_.get_id();
}
@@ -242,7 +243,7 @@ namespace boost
}
#endif
- thread::native_handle_type native_handle()BOOST_NOEXCEPT
+ native_handle_type native_handle()BOOST_NOEXCEPT
{
return t_.native_handle();
}
@@ -266,13 +267,13 @@ namespace boost
static unsigned hardware_concurrency() BOOST_NOEXCEPT
{
- return thread::hardware_concurrency();
+ return Thread::hardware_concurrency();
}
#ifdef BOOST_THREAD_PROVIDES_PHYSICAL_CONCURRENCY
static unsigned physical_concurrency() BOOST_NOEXCEPT
{
- return thread::physical_concurrency();
+ return Thread::physical_concurrency();
}
#endif
};
@@ -280,12 +281,13 @@ namespace boost
/**
* Effects: swaps the contents of two scoped threads.
*/
- template <class Destroyer>
- void swap(scoped_thread<Destroyer>& lhs, scoped_thread<Destroyer>& rhs)
+ template <class Destroyer, class Thread >
+ void swap(scoped_thread<Destroyer, Thread>& lhs, scoped_thread<Destroyer, Thread>& rhs)
BOOST_NOEXCEPT {
return lhs.swap(rhs);
}
+ typedef scoped_thread<> joining_thread;
}
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/thread_functors.hpp b/boost/thread/thread_functors.hpp
index bba129f767..f134593ffe 100644
--- a/boost/thread/thread_functors.hpp
+++ b/boost/thread/thread_functors.hpp
@@ -21,15 +21,29 @@ namespace boost
struct detach
{
- void operator()(thread& t)
+ template <class Thread>
+ void operator()(Thread& t)
{
t.detach();
}
};
+ struct detach_if_joinable
+ {
+ template <class Thread>
+ void operator()(Thread& t)
+ {
+ if (t.joinable())
+ {
+ t.detach();
+ }
+ }
+ };
+
struct join_if_joinable
{
- void operator()(thread& t)
+ template <class Thread>
+ void operator()(Thread& t)
{
if (t.joinable())
{
@@ -41,7 +55,8 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
struct interrupt_and_join_if_joinable
{
- void operator()(thread& t)
+ template <class Thread>
+ void operator()(Thread& t)
{
if (t.joinable())
{
diff --git a/boost/thread/thread_guard.hpp b/boost/thread/thread_guard.hpp
index 85157f101e..64eb453c73 100644
--- a/boost/thread/thread_guard.hpp
+++ b/boost/thread/thread_guard.hpp
@@ -21,14 +21,14 @@ namespace boost
/**
* Non-copyable RAII scoped thread guard joiner which join the thread if joinable when destroyed.
*/
- template <class CallableThread = join_if_joinable>
+ template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
class thread_guard
{
- thread& t_;
+ Thread& t_;
public:
BOOST_THREAD_NO_COPYABLE( thread_guard)
- explicit thread_guard(thread& t) :
+ explicit thread_guard(Thread& t) :
t_(t)
{
}
diff --git a/boost/thread/win32/interlocked_read.hpp b/boost/thread/win32/interlocked_read.hpp
index 2ad3fe9017..775555e184 100644
--- a/boost/thread/win32/interlocked_read.hpp
+++ b/boost/thread/win32/interlocked_read.hpp
@@ -5,6 +5,7 @@
//
// (C) Copyright 2005-8 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
+// (C) Copyright 2017 Andrey Semashev
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -15,36 +16,172 @@
#include <boost/config/abi_prefix.hpp>
-#ifdef BOOST_MSVC
+// Define compiler barriers
+#if defined(__INTEL_COMPILER)
+#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() __memory_barrier()
+#elif defined(_MSC_VER) && !defined(_WIN32_WCE)
+extern "C" void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadWriteBarrier)
+#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() _ReadWriteBarrier()
+#endif
+
+#ifndef BOOST_THREAD_DETAIL_COMPILER_BARRIER
+#define BOOST_THREAD_DETAIL_COMPILER_BARRIER()
+#endif
+
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+
+// Since VS2005 and until VS2012 volatile reads always acquire and volatile writes are always release.
+// But VS2012 adds a compiler switch that can change behavior to the standard. On x86 though
+// the compiler generates a single instruction for the load/store, which is enough synchronization
+// as far as uarch is concerned. To prevent compiler reordering code around the load/store we add
+// compiler barriers.
namespace boost
{
namespace detail
{
- // Since VS2005 volatile reads always acquire
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
{
long const res=*x;
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
return res;
}
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
{
void* const res=*x;
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
return res;
}
- // Since VS2005 volatile writes always release
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
{
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
*x=value;
}
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
{
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
*x=value;
}
}
}
+#elif defined(_MSC_VER) && _MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64))
+
+#include <intrin.h>
+
+namespace boost
+{
+ namespace detail
+ {
+ inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
+ {
+ long const res=__iso_volatile_load32((const volatile __int32*)x);
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ return res;
+ }
+ inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
+ {
+ void* const res=
+#if defined(_M_ARM64)
+ __iso_volatile_load64((const volatile __int64*)x);
+#else
+ __iso_volatile_load32((const volatile __int32*)x);
+#endif
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ return res;
+ }
+
+ inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
+ {
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ __iso_volatile_store32((volatile __int32*)x, (__int32)value);
+ }
+ inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
+ {
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+#if defined(_M_ARM64)
+ __iso_volatile_store64((volatile __int64*)x, (__int64)value);
+#else
+ __iso_volatile_store32((volatile __int32*)x, (__int32)value);
+#endif
+ }
+ }
+}
+
+#elif defined(__GNUC__) && (((__GNUC__ * 100 + __GNUC_MINOR__) >= 407) || (defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) >= 302))
+
+namespace boost
+{
+ namespace detail
+ {
+ inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
+ {
+ return __atomic_load_n((long*)x, __ATOMIC_ACQUIRE);
+ }
+ inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
+ {
+ return __atomic_load_n((void**)x, __ATOMIC_ACQUIRE);
+ }
+
+ inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
+ {
+ __atomic_store_n((long*)x, value, __ATOMIC_RELEASE);
+ }
+ inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
+ {
+ __atomic_store_n((void**)x, value, __ATOMIC_RELEASE);
+ }
+ }
+}
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+namespace boost
+{
+ namespace detail
+ {
+ inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
+ {
+ long res;
+ __asm__ __volatile__ ("movl %1, %0" : "=r" (res) : "m" (*x) : "memory");
+ return res;
+ }
+ inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
+ {
+ void* res;
+#if defined(__x86_64__)
+ __asm__ __volatile__ ("movq %1, %0" : "=r" (res) : "m" (*x) : "memory");
+#else
+ __asm__ __volatile__ ("movl %1, %0" : "=r" (res) : "m" (*x) : "memory");
+#endif
+ return res;
+ }
+
+ inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
+ {
+ __asm__ __volatile__ ("movl %1, %0" : "=m" (*x) : "r" (value) : "memory");
+ }
+ inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
+ {
+#if defined(__x86_64__)
+ __asm__ __volatile__ ("movq %1, %0" : "=m" (*x) : "r" (value) : "memory");
+#else
+ __asm__ __volatile__ ("movl %1, %0" : "=m" (*x) : "r" (value) : "memory");
+#endif
+ }
+ }
+}
+
#else
namespace boost
@@ -53,19 +190,19 @@ namespace boost
{
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
{
- return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0);
+ return BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)x,0,0);
}
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
{
- return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
+ return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER((void**)x,0,0);
}
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
{
- BOOST_INTERLOCKED_EXCHANGE(x,value);
+ BOOST_INTERLOCKED_EXCHANGE((long*)x,value);
}
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
{
- BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
+ BOOST_INTERLOCKED_EXCHANGE_POINTER((void**)x,value);
}
}
}
diff --git a/boost/thread/win32/thread_primitives.hpp b/boost/thread/win32/thread_primitives.hpp
index c9e279faa0..133cc9c761 100644
--- a/boost/thread/win32/thread_primitives.hpp
+++ b/boost/thread/win32/thread_primitives.hpp
@@ -18,6 +18,7 @@
#include <boost/detail/interlocked.hpp>
#include <boost/detail/winapi/config.hpp>
//#include <boost/detail/winapi/synchronization.hpp>
+#include <boost/thread/win32/interlocked_read.hpp>
#include <algorithm>
#if BOOST_PLAT_WINDOWS_RUNTIME
@@ -244,19 +245,19 @@ namespace boost
// 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;
+ static long count = -1l;
unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone;
ticks_type current_tick64;
- previous_count = (unsigned long) _InterlockedCompareExchange(&count, 0, 0);
+ previous_count = (unsigned long) boost::detail::interlocked_read_acquire(&count);
current_tick32 = GetTickCount();
- if(previous_count == 0xFFFFFFFF)
+ if(previous_count == (unsigned long)-1l)
{
// count has never been written
unsigned long initial_count;
initial_count = current_tick32 >> 28;
- previous_count = (unsigned long) _InterlockedCompareExchange(&count, initial_count, 0xFFFFFFFF);
+ previous_count = (unsigned long) _InterlockedCompareExchange(&count, (long)initial_count, -1l);
current_tick64 = initial_count;
current_tick64 <<= 28;
@@ -279,8 +280,9 @@ namespace boost
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;
+ unsigned long new_count = previous_count + 1;
+ _InterlockedCompareExchange(&count, (long)new_count, (long)previous_count);
+ current_tick64 = new_count;
current_tick64 <<= 28;
current_tick64 += current_tick32 & 0x0FFFFFFF;
return current_tick64;