summaryrefslogtreecommitdiff
path: root/boost/thread
diff options
context:
space:
mode:
Diffstat (limited to 'boost/thread')
-rw-r--r--boost/thread/barrier.hpp260
-rw-r--r--boost/thread/caller_context.hpp56
-rw-r--r--boost/thread/completion_latch.hpp226
-rw-r--r--boost/thread/concurrent_queues/queue_adaptor.hpp209
-rwxr-xr-xboost/thread/concurrent_queues/queue_base.hpp202
-rw-r--r--boost/thread/concurrent_queues/queue_op_status.hpp46
-rw-r--r--boost/thread/concurrent_queues/queue_views.hpp165
-rw-r--r--boost/thread/condition.hpp7
-rw-r--r--boost/thread/csbl/deque.hpp45
-rw-r--r--boost/thread/csbl/functional.hpp49
-rw-r--r--boost/thread/csbl/list.hpp35
-rw-r--r--boost/thread/csbl/memory.hpp61
-rw-r--r--boost/thread/csbl/memory/allocator_arg.hpp41
-rw-r--r--boost/thread/csbl/memory/allocator_traits.hpp35
-rw-r--r--boost/thread/csbl/memory/config.hpp16
-rw-r--r--boost/thread/csbl/memory/default_delete.hpp41
-rw-r--r--boost/thread/csbl/memory/pointer_traits.hpp35
-rw-r--r--boost/thread/csbl/memory/scoped_allocator.hpp35
-rw-r--r--boost/thread/csbl/memory/shared_ptr.hpp42
-rw-r--r--boost/thread/csbl/memory/unique_ptr.hpp28
-rw-r--r--boost/thread/csbl/tuple.hpp49
-rw-r--r--boost/thread/csbl/vector.hpp35
-rw-r--r--boost/thread/cv_status.hpp2
-rw-r--r--boost/thread/detail/config.hpp353
-rw-r--r--boost/thread/detail/counter.hpp106
-rw-r--r--boost/thread/detail/delete.hpp19
-rw-r--r--boost/thread/detail/function_wrapper.hpp93
-rw-r--r--boost/thread/detail/invoke.hpp1604
-rw-r--r--boost/thread/detail/invoker.hpp754
-rw-r--r--boost/thread/detail/is_convertible.hpp49
-rw-r--r--boost/thread/detail/lockable_wrapper.hpp45
-rw-r--r--boost/thread/detail/log.hpp83
-rw-r--r--boost/thread/detail/make_tuple_indices.hpp224
-rw-r--r--boost/thread/detail/memory.hpp32
-rw-r--r--boost/thread/detail/move.hpp155
-rw-r--r--boost/thread/detail/nullary_function.hpp234
-rw-r--r--boost/thread/detail/thread.hpp324
-rw-r--r--boost/thread/detail/thread_group.hpp64
-rw-r--r--boost/thread/detail/thread_interruption.hpp5
-rw-r--r--boost/thread/detail/variadic_footer.hpp10
-rw-r--r--boost/thread/detail/variadic_header.hpp19
-rw-r--r--boost/thread/detail/work.hpp23
-rw-r--r--boost/thread/exceptional_ptr.hpp44
-rw-r--r--boost/thread/exceptions.hpp10
-rw-r--r--boost/thread/executor.hpp15
-rw-r--r--boost/thread/executors/basic_thread_pool.hpp317
-rw-r--r--boost/thread/executors/executor.hpp147
-rw-r--r--boost/thread/executors/executor_adaptor.hpp137
-rw-r--r--boost/thread/executors/generic_executor_ref.hpp211
-rw-r--r--boost/thread/executors/inline_executor.hpp131
-rw-r--r--boost/thread/executors/loop_executor.hpp204
-rw-r--r--boost/thread/executors/serial_executor.hpp214
-rw-r--r--boost/thread/executors/thread_executor.hpp136
-rw-r--r--boost/thread/executors/work.hpp43
-rw-r--r--boost/thread/externally_locked.hpp351
-rw-r--r--boost/thread/externally_locked_stream.hpp170
-rw-r--r--boost/thread/future.hpp4607
-rw-r--r--boost/thread/future_error_code.hpp61
-rw-r--r--boost/thread/is_locked_by_this_thread.hpp39
-rw-r--r--boost/thread/latch.hpp167
-rw-r--r--boost/thread/lock_algorithms.hpp468
-rw-r--r--boost/thread/lock_concepts.hpp197
-rw-r--r--boost/thread/lock_factories.hpp78
-rw-r--r--boost/thread/lock_guard.hpp88
-rw-r--r--boost/thread/lock_options.hpp31
-rw-r--r--boost/thread/lock_traits.hpp45
-rw-r--r--boost/thread/lock_types.hpp1230
-rw-r--r--boost/thread/lockable_adapter.hpp226
-rw-r--r--boost/thread/lockable_concepts.hpp157
-rw-r--r--boost/thread/lockable_traits.hpp207
-rw-r--r--boost/thread/locks.hpp1821
-rw-r--r--boost/thread/mutex.hpp34
-rw-r--r--boost/thread/null_mutex.hpp243
-rw-r--r--boost/thread/once.hpp11
-rw-r--r--boost/thread/ostream_buffer.hpp45
-rw-r--r--boost/thread/poly_lockable.hpp68
-rw-r--r--boost/thread/poly_lockable_adapter.hpp89
-rw-r--r--boost/thread/poly_shared_lockable.hpp135
-rw-r--r--boost/thread/poly_shared_lockable_adapter.hpp170
-rw-r--r--boost/thread/pthread/condition_variable.hpp114
-rw-r--r--boost/thread/pthread/condition_variable_fwd.hpp98
-rw-r--r--boost/thread/pthread/mutex.hpp142
-rw-r--r--boost/thread/pthread/once.hpp517
-rw-r--r--boost/thread/pthread/once_atomic.hpp313
-rw-r--r--boost/thread/pthread/recursive_mutex.hpp33
-rw-r--r--boost/thread/pthread/shared_mutex.hpp287
-rw-r--r--boost/thread/pthread/shared_mutex_assert.hpp724
-rw-r--r--boost/thread/pthread/thread_data.hpp119
-rw-r--r--boost/thread/pthread/thread_heap_alloc.hpp8
-rw-r--r--boost/thread/pthread/timespec.hpp108
-rw-r--r--boost/thread/recursive_mutex.hpp45
-rw-r--r--boost/thread/reverse_lock.hpp5
-rw-r--r--boost/thread/scoped_thread.hpp289
-rw-r--r--boost/thread/shared_lock_guard.hpp3
-rw-r--r--boost/thread/shared_mutex.hpp23
-rw-r--r--boost/thread/strict_lock.hpp235
-rw-r--r--boost/thread/sync_bounded_queue.hpp722
-rw-r--r--boost/thread/sync_queue.hpp663
-rw-r--r--boost/thread/synchronized_value.hpp1068
-rw-r--r--boost/thread/testable_mutex.hpp152
-rw-r--r--boost/thread/thread.hpp14
-rw-r--r--boost/thread/thread_functors.hpp57
-rw-r--r--boost/thread/thread_guard.hpp46
-rw-r--r--boost/thread/thread_only.hpp29
-rw-r--r--boost/thread/thread_pool.hpp15
-rw-r--r--boost/thread/tss.hpp16
-rw-r--r--boost/thread/user_scheduler.hpp202
-rwxr-xr-xboost/thread/v2/shared_mutex.hpp1062
-rw-r--r--boost/thread/v2/thread.hpp96
-rw-r--r--boost/thread/win32/basic_recursive_mutex.hpp10
-rw-r--r--boost/thread/win32/basic_timed_mutex.hpp30
-rw-r--r--boost/thread/win32/condition_variable.hpp72
-rw-r--r--boost/thread/win32/interlocked_read.hpp29
-rw-r--r--boost/thread/win32/mfc_thread_init.hpp40
-rw-r--r--boost/thread/win32/mutex.hpp9
-rw-r--r--boost/thread/win32/once.hpp971
-rw-r--r--boost/thread/win32/recursive_mutex.hpp9
-rw-r--r--boost/thread/win32/shared_mutex.hpp64
-rw-r--r--boost/thread/win32/thread_data.hpp140
-rw-r--r--boost/thread/win32/thread_heap_alloc.hpp103
-rw-r--r--boost/thread/win32/thread_primitives.hpp300
-rw-r--r--boost/thread/with_lock_guard.hpp234
-rw-r--r--boost/thread/xtime.hpp3
123 files changed, 24373 insertions, 3109 deletions
diff --git a/boost/thread/barrier.hpp b/boost/thread/barrier.hpp
index 4fd89883b8..47daf07b35 100644
--- a/boost/thread/barrier.hpp
+++ b/boost/thread/barrier.hpp
@@ -1,6 +1,7 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
// Copyright (C) 2007-8 Anthony Williams
+// (C) Copyright 2013 Vicente J. Botet Escriba
//
// 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)
@@ -9,55 +10,244 @@
#define BOOST_BARRIER_JDM030602_HPP
#include <boost/thread/detail/config.hpp>
-#include <boost/throw_exception.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/thread/mutex.hpp>
+#include <boost/thread/lock_types.hpp>
#include <boost/thread/condition_variable.hpp>
#include <string>
#include <stdexcept>
+#include <boost/thread/detail/nullary_function.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/utility/result_of.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
+ namespace thread_detail
+ {
+ typedef detail::nullary_function<void()> void_completion_function;
+ typedef detail::nullary_function<size_t()> size_completion_function;
+
+ struct default_barrier_reseter
+ {
+ unsigned int size_;
+ default_barrier_reseter(unsigned int size) :
+ size_(size)
+ {
+ }
+ BOOST_THREAD_MOVABLE(default_barrier_reseter)
+ //BOOST_THREAD_COPYABLE_AND_MOVABLE(default_barrier_reseter)
+
+ default_barrier_reseter(default_barrier_reseter const& other) BOOST_NOEXCEPT :
+ size_(other.size_)
+ {
+ }
+ default_barrier_reseter(BOOST_THREAD_RV_REF(default_barrier_reseter) other) BOOST_NOEXCEPT :
+ size_(BOOST_THREAD_RV(other).size_)
+ {
+ }
+
+ unsigned int operator()()
+ {
+ return size_;
+ }
+ };
+
+ struct void_functor_barrier_reseter
+ {
+ unsigned int size_;
+ void_completion_function fct_;
+ template <typename F>
+ void_functor_barrier_reseter(unsigned int size, BOOST_THREAD_RV_REF(F) funct)
+ : size_(size), fct_(boost::move(funct))
+ {}
+ template <typename F>
+ void_functor_barrier_reseter(unsigned int size, F& funct)
+ : size_(size), fct_(funct)
+ {}
- class barrier
+ BOOST_THREAD_MOVABLE(void_functor_barrier_reseter)
+ //BOOST_THREAD_COPYABLE_AND_MOVABLE(void_functor_barrier_reseter)
+
+ void_functor_barrier_reseter(void_functor_barrier_reseter const& other) BOOST_NOEXCEPT :
+ size_(other.size_), fct_(other.fct_)
+ {
+ }
+ void_functor_barrier_reseter(BOOST_THREAD_RV_REF(void_functor_barrier_reseter) other) BOOST_NOEXCEPT :
+ size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
+ //size_(BOOST_THREAD_RV(other).size_), fct_(boost::move(BOOST_THREAD_RV(other).fct_))
+ {
+ }
+
+ unsigned int operator()()
+ {
+ fct_();
+ return size_;
+ }
+ };
+ struct void_fct_ptr_barrier_reseter
{
- public:
- barrier(unsigned int count)
- : m_threshold(count), m_count(count), m_generation(0)
- {
- if (count == 0)
- boost::throw_exception(thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
- }
-
- bool wait()
- {
- boost::mutex::scoped_lock lock(m_mutex);
- unsigned int gen = m_generation;
-
- if (--m_count == 0)
- {
- m_generation++;
- m_count = m_threshold;
- m_cond.notify_all();
- return true;
- }
-
- while (gen == m_generation)
- m_cond.wait(lock);
- return false;
- }
-
- private:
- mutex m_mutex;
- condition_variable m_cond;
- unsigned int m_threshold;
- unsigned int m_count;
- unsigned int m_generation;
+ unsigned int size_;
+ void(*fct_)();
+ void_fct_ptr_barrier_reseter(unsigned int size, void(*funct)()) :
+ size_(size), fct_(funct)
+ {
+ }
+ BOOST_THREAD_MOVABLE(void_fct_ptr_barrier_reseter)
+ //BOOST_THREAD_COPYABLE_AND_MOVABLE(void_fct_ptr_barrier_reseter)
+
+ void_fct_ptr_barrier_reseter(void_fct_ptr_barrier_reseter const& other) BOOST_NOEXCEPT :
+ size_(other.size_), fct_(other.fct_)
+ {
+ }
+ void_fct_ptr_barrier_reseter(BOOST_THREAD_RV_REF(void_fct_ptr_barrier_reseter) other) BOOST_NOEXCEPT :
+ size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_)
+ {
+ }
+ unsigned int operator()()
+ {
+ fct_();
+ return size_;
+ }
};
+ }
+ //BOOST_THREAD_DCL_MOVABLE(thread_detail::default_barrier_reseter)
+ //BOOST_THREAD_DCL_MOVABLE(thread_detail::void_functor_barrier_reseter)
+ //BOOST_THREAD_DCL_MOVABLE(thread_detail::void_fct_ptr_barrier_reseter)
+
+ class barrier
+ {
+ static inline unsigned int check_counter(unsigned int count)
+ {
+ if (count == 0) boost::throw_exception(
+ thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero."));
+ return count;
+ }
+ struct dummy
+ {
+ };
+
+ public:
+ BOOST_THREAD_NO_COPYABLE( barrier)
+
+ explicit barrier(unsigned int count) :
+ m_count(check_counter(count)), m_generation(0), fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))
+ {
+ }
+
+ template <typename F>
+ barrier(
+ unsigned int count,
+ BOOST_THREAD_RV_REF(F) funct,
+ typename enable_if<
+ typename is_void<typename result_of<F>::type>::type, dummy*
+ >::type=0
+ )
+ : m_count(check_counter(count)),
+ m_generation(0),
+ fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count,
+ boost::move(funct)))
+ )
+ {
+ }
+ template <typename F>
+ barrier(
+ unsigned int count,
+ F &funct,
+ typename enable_if<
+ typename is_void<typename result_of<F>::type>::type, dummy*
+ >::type=0
+ )
+ : m_count(check_counter(count)),
+ m_generation(0),
+ fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count,
+ funct))
+ )
+ {
+ }
+
+ template <typename F>
+ barrier(
+ unsigned int count,
+ BOOST_THREAD_RV_REF(F) funct,
+ typename enable_if<
+ typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
+ >::type=0
+ )
+ : m_count(check_counter(count)),
+ m_generation(0),
+ fct_(boost::move(funct))
+ {
+ }
+ template <typename F>
+ barrier(
+ unsigned int count,
+ F& funct,
+ typename enable_if<
+ typename is_same<typename result_of<F>::type, unsigned int>::type, dummy*
+ >::type=0
+ )
+ : m_count(check_counter(count)),
+ m_generation(0),
+ fct_(funct)
+ {
+ }
+
+ barrier(unsigned int count, void(*funct)()) :
+ m_count(check_counter(count)), m_generation(0),
+ fct_(funct
+ ? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_fct_ptr_barrier_reseter(count, funct))))
+ : BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))))
+ )
+ {
+ }
+ barrier(unsigned int count, unsigned int(*funct)()) :
+ m_count(check_counter(count)), m_generation(0),
+ fct_(funct
+ ? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(funct))
+ : BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))))
+ )
+ {
+ }
+
+ bool wait()
+ {
+ boost::unique_lock < boost::mutex > lock(m_mutex);
+ unsigned int gen = m_generation;
+
+ if (--m_count == 0)
+ {
+ m_generation++;
+ m_count = static_cast<unsigned int>(fct_());
+ BOOST_ASSERT(m_count != 0);
+ m_cond.notify_all();
+ return true;
+ }
+
+ while (gen == m_generation)
+ m_cond.wait(lock);
+ return false;
+ }
+
+ void count_down_and_wait()
+ {
+ wait();
+ }
+
+ private:
+ mutex m_mutex;
+ condition_variable m_cond;
+ unsigned int m_count;
+ unsigned int m_generation;
+ thread_detail::size_completion_function fct_;
+ };
-} // namespace boost
+} // namespace boost
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/caller_context.hpp b/boost/thread/caller_context.hpp
new file mode 100644
index 0000000000..1e341686b0
--- /dev/null
+++ b/boost/thread/caller_context.hpp
@@ -0,0 +1,56 @@
+// (C) Copyright 2013 Vicente J. Botet Escriba
+// 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)
+
+
+#ifndef BOOST_THREAD_CALL_CONTEXT_HPP
+#define BOOST_THREAD_CALL_CONTEXT_HPP
+
+#include <boost/thread/detail/config.hpp>
+#if defined BOOST_THREAD_USES_LOG_THREAD_ID
+#include <boost/thread/thread.hpp>
+#endif
+#include <boost/current_function.hpp>
+#include <iomanip>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ struct caller_context_t
+ {
+ const char * filename;
+ unsigned lineno;
+ const char * func;
+ caller_context_t(const char * filename, unsigned lineno, const char * func) :
+ filename(filename), lineno(lineno), func(func)
+ {
+ }
+ };
+
+#define BOOST_CONTEXTOF boost::caller_context_t(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION)
+
+ template <typename OStream>
+ OStream& operator<<(OStream& os, caller_context_t const& ctx)
+ {
+#if defined BOOST_THREAD_USES_LOG_THREAD_ID
+ {
+ io::ios_flags_saver ifs( os );
+ os << std::left << std::setw(14) << boost::this_thread::get_id() << " ";
+ }
+#endif
+ {
+ io::ios_flags_saver ifs(os);
+ os << ctx.filename << "["
+ << std::setw(4) << std::right << std::dec<< ctx.lineno << "] ";
+ os << ctx.func << " " ;
+ }
+ return os;
+ }
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // header
diff --git a/boost/thread/completion_latch.hpp b/boost/thread/completion_latch.hpp
new file mode 100644
index 0000000000..ea76474276
--- /dev/null
+++ b/boost/thread/completion_latch.hpp
@@ -0,0 +1,226 @@
+// 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)
+// (C) Copyright 2013 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_COMPLETION_LATCH_HPP
+#define BOOST_THREAD_COMPLETION_LATCH_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/counter.hpp>
+
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/lock_types.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/chrono/duration.hpp>
+#include <boost/chrono/time_point.hpp>
+#include <boost/assert.hpp>
+//#include <boost/thread/detail/nullary_function.hpp>
+#include <boost/thread/csbl/functional.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ namespace thread_detail
+ {
+ void noop()
+ {
+ }
+ }
+ class completion_latch
+ {
+ public:
+ /// the implementation defined completion function type
+ //typedef detail::nullary_function<void()> completion_function;
+ typedef csbl::function<void()> completion_function;
+ /// noop completion function factory
+ static completion_function noop()
+ {
+ return completion_function(&thread_detail::noop);
+ }
+
+ private:
+ struct around_wait;
+ friend struct around_wait;
+ struct around_wait
+ {
+ completion_latch &that_;
+ boost::unique_lock<boost::mutex> &lk_;
+ around_wait(completion_latch &that, boost::unique_lock<boost::mutex> &lk)
+ : that_(that), lk_(lk)
+ {
+ that_.leavers_.cond_.wait(lk, detail::counter_is_zero(that_.leavers_));
+ that_.waiters_.inc_and_notify_all();
+ that_.leavers_.cond_.wait(lk, detail::counter_is_not_zero(that_.leavers_));
+ }
+ ~around_wait()
+ {
+ that_.waiters_.dec_and_notify_all();
+ }
+ };
+
+ bool count_down(unique_lock<mutex> &lk)
+ {
+ BOOST_ASSERT(count_ > 0);
+ if (--count_ == 0)
+ {
+ waiters_.cond_.wait(lk, detail::counter_is_not_zero(waiters_));
+ leavers_.assign_and_notify_all(waiters_);
+ count_.cond_.notify_all();
+ waiters_.cond_.wait(lk, detail::counter_is_zero(waiters_));
+ leavers_.assign_and_notify_all(0);
+ lk.unlock();
+ funct_();
+ return true;
+ }
+ return false;
+ }
+
+ public:
+ BOOST_THREAD_NO_COPYABLE( completion_latch )
+
+ /// Constructs a latch with a given count.
+ completion_latch(std::size_t count) :
+ count_(count), funct_(noop()), waiters_(0), leavers_(0)
+ {
+ }
+
+ /// Constructs a latch with a given count and a completion function.
+ template <typename F>
+ completion_latch(std::size_t count, BOOST_THREAD_RV_REF(F) funct) :
+ count_(count),
+ funct_(boost::move(funct)),
+ waiters_(0),
+ leavers_(0)
+ {
+ }
+ template <typename F>
+ completion_latch(std::size_t count, void(*funct)()) :
+ count_(count), funct_(funct), waiters_(0), leavers_(0)
+ {
+ }
+
+ ///
+ ~completion_latch()
+ {
+ }
+
+ /// Blocks until the latch has counted down to zero.
+ void wait()
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ around_wait aw(*this, lk);
+ count_.cond_.wait(lk, detail::counter_is_zero(count_));
+ }
+
+ /// @return true if the internal counter is already 0, false otherwise
+ bool try_wait()
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ around_wait aw(*this, lk);
+ return (count_ == 0);
+ }
+
+ /// try to wait for a specified amount of time
+ /// @return whether there is a timeout or not.
+ template <class Rep, class Period>
+ cv_status wait_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ around_wait aw(*this, lk);
+ return count_.cond_.wait_for(lk, rel_time, detail::counter_is_zero(count_))
+ ? cv_status::no_timeout
+ : cv_status::timeout;
+ }
+
+ /// try to wait until the specified time_point is reached
+ /// @return whether there is a timeout or not.
+ template <class Clock, class Duration>
+ cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ around_wait aw(*this, lk);
+ return count_.cond_.wait_until(lk, abs_time, detail::counter_is_zero(count_))
+ ? cv_status::no_timeout
+ : cv_status::timeout;
+ }
+
+ /// Decrement the count and notify anyone waiting if we reach zero.
+ /// @Requires count must be greater than 0
+ void count_down()
+ {
+ unique_lock<mutex> lk(mutex_);
+ count_down(lk);
+ }
+ void signal()
+ {
+ count_down();
+ }
+
+ /// Decrement the count and notify anyone waiting if we reach zero.
+ /// Blocks until the latch has counted down to zero.
+ /// @Requires count must be greater than 0
+ void count_down_and_wait()
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ if (count_down(lk))
+ {
+ return;
+ }
+ around_wait aw(*this, lk);
+ count_.cond_.wait(lk, detail::counter_is_zero(count_));
+ }
+ void sync()
+ {
+ count_down_and_wait();
+ }
+
+ /// Reset the counter
+ /// #Requires This method may only be invoked when there are no other threads currently inside the count_down_and_wait() method.
+ void reset(std::size_t count)
+ {
+ boost::lock_guard<boost::mutex> lk(mutex_);
+ //BOOST_ASSERT(count_ == 0);
+ count_ = count;
+ }
+
+ /// Resets the latch with the new completion function.
+ /// The next time the internal count reaches 0, this function will be invoked.
+ /// This completion function may only be invoked when there are no other threads
+ /// currently inside the count_down and wait related functions.
+ /// It may also be invoked from within the registered completion function.
+ /// @Returns the old completion function if any or noop if
+
+#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
+ template <typename F>
+ completion_function then(BOOST_THREAD_RV_REF(F) funct)
+ {
+ boost::lock_guard<boost::mutex> lk(mutex_);
+ completion_function tmp(funct_);
+ funct_ = boost::move(funct);
+ return tmp;
+ }
+#endif
+ completion_function then(void(*funct)())
+ {
+ boost::lock_guard<boost::mutex> lk(mutex_);
+ completion_function tmp(funct_);
+ funct_ = completion_function(funct);
+ return tmp;
+ }
+
+ private:
+ mutex mutex_;
+ detail::counter count_;
+ completion_function funct_;
+ detail::counter waiters_;
+ detail::counter leavers_;
+ };
+
+} // namespace boost
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/concurrent_queues/queue_adaptor.hpp b/boost/thread/concurrent_queues/queue_adaptor.hpp
new file mode 100644
index 0000000000..c729276f99
--- /dev/null
+++ b/boost/thread/concurrent_queues/queue_adaptor.hpp
@@ -0,0 +1,209 @@
+#ifndef BOOST_THREAD_QUEUE_ADAPTOR_HPP
+#define BOOST_THREAD_QUEUE_ADAPTOR_HPP
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2014. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/concurrent_queues/queue_op_status.hpp>
+#include <boost/thread/concurrent_queues/queue_base.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+namespace concurrent
+{
+namespace detail
+{
+
+ template <typename Queue>
+ class queue_adaptor_copyable_only :
+ public boost::queue_base<typename Queue::value_type>
+ {
+ Queue queue;
+ public:
+ typedef typename Queue::value_type value_type;
+ typedef std::size_t size_type;
+
+ // Constructors/Assignment/Destructors
+ queue_adaptor_copyable_only() {}
+
+ // Observers
+ bool empty() const { return queue.empty(); }
+ bool full() const { return queue.full(); }
+ size_type size() const { return queue.size(); }
+ bool closed() const { return queue.closed(); }
+
+ // Modifiers
+ void close() { queue.close(); }
+
+ void push_back(const value_type& x) { queue.push_back(x); }
+
+ void pull_front(value_type& x) { queue.pull_front(x); };
+ value_type pull_front() { return queue.pull_front(); }
+
+ queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
+ queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
+
+ queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
+ queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
+
+ queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
+ queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
+
+ };
+ template <typename Queue>
+ class queue_adaptor_movable_only :
+ public boost::queue_base<typename Queue::value_type>
+ {
+ Queue queue;
+ public:
+ typedef typename Queue::value_type value_type;
+ typedef std::size_t size_type;
+
+ // Constructors/Assignment/Destructors
+
+ queue_adaptor_movable_only() {}
+
+ // Observers
+ bool empty() const { return queue.empty(); }
+ bool full() const { return queue.full(); }
+ size_type size() const { return queue.size(); }
+ bool closed() const { return queue.closed(); }
+
+ // Modifiers
+ void close() { queue.close(); }
+
+
+ void pull_front(value_type& x) { queue.pull_front(x); };
+ // enable_if is_nothrow_copy_movable<value_type>
+ value_type pull_front() { return queue.pull_front(); }
+
+ queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
+
+ queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
+
+ queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
+
+ void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
+ queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
+ queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
+ queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
+ };
+
+ template <typename Queue>
+ class queue_adaptor_copyable_and_movable :
+ public boost::queue_base<typename Queue::value_type>
+ {
+ Queue queue;
+ public:
+ typedef typename Queue::value_type value_type;
+ typedef std::size_t size_type;
+
+ // Constructors/Assignment/Destructors
+
+ queue_adaptor_copyable_and_movable() {}
+
+ // Observers
+ bool empty() const { return queue.empty(); }
+ bool full() const { return queue.full(); }
+ size_type size() const { return queue.size(); }
+ bool closed() const { return queue.closed(); }
+
+ // Modifiers
+ void close() { queue.close(); }
+
+
+ void push_back(const value_type& x) { queue.push_back(x); }
+
+ void pull_front(value_type& x) { queue.pull_front(x); };
+ // enable_if is_nothrow_copy_movable<value_type>
+ value_type pull_front() { return queue.pull_front(); }
+
+ queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); }
+ queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
+
+ queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); }
+ queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
+
+ queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); }
+ queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
+
+ void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); }
+ queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); }
+ queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); }
+ queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); }
+ };
+
+
+ template <class Q, class T,
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#if defined __GNUC__
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
+ bool Copyable = is_copy_constructible<T>::value,
+ bool Movable = true
+#else
+ bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
+ bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
+#endif // __GNUC__
+#elif defined _MSC_VER
+#if _MSC_VER < 1700
+ bool Copyable = is_copy_constructible<T>::value,
+ bool Movable = true
+#else
+ bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
+ bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
+#endif // _MSC_VER
+#else
+ bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
+ bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
+#endif
+#else
+ bool Copyable = is_copy_constructible<T>::value,
+ bool Movable = has_move_emulation_enabled<T>::value
+#endif
+ >
+ struct queue_adaptor;
+
+ template <class Q, class T>
+ struct queue_adaptor<Q, T, true, true> {
+ typedef queue_adaptor_copyable_and_movable<Q> type;
+ };
+ template <class Q, class T>
+ struct queue_adaptor<Q, T, true, false> {
+ typedef queue_adaptor_copyable_only<Q> type;
+ };
+ template <class Q, class T>
+ struct queue_adaptor<Q, T, false, true> {
+ typedef queue_adaptor_movable_only<Q> type;
+ };
+
+}
+
+ template <typename Queue>
+ class queue_adaptor :
+ public detail::queue_adaptor<Queue, typename Queue::value_type>::type
+ {
+ public:
+ typedef typename Queue::value_type value_type;
+ typedef std::size_t size_type;
+ // Constructors/Assignment/Destructors
+ virtual ~queue_adaptor() {};
+ };
+}
+using concurrent::queue_adaptor;
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/concurrent_queues/queue_base.hpp b/boost/thread/concurrent_queues/queue_base.hpp
new file mode 100755
index 0000000000..5ed14fd393
--- /dev/null
+++ b/boost/thread/concurrent_queues/queue_base.hpp
@@ -0,0 +1,202 @@
+#ifndef BOOST_THREAD_QUEUE_BASE_HPP
+#define BOOST_THREAD_QUEUE_BASE_HPP
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2014. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/concurrent_queues/queue_op_status.hpp>
+#include <boost/type_traits/conditional.hpp>
+#include <boost/type_traits/is_copy_constructible.hpp>
+
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+namespace concurrent
+{
+namespace detail
+{
+
+ template <typename ValueType>
+ class queue_base_copyable_only
+ {
+ public:
+ typedef ValueType value_type;
+ typedef std::size_t size_type;
+
+ // Constructors/Assignment/Destructors
+ virtual ~queue_base_copyable_only() {};
+
+ // Observers
+ virtual bool empty() const = 0;
+ virtual bool full() const = 0;
+ virtual size_type size() const = 0;
+ virtual bool closed() const = 0;
+
+ // Modifiers
+ virtual void close() = 0;
+
+ virtual void push_back(const value_type& x) = 0;
+
+ virtual void pull_front(value_type&) = 0;
+ virtual value_type pull_front() = 0;
+
+ virtual queue_op_status try_push_back(const value_type& x) = 0;
+ virtual queue_op_status try_pull_front(value_type&) = 0;
+
+ virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
+ virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
+
+ virtual queue_op_status wait_push_back(const value_type& x) = 0;
+ virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
+
+ };
+
+ template <typename ValueType>
+ class queue_base_movable_only
+ {
+ public:
+ typedef ValueType value_type;
+ typedef std::size_t size_type;
+ // Constructors/Assignment/Destructors
+ virtual ~queue_base_movable_only() {};
+
+ // Observers
+ virtual bool empty() const = 0;
+ virtual bool full() const = 0;
+ virtual size_type size() const = 0;
+ virtual bool closed() const = 0;
+
+ // Modifiers
+ virtual void close() = 0;
+
+ virtual void pull_front(value_type&) = 0;
+ // enable_if is_nothrow_movable<value_type>
+ virtual value_type pull_front() = 0;
+
+ virtual queue_op_status try_pull_front(value_type&) = 0;
+
+ virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
+
+ virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
+
+ virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
+ virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
+ virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
+ virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
+ };
+
+
+ template <typename ValueType>
+ class queue_base_copyable_and_movable
+ {
+ public:
+ typedef ValueType value_type;
+ typedef std::size_t size_type;
+ // Constructors/Assignment/Destructors
+ virtual ~queue_base_copyable_and_movable() {};
+
+
+ // Observers
+ virtual bool empty() const = 0;
+ virtual bool full() const = 0;
+ virtual size_type size() const = 0;
+ virtual bool closed() const = 0;
+
+ // Modifiers
+ virtual void close() = 0;
+
+ virtual void push_back(const value_type& x) = 0;
+
+ virtual void pull_front(value_type&) = 0;
+ // enable_if is_nothrow_copy_movable<value_type>
+ virtual value_type pull_front() = 0;
+
+ virtual queue_op_status try_push_back(const value_type& x) = 0;
+ virtual queue_op_status try_pull_front(value_type&) = 0;
+
+ virtual queue_op_status nonblocking_push_back(const value_type& x) = 0;
+ virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
+
+ virtual queue_op_status wait_push_back(const value_type& x) = 0;
+ virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
+
+ virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
+ virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
+ virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
+ virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0;
+ };
+
+ template <class T,
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#if defined __GNUC__
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
+ bool Copyable = is_copy_constructible<T>::value,
+ bool Movable = true
+#else
+ bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
+ bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
+#endif // __GNUC__
+#elif defined _MSC_VER
+#if _MSC_VER < 1700
+ bool Copyable = is_copy_constructible<T>::value,
+ bool Movable = true
+#else
+ bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
+ bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
+#endif // _MSC_VER
+#else
+ bool Copyable = std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
+ bool Movable = std::is_move_constructible<T>::value && std::is_move_assignable<T>::value
+#endif
+#else
+ bool Copyable = is_copy_constructible<T>::value,
+ bool Movable = has_move_emulation_enabled<T>::value
+#endif
+ >
+ struct queue_base;
+
+ template <class T>
+ struct queue_base<T, true, true> {
+ typedef queue_base_copyable_and_movable<T> type;
+ };
+ template <class T>
+ struct queue_base<T, true, false> {
+ typedef queue_base_copyable_only<T> type;
+ };
+ template <class T>
+ struct queue_base<T, false, true> {
+ typedef queue_base_movable_only<T> type;
+ };
+
+}
+
+ template <typename ValueType>
+ class queue_base :
+ public detail::queue_base<ValueType>::type
+ {
+ public:
+ typedef ValueType value_type;
+ typedef std::size_t size_type;
+ // Constructors/Assignment/Destructors
+ virtual ~queue_base() {};
+ };
+
+}
+using concurrent::queue_base;
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/concurrent_queues/queue_op_status.hpp b/boost/thread/concurrent_queues/queue_op_status.hpp
new file mode 100644
index 0000000000..3a8f0d994d
--- /dev/null
+++ b/boost/thread/concurrent_queues/queue_op_status.hpp
@@ -0,0 +1,46 @@
+#ifndef BOOST_THREAD_QUEUE_OP_STATUS_HPP
+#define BOOST_THREAD_QUEUE_OP_STATUS_HPP
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2014. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/move.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+namespace concurrent
+{
+
+ BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status)
+ { success = 0, empty, full, closed, busy }
+ BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
+
+ struct sync_queue_is_closed : std::exception
+ {
+ };
+
+}
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ struct no_block_tag{};
+ BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {};
+#endif
+
+ using concurrent::queue_op_status;
+ using concurrent::sync_queue_is_closed;
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/concurrent_queues/queue_views.hpp b/boost/thread/concurrent_queues/queue_views.hpp
new file mode 100644
index 0000000000..1c06af8297
--- /dev/null
+++ b/boost/thread/concurrent_queues/queue_views.hpp
@@ -0,0 +1,165 @@
+#ifndef BOOST_THREAD_QUEUE_VIEWS_HPP
+#define BOOST_THREAD_QUEUE_VIEWS_HPP
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2014. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/concurrent_queues/queue_op_status.hpp>
+#include <boost/thread/concurrent_queues/queue_base.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+namespace concurrent
+{
+
+ template <typename Queue>
+ class queue_back_view
+ {
+ Queue* queue;
+ public:
+ typedef typename Queue::value_type value_type;
+ typedef typename Queue::size_type size_type;
+
+ // Constructors/Assignment/Destructors
+ queue_back_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
+
+ // Observers
+ bool empty() const { return queue->empty(); }
+ bool full() const { return queue->full(); }
+ size_type size() const { return queue->size(); }
+ bool closed() const { return queue->closed(); }
+
+ // Modifiers
+ void close() { queue->close(); }
+
+ void push(const value_type& x) { queue->push_back(x); }
+
+ void pull(value_type& x) { queue->pull_back(x); }
+ // enable_if is_nothrow_copy_movable<value_type>
+ value_type pull() { return queue->pull_back(); }
+
+ queue_op_status try_push(const value_type& x) { return queue->try_push_back(x); }
+
+ queue_op_status try_pull(value_type& x) { return queue->try_pull_back(x); }
+
+ queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_back(x); }
+
+ queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_back(x); }
+
+ queue_op_status wait_push(const value_type& x) { return queue->wait_push_back(x); }
+ queue_op_status wait_pull(value_type& x) { return queue->wait_pull_back(x); }
+
+ void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_back(boost::move(x)); }
+ queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_back(boost::move(x)); }
+ queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_back(boost::move(x)); }
+ queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_back(boost::move(x)); }
+ };
+
+ template <typename Queue>
+ class queue_front_view
+ {
+ Queue* queue;
+ public:
+ typedef typename Queue::value_type value_type;
+ typedef typename Queue::size_type size_type;
+
+ // Constructors/Assignment/Destructors
+ queue_front_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {}
+
+ // Observers
+ bool empty() const { return queue->empty(); }
+ bool full() const { return queue->full(); }
+ size_type size() const { return queue->size(); }
+ bool closed() const { return queue->closed(); }
+
+ // Modifiers
+ void close() { queue->close(); }
+
+ void push(const value_type& x) { queue->push_front(x); }
+
+ void pull(value_type& x) { queue->pull_front(x); };
+ // enable_if is_nothrow_copy_movable<value_type>
+ value_type pull() { return queue->pull_front(); }
+
+ queue_op_status try_push(const value_type& x) { return queue->try_push_front(x); }
+
+ queue_op_status try_pull(value_type& x) { return queue->try_pull_front(x); }
+
+ queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_front(x); }
+
+ queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_front(x); }
+
+ queue_op_status wait_push(const value_type& x) { return queue->wait_push_front(x); }
+ queue_op_status wait_pull(value_type& x) { return queue->wait_pull_front(x); }
+ void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_front(forward<value_type>(x)); }
+ queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_front(forward<value_type>(x)); }
+ queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_front(forward<value_type>(x)); }
+ queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_front(forward<value_type>(x)); }
+
+ };
+
+#if ! defined BOOST_NO_CXX11_TEMPLATE_ALIASES
+
+ template <class T>
+ using queue_back = queue_back_view<queue_base<T> > ;
+ template <class T>
+ using queue_front = queue_front_view<queue_base<T> > ;
+
+#else
+
+ template <class T>
+ struct queue_back : queue_back_view<queue_base<T> >
+ {
+ typedef queue_back_view<queue_base<T> > base_type;
+ queue_back(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
+ };
+ template <class T>
+ struct queue_front : queue_front_view<queue_base<T> >
+ {
+ typedef queue_front_view<queue_base<T> > base_type;
+ queue_front(queue_base<T>& q) BOOST_NOEXCEPT : base_type(q) {}
+
+ };
+
+#endif
+
+// template <class Queue>
+// queue_back_view<Queue> back(Queue & q) { return queue_back_view<Queue>(q); }
+// template <class Queue>
+// queue_front_view<Queue> front(Queue & q) { return queue_front_view<Queue>(q); }
+//#if 0
+// template <class T>
+// queue_back<T> back(queue_base<T> & q) { return queue_back<T>(q); }
+// template <class T>
+// queue_front<T> front(queue_base<T> & q) { return queue_front<T>(q); }
+//#else
+// template <class T>
+// typename queue_back<T>::type back(queue_base<T> & q) { return typename queue_back<T>::type(q); }
+// template <class T>
+// typename queue_front<T>::type front(queue_base<T> & q) { return typename queue_front<T>::type(q); }
+//#endif
+}
+
+using concurrent::queue_back_view;
+using concurrent::queue_front_view;
+using concurrent::queue_back;
+using concurrent::queue_front;
+//using concurrent::back;
+//using concurrent::front;
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/condition.hpp b/boost/thread/condition.hpp
index 35b879fe03..9567df9825 100644
--- a/boost/thread/condition.hpp
+++ b/boost/thread/condition.hpp
@@ -1,11 +1,15 @@
#ifndef BOOST_THREAD_CONDITION_HPP
#define BOOST_THREAD_CONDITION_HPP
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007 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)
+#include <boost/thread/detail/config.hpp>
+
+#if defined BOOST_THREAD_PROVIDES_CONDITION
+
#include <boost/thread/condition_variable.hpp>
namespace boost
@@ -14,3 +18,4 @@ namespace boost
}
#endif
+#endif
diff --git a/boost/thread/csbl/deque.hpp b/boost/thread/csbl/deque.hpp
new file mode 100644
index 0000000000..1e48903b1c
--- /dev/null
+++ b/boost/thread/csbl/deque.hpp
@@ -0,0 +1,45 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_DEQUE_HPP
+#define BOOST_CSBL_DEQUE_HPP
+
+#include <boost/config.hpp>
+// MSVC has some trouble instantiating a non_copyable type
+//C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(606) : error C2248: 'non_copyable::non_copyable' : cannot access private member declared in class 'non_copyable'
+// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(24) : see declaration of 'non_copyable::non_copyable'
+// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(23) : see declaration of 'non_copyable'
+// C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
+// with
+// [
+// _Ty=non_copyable
+// ]
+#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_HDR_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
+#ifndef BOOST_THREAD_USES_BOOST_DEQUE
+#define BOOST_THREAD_USES_BOOST_DEQUE
+#endif
+#include <boost/container/deque.hpp>
+#else
+#include <deque>
+#endif
+
+namespace boost
+{
+ namespace csbl
+ {
+#if defined BOOST_THREAD_USES_BOOST_DEQUE
+ using ::boost::container::deque;
+
+#else
+ using ::std::deque;
+
+#endif
+
+ }
+}
+#endif // header
diff --git a/boost/thread/csbl/functional.hpp b/boost/thread/csbl/functional.hpp
new file mode 100644
index 0000000000..7a7e928b70
--- /dev/null
+++ b/boost/thread/csbl/functional.hpp
@@ -0,0 +1,49 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_FUNCTIONAL_HPP
+#define BOOST_CSBL_FUNCTIONAL_HPP
+
+#include <boost/config.hpp>
+
+#include <functional>
+
+#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL || defined BOOST_NO_CXX11_HDR_FUNCTIONAL || defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifndef BOOST_THREAD_USES_BOOST_FUNCTIONAL
+#define BOOST_THREAD_USES_BOOST_FUNCTIONAL
+#endif
+#include <boost/function.hpp>
+#endif
+
+namespace boost
+{
+ namespace csbl
+ {
+#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL
+ using ::boost::function;
+#else
+ // D.8.1, base (deprecated):
+ // 20.9.3, reference_wrapper:
+ // 20.9.4, arithmetic operations:
+ // 20.9.5, comparisons:
+ // 20.9.6, logical operations:
+ // 20.9.7, bitwise operations:
+ // 20.9.8, negators:
+ // 20.9.9, bind:
+ // D.9, binders (deprecated):
+ // D.8.2.1, adaptors (deprecated):
+ // D.8.2.2, adaptors (deprecated):
+ // 20.9.10, member function adaptors:
+ // 20.9.11 polymorphic function wrappers:
+ using ::std::function;
+ // 20.9.12, hash function primary template:
+#endif
+
+ }
+}
+#endif // header
diff --git a/boost/thread/csbl/list.hpp b/boost/thread/csbl/list.hpp
new file mode 100644
index 0000000000..c7f10a18d5
--- /dev/null
+++ b/boost/thread/csbl/list.hpp
@@ -0,0 +1,35 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_LIST_HPP
+#define BOOST_CSBL_LIST_HPP
+
+#include <boost/config.hpp>
+
+#if defined BOOST_THREAD_USES_BOOST_LIST || defined BOOST_NO_CXX11_HDR_LIST || defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifndef BOOST_THREAD_USES_BOOST_LIST
+#define BOOST_THREAD_USES_BOOST_LIST
+#endif
+#include <boost/container/list.hpp>
+#else
+#include <list>
+#endif
+
+namespace boost
+{
+ namespace csbl
+ {
+#if defined BOOST_THREAD_USES_BOOST_LIST
+ using ::boost::container::list;
+#else
+ using ::std::list;
+#endif
+
+ }
+}
+#endif // header
diff --git a/boost/thread/csbl/memory.hpp b/boost/thread/csbl/memory.hpp
new file mode 100644
index 0000000000..e076f11ad3
--- /dev/null
+++ b/boost/thread/csbl/memory.hpp
@@ -0,0 +1,61 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_MEMORY_HPP
+#define BOOST_CSBL_MEMORY_HPP
+
+// 20.7.2 Header <memory> synopsis
+
+// 20.7.3, pointer traits
+#include <boost/thread/csbl/memory/pointer_traits.hpp>
+
+// 20.7.4, pointer safety
+// 20.7.5, pointer alignment function
+
+// 20.7.6, allocator argument tag
+#include <boost/thread/csbl/memory/allocator_arg.hpp>
+
+// 20.7.8, allocator traits
+#include <boost/thread/csbl/memory/allocator_traits.hpp>
+
+// 20.7.7, uses_allocator
+#include <boost/thread/csbl/memory/scoped_allocator.hpp>
+
+// 20.7.9, the default allocator:
+namespace boost
+{
+ namespace csbl
+ {
+ using ::std::allocator;
+ }
+}
+// 20.7.10, raw storage iterator:
+// 20.7.11, temporary buffers:
+// 20.7.12, specialized algorithms:
+
+// 20.8.1 class template unique_ptr:
+// default_delete
+#include <boost/thread/csbl/memory/default_delete.hpp>
+#include <boost/thread/csbl/memory/unique_ptr.hpp>
+
+// 20.8.2.1, class bad_weak_ptr:
+// 20.8.2.2, class template shared_ptr:
+// 20.8.2.2.6, shared_ptr creation
+// 20.8.2.2.7, shared_ptr comparisons:
+// 20.8.2.2.8, shared_ptr specialized algorithms:
+// 20.8.2.2.9, shared_ptr casts:
+// 20.8.2.2.10, shared_ptr get_deleter:
+// 20.8.2.2.11, shared_ptr I/O:
+// 20.8.2.3, class template weak_ptr:
+// 20.8.2.3.6, weak_ptr specialized algorithms:
+// 20.8.2.3.7, class template owner_less:
+// 20.8.2.4, class template enable_shared_from_this:
+// 20.8.2.5, shared_ptr atomic access:
+// 20.8.2.6 hash support
+
+#endif // header
diff --git a/boost/thread/csbl/memory/allocator_arg.hpp b/boost/thread/csbl/memory/allocator_arg.hpp
new file mode 100644
index 0000000000..354cdaee88
--- /dev/null
+++ b/boost/thread/csbl/memory/allocator_arg.hpp
@@ -0,0 +1,41 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP
+#define BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP
+
+#include <boost/thread/csbl/memory/config.hpp>
+
+// 20.7.6, allocator argument tag
+#if defined BOOST_NO_CXX11_ALLOCATOR
+#include <boost/container/scoped_allocator.hpp>
+
+namespace boost
+{
+ namespace csbl
+ {
+ using ::boost::container::allocator_arg_t;
+ using ::boost::container::allocator_arg;
+ }
+}
+#else
+namespace boost
+{
+ namespace csbl
+ {
+ using ::std::allocator_arg_t;
+ using ::std::allocator_arg;
+ }
+}
+#endif // BOOST_NO_CXX11_ALLOCATOR
+namespace boost
+{
+ using ::boost::csbl::allocator_arg_t;
+ using ::boost::csbl::allocator_arg;
+}
+#endif // header
diff --git a/boost/thread/csbl/memory/allocator_traits.hpp b/boost/thread/csbl/memory/allocator_traits.hpp
new file mode 100644
index 0000000000..3737cd85de
--- /dev/null
+++ b/boost/thread/csbl/memory/allocator_traits.hpp
@@ -0,0 +1,35 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP
+#define BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP
+
+#include <boost/thread/csbl/memory/config.hpp>
+
+// 20.7.8, allocator traits
+#if defined BOOST_NO_CXX11_ALLOCATOR
+#include <boost/container/allocator_traits.hpp>
+
+namespace boost
+{
+ namespace csbl
+ {
+ using ::boost::container::allocator_traits;
+ }
+}
+#else
+namespace boost
+{
+ namespace csbl
+ {
+ using ::std::allocator_traits;
+ }
+}
+#endif // BOOST_NO_CXX11_POINTER_TRAITS
+
+#endif // header
diff --git a/boost/thread/csbl/memory/config.hpp b/boost/thread/csbl/memory/config.hpp
new file mode 100644
index 0000000000..7b0596ac49
--- /dev/null
+++ b/boost/thread/csbl/memory/config.hpp
@@ -0,0 +1,16 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_MEMORY_CONFIG_HPP
+#define BOOST_CSBL_MEMORY_CONFIG_HPP
+
+#include <boost/config.hpp>
+
+#include <memory>
+
+#endif // header
diff --git a/boost/thread/csbl/memory/default_delete.hpp b/boost/thread/csbl/memory/default_delete.hpp
new file mode 100644
index 0000000000..d20153b309
--- /dev/null
+++ b/boost/thread/csbl/memory/default_delete.hpp
@@ -0,0 +1,41 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_MEMORY_DEFAULT_DELETE_HPP
+#define BOOST_CSBL_MEMORY_DEFAULT_DELETE_HPP
+
+#include <boost/thread/csbl/memory/config.hpp>
+
+// 20.8.1 class template unique_ptr:
+// default_delete
+
+#if defined BOOST_NO_CXX11_SMART_PTR
+#include <boost/move/unique_ptr.hpp>
+
+namespace boost
+{
+ namespace csbl
+ {
+ using ::boost::movelib::default_delete;
+ }
+}
+#else
+namespace boost
+{
+ namespace csbl
+ {
+ using ::std::default_delete;
+ }
+}
+#endif // defined BOOST_NO_CXX11_SMART_PTR
+
+namespace boost
+{
+ using ::boost::csbl::default_delete;
+}
+#endif // header
diff --git a/boost/thread/csbl/memory/pointer_traits.hpp b/boost/thread/csbl/memory/pointer_traits.hpp
new file mode 100644
index 0000000000..320f8e9e77
--- /dev/null
+++ b/boost/thread/csbl/memory/pointer_traits.hpp
@@ -0,0 +1,35 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP
+#define BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP
+
+#include <boost/thread/csbl/memory/config.hpp>
+
+// 20.7.3, pointer traits
+#if defined BOOST_NO_CXX11_ALLOCATOR
+#include <boost/intrusive/pointer_traits.hpp>
+
+namespace boost
+{
+ namespace csbl
+ {
+ using ::boost::intrusive::pointer_traits;
+ }
+}
+#else
+namespace boost
+{
+ namespace csbl
+ {
+ using ::std::pointer_traits;
+ }
+}
+#endif // BOOST_NO_CXX11_ALLOCATOR
+
+#endif // header
diff --git a/boost/thread/csbl/memory/scoped_allocator.hpp b/boost/thread/csbl/memory/scoped_allocator.hpp
new file mode 100644
index 0000000000..a92f3d8514
--- /dev/null
+++ b/boost/thread/csbl/memory/scoped_allocator.hpp
@@ -0,0 +1,35 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP
+#define BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP
+
+#include <boost/thread/csbl/memory/config.hpp>
+
+// 20.7.7, uses_allocator
+#if defined BOOST_NO_CXX11_ALLOCATOR
+#include <boost/container/scoped_allocator.hpp>
+
+namespace boost
+{
+ namespace csbl
+ {
+ using ::boost::container::uses_allocator;
+ }
+}
+#else
+namespace boost
+{
+ namespace csbl
+ {
+ using ::std::uses_allocator;
+ }
+}
+#endif // BOOST_NO_CXX11_POINTER_TRAITS
+
+#endif // header
diff --git a/boost/thread/csbl/memory/shared_ptr.hpp b/boost/thread/csbl/memory/shared_ptr.hpp
new file mode 100644
index 0000000000..e9a9383723
--- /dev/null
+++ b/boost/thread/csbl/memory/shared_ptr.hpp
@@ -0,0 +1,42 @@
+// Copyright (C) 2014 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2014/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_MEMORY_SHARED_PTR_HPP
+#define BOOST_CSBL_MEMORY_SHARED_PTR_HPP
+
+#include <boost/thread/csbl/memory/config.hpp>
+
+#if defined BOOST_NO_CXX11_SMART_PTR
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+namespace boost
+{
+ namespace csbl
+ {
+ using ::boost::shared_ptr;
+ using ::boost::make_shared;
+ }
+}
+
+#else
+
+#include <boost/shared_ptr.hpp>
+
+namespace boost
+{
+ namespace csbl
+ {
+ using std::shared_ptr;
+ using std::make_shared;
+ }
+}
+
+#endif
+#endif // header
diff --git a/boost/thread/csbl/memory/unique_ptr.hpp b/boost/thread/csbl/memory/unique_ptr.hpp
new file mode 100644
index 0000000000..17abf54e92
--- /dev/null
+++ b/boost/thread/csbl/memory/unique_ptr.hpp
@@ -0,0 +1,28 @@
+// Copyright (C) 2013-2014 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation using interprocess::unique_ptr.
+// 2014/09 Vicente J. Botet Escriba
+// Adaptation to movelib::unique_ptr
+
+#ifndef BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
+#define BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
+
+#include <boost/thread/csbl/memory/config.hpp>
+
+#include <boost/move/unique_ptr.hpp>
+#include <boost/move/make_unique.hpp>
+
+namespace boost
+{
+ namespace csbl
+ {
+ using ::boost::movelib::unique_ptr;
+ using ::boost::movelib::make_unique;
+
+ }
+}
+#endif // header
diff --git a/boost/thread/csbl/tuple.hpp b/boost/thread/csbl/tuple.hpp
new file mode 100644
index 0000000000..860229ebe0
--- /dev/null
+++ b/boost/thread/csbl/tuple.hpp
@@ -0,0 +1,49 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_TUPLE_HPP
+#define BOOST_CSBL_TUPLE_HPP
+
+#include <boost/config.hpp>
+
+#if defined BOOST_THREAD_USES_BOOST_TUPLE || defined BOOST_NO_CXX11_HDR_TUPLE || defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#include <boost/tuple/tuple.hpp>
+#ifndef BOOST_THREAD_USES_BOOST_TUPLE
+#define BOOST_THREAD_USES_BOOST_TUPLE
+#endif
+
+#else
+#include <tuple>
+#endif
+
+namespace boost
+{
+ namespace csbl
+ {
+#if defined BOOST_THREAD_USES_BOOST_TUPLE
+ using ::boost::tuple;
+ using ::boost::get;
+ using ::boost::make_tuple;
+ //using ::boost::tuple_size;
+#else
+ // 20.4.2, class template tuple:
+ using ::std::tuple;
+ using ::std::get;
+ using ::std::make_tuple;
+ using ::std::tuple_size;
+ // 20.4.2.4, tuple creation functions:
+ // 20.4.2.5, tuple helper classes:
+ // 20.4.2.6, element access:
+ // 20.4.2.7, relational operators:
+ // 20.4.2.8, allocator-related traits
+ // 20.4.2.9, specialized algorithms:
+#endif
+
+ }
+}
+#endif // header
diff --git a/boost/thread/csbl/vector.hpp b/boost/thread/csbl/vector.hpp
new file mode 100644
index 0000000000..d39c87d114
--- /dev/null
+++ b/boost/thread/csbl/vector.hpp
@@ -0,0 +1,35 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/10 Vicente J. Botet Escriba
+// Creation.
+
+#ifndef BOOST_CSBL_VECTOR_HPP
+#define BOOST_CSBL_VECTOR_HPP
+
+#include <boost/config.hpp>
+
+#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_HDR_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifndef BOOST_THREAD_USES_BOOST_VECTOR
+#define BOOST_THREAD_USES_BOOST_VECTOR
+#endif
+#include <boost/container/vector.hpp>
+#else
+#include <vector>
+#endif
+
+namespace boost
+{
+ namespace csbl
+ {
+#if defined BOOST_THREAD_USES_BOOST_VECTOR
+ using ::boost::container::vector;
+#else
+ using ::std::vector;
+#endif
+
+ }
+}
+#endif // header
diff --git a/boost/thread/cv_status.hpp b/boost/thread/cv_status.hpp
index 99b3c0c218..e52de4a522 100644
--- a/boost/thread/cv_status.hpp
+++ b/boost/thread/cv_status.hpp
@@ -9,7 +9,7 @@
#ifndef BOOST_THREAD_CV_STATUS_HPP
#define BOOST_THREAD_CV_STATUS_HPP
-#include <boost/detail/scoped_enum_emulation.hpp>
+#include <boost/core/scoped_enum.hpp>
namespace boost
{
diff --git a/boost/thread/detail/config.hpp b/boost/thread/detail/config.hpp
index d9270df8af..475dadbaaa 100644
--- a/boost/thread/detail/config.hpp
+++ b/boost/thread/detail/config.hpp
@@ -1,6 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
-// Copyright (C) 2011-2012 Vicente J. Botet Escriba
+// Copyright (C) 2011-2013 Vicente J. Botet Escriba
//
// 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)
@@ -10,118 +10,353 @@
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
+#include <boost/thread/detail/platform.hpp>
+
+//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
+// ATTRIBUTE_MAY_ALIAS
+
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+
+ // GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
+ // regard to violation of the strict aliasing rules.
+
+ #define BOOST_THREAD_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
+ #define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__))
+#else
+ #define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS
+#endif
+
+
+#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+#define BOOST_THREAD_ASSERT_PRECONDITION(EXPR, EX) \
+ if (EXPR) {} else boost::throw_exception(EX)
+#define BOOST_THREAD_VERIFY_PRECONDITION(EXPR, EX) \
+ if (EXPR) {} else boost::throw_exception(EX)
+#define BOOST_THREAD_THROW_ELSE_RETURN(EX, RET) \
+ boost::throw_exception(EX)
+#else
+#define BOOST_THREAD_ASSERT_PRECONDITION(EXPR, EX)
+#define BOOST_THREAD_VERIFY_PRECONDITION(EXPR, EX) \
+ (void)(EXPR)
+#define BOOST_THREAD_THROW_ELSE_RETURN(EX, RET) \
+ return (RET)
+#endif
// This compiler doesn't support Boost.Chrono
-#if defined __IBMCPP__ && (__IBMCPP__ < 1100)
+#if defined __IBMCPP__ && (__IBMCPP__ < 1100) \
+ && ! defined BOOST_THREAD_DONT_USE_CHRONO
#define BOOST_THREAD_DONT_USE_CHRONO
+#if ! defined BOOST_THREAD_USES_DATETIME
+#define BOOST_THREAD_USES_DATETIME
+#endif
#endif
// This compiler doesn't support Boost.Move
-#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
+#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) \
+ && ! defined BOOST_THREAD_DONT_USE_MOVE
#define BOOST_THREAD_DONT_USE_MOVE
#endif
// This compiler doesn't support Boost.Container Allocators files
-#if defined __SUNPRO_CC
+#if defined __SUNPRO_CC \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#endif
-#if defined _WIN32_WCE && _WIN32_WCE==0x501
+#if defined _WIN32_WCE && _WIN32_WCE==0x501 \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_BASIC_THREAD_ID
+
+#if defined BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX || defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+#define BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST
+#define BOOST_THREAD_NO_MAKE_LOCK_GUARD
+#define BOOST_THREAD_NO_MAKE_STRICT_LOCK
+#define BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK
+#endif
+
+#if defined(BOOST_NO_CXX11_HDR_TUPLE) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#define BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS
+#define BOOST_THREAD_NO_SYNCHRONIZE
+#elif defined _MSC_VER && _MSC_VER <= 1600
+// C++ features supported by VC++ 10 (aka 2010)
+#define BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS
+#define BOOST_THREAD_NO_SYNCHRONIZE
+#endif
+
+/// BASIC_THREAD_ID
+#if ! defined BOOST_THREAD_DONT_PROVIDE_BASIC_THREAD_ID \
+ && ! defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#define BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#endif
-// Default version is 2
+/// RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+//#if defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_MSVC
+#define BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+//#endif
+
+// Default version
#if !defined BOOST_THREAD_VERSION
#define BOOST_THREAD_VERSION 2
#else
-#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3
-#error "BOOST_THREAD_VERSION must be 2 or 3"
+#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3 && BOOST_THREAD_VERSION!=4
+#error "BOOST_THREAD_VERSION must be 2, 3 or 4"
#endif
#endif
-// Uses Boost.System by default if not stated the opposite defining BOOST_THREAD_DONT_USE_SYSTEM
-#if ! defined BOOST_THREAD_DONT_USE_SYSTEM
-#define BOOST_THREAD_USES_SYSTEM
+// CHRONO
+// Uses Boost.Chrono by default if not stated the opposite defining BOOST_THREAD_DONT_USE_CHRONO
+#if ! defined BOOST_THREAD_DONT_USE_CHRONO \
+ && ! defined BOOST_THREAD_USES_CHRONO
+#define BOOST_THREAD_USES_CHRONO
#endif
-// Uses Boost.Chrono by default if not stated the opposite defining BOOST_THREAD_DONT_USE_CHRONO or BOOST_THREAD_DONT_USE_SYSTEM
-#if ! defined BOOST_THREAD_DONT_USE_CHRONO && ! defined BOOST_THREAD_DONT_USE_SYSTEM
-#define BOOST_THREAD_USES_CHRONO
+#if ! defined BOOST_THREAD_DONT_USE_ATOMIC \
+ && ! defined BOOST_THREAD_USES_ATOMIC
+#define BOOST_THREAD_USES_ATOMIC
+//#define BOOST_THREAD_DONT_USE_ATOMIC
#endif
-// Don't provided by default in version 1.
-#if defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
-#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION explicit
+#if defined BOOST_THREAD_USES_ATOMIC
+// Andrey Semashev
+#define BOOST_THREAD_ONCE_ATOMIC
#else
-#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION
+//#elif ! defined BOOST_NO_CXX11_THREAD_LOCAL && ! defined BOOST_NO_THREAD_LOCAL && ! defined BOOST_THREAD_NO_UINT32_PSEUDO_ATOMIC
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html#Appendix
+#define BOOST_THREAD_ONCE_FAST_EPOCH
#endif
+#if BOOST_THREAD_VERSION==2
-
-// Uses Boost.Move by default if not stated the opposite defining BOOST_THREAD_DONT_USE_MOVE
-#if ! defined BOOST_THREAD_DONT_USE_MOVE
-#if ! defined BOOST_THREAD_USES_MOVE
-//#define BOOST_THREAD_USES_MOVE
-#endif
+// PROVIDE_PROMISE_LAZY
+#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY \
+ && ! defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
+#define BOOST_THREAD_PROVIDES_PROMISE_LAZY
#endif
-#if BOOST_THREAD_VERSION==2
-#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY
-#define BOOST_THREAD_PROMISE_LAZY
-#endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
-#define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+// PROVIDE_THREAD_EQ
+#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_EQ \
+ && ! defined BOOST_THREAD_PROVIDES_THREAD_EQ
+#define BOOST_THREAD_PROVIDES_THREAD_EQ
#endif
+
#endif
-#if BOOST_THREAD_VERSION==3
-#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11
-#define BOOST_THREAD_PROVIDES_ONCE_CXX11
+#if BOOST_THREAD_VERSION>=3
+
+// ONCE_CXX11
+// fixme BOOST_THREAD_PROVIDES_ONCE_CXX11 doesn't works when thread.cpp is compiled BOOST_THREAD_VERSION 3
+#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11 \
+ && ! defined BOOST_THREAD_PROVIDES_ONCE_CXX11
+#define BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11
#endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
+
+// THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
+#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE \
+ && ! defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
#define BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
#endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
+
+// THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
+#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE \
+ && ! defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
#define BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
#endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE
+
+// PROVIDE_FUTURE
+#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE \
+ && ! defined BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE
#endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
+
+// FUTURE_CTOR_ALLOCATORS
+#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS \
+ && ! defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#define BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSIONS
+
+// SHARED_MUTEX_UPWARDS_CONVERSIONS
+#if ! defined BOOST_THREAD_DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSIONS \
+ && ! defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
#endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION
+
+// PROVIDE_EXPLICIT_LOCK_CONVERSION
+#if ! defined BOOST_THREAD_DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION \
+ && ! defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
#endif
-#if ! defined BOOST_THREAD_DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN
+
+// GENERIC_SHARED_MUTEX_ON_WIN
+#if ! defined BOOST_THREAD_DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN \
+ && ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
#endif
-#if ! defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
-#define BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
-#endif
-#if ! defined BOOST_THREAD_DONT_USE_MOVE
-#if ! defined BOOST_THREAD_USES_MOVE
+
+// USE_MOVE
+#if ! defined BOOST_THREAD_DONT_USE_MOVE \
+ && ! defined BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_USES_MOVE
#endif
+
+#endif
+
+// deprecated since version 4
+#if BOOST_THREAD_VERSION < 4
+
+// NESTED_LOCKS
+#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_NESTED_LOCKS
+#define BOOST_THREAD_PROVIDES_NESTED_LOCKS
+#endif
+
+// CONDITION
+#if ! defined BOOST_THREAD_PROVIDES_CONDITION \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_CONDITION
+#define BOOST_THREAD_PROVIDES_CONDITION
#endif
+// USE_DATETIME
+#if ! defined BOOST_THREAD_DONT_USE_DATETIME \
+ && ! defined BOOST_THREAD_USES_DATETIME
+#define BOOST_THREAD_USES_DATETIME
+#endif
+#endif
+
+#if BOOST_THREAD_VERSION>=4
+
+// SIGNATURE_PACKAGED_TASK
+#if ! defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_SIGNATURE_PACKAGED_TASK
+#define BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+#endif
+
+// VARIADIC_THREAD
+#if ! defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_VARIADIC_THREAD
+
+#if ! defined(BOOST_NO_SFINAE_EXPR) && \
+ ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ ! defined(BOOST_NO_CXX11_DECLTYPE) && \
+ ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
+ ! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
+ ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ ! defined(BOOST_NO_CXX11_HDR_TUPLE)
+
+#define BOOST_THREAD_PROVIDES_VARIADIC_THREAD
+#endif
+#endif
+
+#if ! defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_WHEN_ALL_WHEN_ANY
+
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ ! defined(BOOST_NO_CXX11_HDR_TUPLE)
+
+#define BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
+#endif
+#endif
+
+// ! defined(BOOST_NO_SFINAE_EXPR) &&
+// ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) &&
+// ! defined(BOOST_NO_CXX11_AUTO) &&
+// ! defined(BOOST_NO_CXX11_DECLTYPE) &&
+// ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) &&
+
+
+// MAKE_READY_AT_THREAD_EXIT
+#if ! defined BOOST_THREAD_PROVIDES_MAKE_READY_AT_THREAD_EXIT \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_MAKE_READY_AT_THREAD_EXIT
+
+//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+#define BOOST_THREAD_PROVIDES_MAKE_READY_AT_THREAD_EXIT
+//#endif
+#endif
+
+// FUTURE_CONTINUATION
+#if ! defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CONTINUATION
+#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+#endif
+
+#if ! defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_UNWRAP
+#define BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+#endif
+
+// FUTURE_INVALID_AFTER_GET
+#if ! defined BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET
+#define BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+#endif
+
+// NESTED_LOCKS
+#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_NESTED_LOCKS
+#define BOOST_THREAD_DONT_PROVIDE_NESTED_LOCKS
+#endif
+
+// CONDITION
+#if ! defined BOOST_THREAD_PROVIDES_CONDITION \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_CONDITION
+#define BOOST_THREAD_DONT_PROVIDE_CONDITION
+#endif
+
+#endif // BOOST_THREAD_VERSION>=4
+
+// INTERRUPTIONS
+#if ! defined BOOST_THREAD_PROVIDES_INTERRUPTIONS \
+ && ! defined BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
+#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
+#endif
+
+// CORRELATIONS
+
+// EXPLICIT_LOCK_CONVERSION.
+#if defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
+#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION explicit
+#else
+#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION
#endif
// BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN is defined if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
-#if defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+#if defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS \
+&& ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
#endif
-// BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.52
+// For C++11 call_once interface the compiler MUST support constexpr.
+// Otherwise once_flag would be initialized during dynamic initialization stage, which is not thread-safe.
+#if defined(BOOST_THREAD_PROVIDES_ONCE_CXX11)
+#if defined(BOOST_NO_CXX11_CONSTEXPR)
+#undef BOOST_THREAD_PROVIDES_ONCE_CXX11
+#endif
+#endif
+
+#if defined(BOOST_THREAD_PLATFORM_WIN32) && defined BOOST_THREAD_DONT_USE_DATETIME
+#undef BOOST_THREAD_DONT_USE_DATETIME
+#define BOOST_THREAD_USES_DATETIME
+#endif
+
+#if defined(BOOST_THREAD_PLATFORM_WIN32) && defined BOOST_THREAD_DONT_USE_CHRONO
+#undef BOOST_THREAD_DONT_USE_CHRONO
+#define BOOST_THREAD_USES_CHRONO
+#endif
+
+// BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55
// BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55
-#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0
-#define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+
+#if ! defined BOOST_THREAD_PROVIDES_THREAD_EQ
+#define BOOST_THREAD_PROVIDES_THREAD_EQ
+#endif
+
+#endif
+
+
+//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_THREAD_USES_MOVE
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#define BOOST_THREAD_FUTURE_USES_OPTIONAL
#endif
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
@@ -133,16 +368,25 @@
#include <boost/thread/detail/platform.hpp>
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+#else
+ # if defined(BOOST_HAS_PTHREAD_DELAY_NP) || defined(BOOST_HAS_NANOSLEEP)
+ # define BOOST_THREAD_SLEEP_FOR_IS_STEADY
+ # endif
+#endif
+
// provided for backwards compatibility, since this
// macro was used for several releases by mistake.
-#if defined(BOOST_THREAD_DYN_DLL)
+#if defined(BOOST_THREAD_DYN_DLL) && ! defined BOOST_THREAD_DYN_LINK
# define BOOST_THREAD_DYN_LINK
#endif
// compatibility with the rest of Boost's auto-linking code:
#if defined(BOOST_THREAD_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
# undef BOOST_THREAD_USE_LIB
-# define BOOST_THREAD_USE_DLL
+# if !defined(BOOST_THREAD_USE_DLL)
+# define BOOST_THREAD_USE_DLL
+# endif
#endif
#if defined(BOOST_THREAD_BUILD_DLL) //Build dll
@@ -151,8 +395,9 @@
#elif defined(BOOST_THREAD_USE_LIB) //Use lib
#else //Use default
# if defined(BOOST_THREAD_PLATFORM_WIN32)
-# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
- //For compilers supporting auto-tss cleanup
+# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN) \
+ || defined(__MINGW32__) || defined(MINGW32) || defined(BOOST_MINGW32)
+ //For compilers supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads lib
# define BOOST_THREAD_USE_LIB
# else
diff --git a/boost/thread/detail/counter.hpp b/boost/thread/detail/counter.hpp
new file mode 100644
index 0000000000..38e1597c57
--- /dev/null
+++ b/boost/thread/detail/counter.hpp
@@ -0,0 +1,106 @@
+// 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)
+// (C) Copyright 2013 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_COUNTER_HPP
+#define BOOST_THREAD_COUNTER_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+
+//#include <boost/thread/mutex.hpp>
+//#include <boost/thread/lock_types.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/chrono/duration.hpp>
+#include <boost/chrono/time_point.hpp>
+#include <boost/assert.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ namespace detail {
+ struct counter
+ {
+ condition_variable cond_;
+ std::size_t value_;
+
+ counter(std::size_t value)
+ : value_(value)
+ {
+
+ }
+ counter& operator=(counter const& rhs)
+ {
+ value_ = rhs.value_;
+ return *this;
+ }
+ counter& operator=(std::size_t value)
+ {
+ value_ = value;
+ return *this;
+ }
+
+ operator std::size_t() const
+ {
+ return value_;
+ }
+ operator std::size_t&()
+ {
+ return value_;
+ }
+
+ void inc_and_notify_all()
+ {
+ ++value_;
+ cond_.notify_all();
+ }
+
+ void dec_and_notify_all()
+ {
+ --value_;
+ cond_.notify_all();
+ }
+ void assign_and_notify_all(counter const& rhs)
+ {
+ value_ = rhs.value_;
+ cond_.notify_all();
+ }
+ void assign_and_notify_all(std::size_t value)
+ {
+ value_ = value;
+ cond_.notify_all();
+ }
+ };
+ struct counter_is_not_zero
+ {
+ counter_is_not_zero(counter const& count) : count_(count) {}
+ bool operator()() const { return count_ != 0; }
+ counter const& count_;
+ };
+ struct counter_is_zero
+ {
+ counter_is_zero(counter const& count) : count_(count) {}
+ bool operator()() const { return count_ == 0; }
+ counter const& count_;
+ };
+ struct is_zero
+ {
+ is_zero(std::size_t& count) : count_(count) {}
+ bool operator()() const { return count_ == 0; }
+ std::size_t& count_;
+ };
+ struct not_equal
+ {
+ not_equal(std::size_t& x, std::size_t& y) : x_(x), y_(y) {}
+ bool operator()() const { return x_ != y_; }
+ std::size_t& x_;
+ std::size_t& y_;
+ };
+ }
+} // namespace boost
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/detail/delete.hpp b/boost/thread/detail/delete.hpp
index 9e56d4429e..8f8113f4e8 100644
--- a/boost/thread/detail/delete.hpp
+++ b/boost/thread/detail/delete.hpp
@@ -15,14 +15,26 @@
* BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or
* makes it private.
*/
-#ifndef BOOST_NO_DELETED_FUNCTIONS
+
+#if ! defined BOOST_NO_CXX11_DELETED_FUNCTIONS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
CLASS(CLASS const&) = delete; \
#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \
CLASS& operator=(CLASS const&) = delete;
-#else // BOOST_NO_DELETED_FUNCTIONS
+#else // BOOST_NO_CXX11_DELETED_FUNCTIONS
+#if defined(BOOST_MSVC) && _MSC_VER >= 1600
+#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
+ private: \
+ CLASS(CLASS const&); \
+ public:
+
+#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \
+ private: \
+ CLASS& operator=(CLASS const&); \
+ public:
+#else
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
private: \
CLASS(CLASS&); \
@@ -32,7 +44,8 @@
private: \
CLASS& operator=(CLASS&); \
public:
-#endif // BOOST_NO_DELETED_FUNCTIONS
+#endif
+#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
/**
* BOOST_THREAD_NO_COPYABLE deletes the copy constructor and assignment when the compiler supports it or
diff --git a/boost/thread/detail/function_wrapper.hpp b/boost/thread/detail/function_wrapper.hpp
new file mode 100644
index 0000000000..355f726762
--- /dev/null
+++ b/boost/thread/detail/function_wrapper.hpp
@@ -0,0 +1,93 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/09 Vicente J. Botet Escriba
+// Adapt to boost from CCIA C++11 implementation
+// Make use of Boost.Move
+
+#ifndef BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP
+#define BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP
+
+#include <boost/config.hpp>
+#include <boost/thread/detail/memory.hpp>
+#include <boost/thread/detail/move.hpp>
+
+#include <boost/thread/csbl/memory/unique_ptr.hpp>
+
+#include <memory>
+#include <functional>
+
+namespace boost
+{
+ namespace detail
+ {
+ class function_wrapper
+ {
+ struct impl_base
+ {
+ virtual void call()=0;
+ virtual ~impl_base()
+ {
+ }
+ };
+ typedef boost::csbl::unique_ptr<impl_base> impl_base_type;
+ impl_base_type impl;
+ template <typename F>
+ struct impl_type: impl_base
+ {
+ F f;
+ impl_type(F const &f_)
+ : f(f_)
+ {}
+ impl_type(BOOST_THREAD_RV_REF(F) f_)
+ : f(boost::move(f_))
+ {}
+
+ void call()
+ {
+ if (impl) f();
+ }
+ };
+ public:
+ BOOST_THREAD_MOVABLE_ONLY(function_wrapper)
+
+//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ template<typename F>
+ function_wrapper(F const& f):
+ impl(new impl_type<F>(f))
+ {}
+//#endif
+ template<typename F>
+ function_wrapper(BOOST_THREAD_RV_REF(F) f):
+ impl(new impl_type<F>(boost::forward<F>(f)))
+ {}
+ function_wrapper(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT :
+ impl(other.impl)
+ {
+ other.impl = 0;
+ }
+ function_wrapper()
+ : impl(0)
+ {
+ }
+ ~function_wrapper()
+ {
+ }
+
+ function_wrapper& operator=(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT
+ {
+ impl=other.impl;
+ other.impl=0;
+ return *this;
+ }
+
+ void operator()()
+ { impl->call();}
+
+ };
+ }
+}
+
+#endif // header
diff --git a/boost/thread/detail/invoke.hpp b/boost/thread/detail/invoke.hpp
new file mode 100644
index 0000000000..e772da29ee
--- /dev/null
+++ b/boost/thread/detail/invoke.hpp
@@ -0,0 +1,1604 @@
+// Copyright (C) 2012-2013 Vicente J. Botet Escriba
+//
+// 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)
+
+// 2013/04 Vicente J. Botet Escriba
+// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined.
+// Make use of Boost.Move
+// Make use of Boost.Tuple (movable)
+// 2012 Vicente J. Botet Escriba
+// Provide implementation _RET using bind when BOOST_NO_CXX11_HDR_FUNCTIONAL and BOOST_NO_SFINAE_EXPR are not defined
+// 2012 Vicente J. Botet Escriba
+// Adapt to boost libc++ implementation
+
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+// The invoke code is based on the one from libcxx.
+//===----------------------------------------------------------------------===//
+
+#ifndef BOOST_THREAD_DETAIL_INVOKE_HPP
+#define BOOST_THREAD_DETAIL_INVOKE_HPP
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_member_function_pointer.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
+#include <functional>
+#endif
+
+namespace boost
+{
+ namespace detail
+ {
+
+
+#if ! defined(BOOST_NO_SFINAE_EXPR) && \
+ ! defined(BOOST_NO_CXX11_DECLTYPE) && \
+ ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
+ ! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
+
+#define BOOST_THREAD_PROVIDES_INVOKE
+
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ // bullets 1 and 2
+
+ template <class Fp, class A0, class ...Args>
+ inline auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ -> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...))
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
+ }
+ template <class R, class Fp, class A0, class ...Args>
+ inline auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ -> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...))
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
+ }
+
+ template <class Fp, class A0, class ...Args>
+ inline auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...))
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
+ }
+ template <class R, class Fp, class A0, class ...Args>
+ inline auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...))
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
+ }
+
+ // bullets 3 and 4
+
+ template <class Fp, class A0>
+ inline auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype(boost::forward<A0>(a0).*f)
+ {
+ return boost::forward<A0>(a0).*f;
+ }
+
+ template <class Fp, class A0>
+ inline auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype((*boost::forward<A0>(a0)).*f)
+ {
+ return (*boost::forward<A0>(a0)).*f;
+ }
+
+ template <class R, class Fp, class A0>
+ inline auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype(boost::forward<A0>(a0).*f)
+ {
+ return boost::forward<A0>(a0).*f;
+ }
+
+ template <class R, class Fp, class A0>
+ inline auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype((*boost::forward<A0>(a0)).*f)
+ {
+ return (*boost::forward<A0>(a0)).*f;
+ }
+
+
+ // bullet 5
+
+ template <class R, class Fp, class ...Args>
+ inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
+ -> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...))
+ {
+ return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
+ }
+ template <class Fp, class ...Args>
+ inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
+ -> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...))
+ {
+ return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
+ }
+
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+ // bullets 1 and 2
+
+ template <class Fp, class A0>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype((boost::forward<A0>(a0).*f)())
+ {
+ return (boost::forward<A0>(a0).*f)();
+ }
+ template <class R, class Fp, class A0>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype((boost::forward<A0>(a0).*f)())
+ {
+ return (boost::forward<A0>(a0).*f)();
+ }
+ template <class Fp, class A0, class A1>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
+ -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)))
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
+ }
+ template <class R, class Fp, class A0, class A1>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
+ -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)))
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
+ }
+ template <class Fp, class A0, class A1, class A2>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class R, class Fp, class A0, class A1, class A2>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+
+ template <class Fp, class A0>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype(((*boost::forward<A0>(a0)).*f)())
+ {
+ return ((*boost::forward<A0>(a0)).*f)();
+ }
+ template <class R, class Fp, class A0>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype(((*boost::forward<A0>(a0)).*f)())
+ {
+ return ((*boost::forward<A0>(a0)).*f)();
+ }
+ template <class Fp, class A0, class A1>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
+ -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)))
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
+ }
+ template <class R, class Fp, class A0, class A1>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
+ -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)))
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
+ }
+ template <class Fp, class A0, class A1, class A2>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class R, class Fp, class A0, class A1, class A2>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+
+ // bullets 3 and 4
+
+ template <class Fp, class A0>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype(boost::forward<A0>(a0).*f)
+ {
+ return boost::forward<A0>(a0).*f;
+ }
+ template <class R, class Fp, class A0>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype(boost::forward<A0>(a0).*f)
+ {
+ return boost::forward<A0>(a0).*f;
+ }
+
+ template <class Fp, class A0>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype((*boost::forward<A0>(a0)).*f)
+ {
+ return (*boost::forward<A0>(a0)).*f;
+ }
+ template <class R, class Fp, class A0>
+ inline
+ auto
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
+ -> decltype((*boost::forward<A0>(a0)).*f)
+ {
+ return (*boost::forward<A0>(a0)).*f;
+ }
+
+ // bullet 5
+
+ template <class Fp>
+ inline
+ auto invoke(BOOST_THREAD_RV_REF(Fp) f)
+ -> decltype(boost::forward<Fp>(f)())
+ {
+ return boost::forward<Fp>(f)();
+ }
+ template <class Fp, class A1>
+ inline
+ auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
+ -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1)))
+ {
+ return boost::forward<Fp>(f)(boost::forward<A1>(a1));
+ } template <class Fp, class A1, class A2>
+ inline
+ auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
+ {
+ return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Fp, class A1, class A2, class A3>
+ inline
+ auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)))
+ {
+ return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+
+
+ template <class R, class Fp>
+ inline
+ auto invoke(BOOST_THREAD_RV_REF(Fp) f)
+ -> decltype(boost::forward<Fp>(f)())
+ {
+ return boost::forward<Fp>(f)();
+ }
+ template <class R, class Fp, class A1>
+ inline
+ auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
+ -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1)))
+ {
+ return boost::forward<Fp>(f)(boost::forward<A1>(a1));
+ }
+ template <class R, class Fp, class A1, class A2>
+ inline
+ auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
+ {
+ return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class R, class Fp, class A1, class A2, class A3>
+ inline
+ auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)))
+ {
+ return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+#elif ! defined(BOOST_NO_SFINAE_EXPR) && \
+ ! defined BOOST_NO_CXX11_HDR_FUNCTIONAL && \
+ defined BOOST_MSVC
+
+ template <class Ret, class Fp>
+ inline
+ Ret invoke(BOOST_THREAD_RV_REF(Fp) f)
+ {
+ return f();
+ }
+ template <class Ret, class Fp, class A1>
+ inline
+ Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return std::bind(boost::forward<Fp>(f), boost::forward<A1>(a1))();
+ }
+ template <class Ret, class Fp, class A1, class A2>
+ inline
+ Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ {
+ return std::bind(boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2))();
+ }
+ template <class Ret, class Fp, class A1, class A2, class A3>
+ inline
+ Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ {
+ return std::bind(boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3))();
+ }
+
+#define BOOST_THREAD_PROVIDES_INVOKE_RET
+
+#elif ! defined BOOST_MSVC
+//!!!!! WARNING !!!!! THIS DOESN'T WORKS YET
+#define BOOST_THREAD_PROVIDES_INVOKE_RET
+
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ // bullet 1
+ // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of
+ // type T or a reference to an object of type T or a reference to an object of a type derived from T
+ template <class Ret, class A, class A0, class ...Args>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(Args...), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
+ }
+
+ template <class Ret, class A, class A0, class ...Args>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(Args...) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
+ }
+
+ template <class Ret, class A, class A0, class ...Args>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(Args...) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
+ }
+
+ template <class Ret, class A, class A0, class ...Args>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(Args...) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
+ }
+
+ // bullet 2
+ // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of
+ // the types described in the previous item;
+ template <class Ret, class A, class A0, class ...Args>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(Args...), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
+ }
+
+ template <class Ret, class A, class A0, class ...Args>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(Args...) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
+ }
+
+ template <class Ret, class A, class A0, class ...Args>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(Args...) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
+ }
+
+ template <class Ret, class A, class A0, class ...Args>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(Args...) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
+ }
+
+ // bullet 3
+ // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a
+ // reference to an object of type T or a reference to an object of a type derived from T;
+// template <class Ret, class A, class A0>
+// inline
+// typename enable_if_c
+// <
+// is_base_of<A, typename remove_reference<A0>::type>::value,
+// typename detail::apply_cv<A0, A>::type&
+// >::type
+// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
+// {
+// return boost::forward<A0>(a0).*f;
+// }
+
+ // bullet 4
+ // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types
+ //described in the previous item;
+
+// template <class A0, class Ret, bool>
+// struct d4th_helper
+// {
+// };
+//
+// template <class A0, class Ret>
+// struct d4th_helper<A0, Ret, true>
+// {
+// typedef typename apply_cv<decltype(*declval<A0>()), Ret>::type type;
+// };
+//
+// template <class Ret, class A, class A0>
+// inline
+// typename detail::4th_helper<A, Ret,
+// !is_base_of<A,
+// typename remove_reference<A0>::type
+// >::value
+// >::type&
+// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
+// {
+// return (*boost::forward<A0>(a0)).*f;
+// }
+
+// template <class Ret, class A, class A0>
+// inline
+// typename enable_if_c
+// <
+// !is_base_of<A, typename remove_reference<A0>::type>::value,
+// typename detail::ref_return1<Ret A::*, A0>::type
+// >::type
+// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
+// {
+// return (*boost::forward<A0>(a0)).*f;
+// }
+
+ // bullet 5
+ // f(t1, t2, ..., tN) in all other cases.
+
+ template <class Ret, class Fp, class ...Args>
+ inline Ret do_invoke(mpl::false_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
+ }
+
+ template <class Ret, class Fp, class ...Args>
+ inline Ret do_invoke(mpl::true_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return f(boost::forward<Args>(args)...);
+ }
+
+ template <class Ret, class Fp, class ...Args>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
+ {
+ return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<Args>(args)...);
+ }
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ // bullet 1
+ // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of
+ // type T or a reference to an object of type T or a reference to an object of a type derived from T
+
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(), A0& a0)
+ {
+ return (a0.*f)();
+ }
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(), A0* a0)
+ {
+ return ((*a0).*f)();
+ }
+
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1),
+ A0& a0, BOOST_THREAD_RV_REF(A1) a1
+ )
+ {
+ return (a0.*f)(boost::forward<A1>(a1));
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1), A0& a0, A1 a1)
+ {
+ return (a0.*f)(a1);
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1), A0* a0, BOOST_THREAD_RV_REF(A1) a1
+ )
+ {
+ return (*(a0).*f)(boost::forward<A1>(a1));
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1), A0* a0, A1 a1)
+ {
+ return (*a0.*f)(a1);
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2),
+ A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
+ )
+ {
+ return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2), A0* a0, A1 a1, A2 a2)
+ {
+ return ((*a0).*f)(a1, a2);
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3),
+ A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ {
+ return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3), A0* a0, A1 a1, A2 a2, A3 a3)
+ {
+ return ((*a0).*f)(a1, a2, a3);
+ }
+
+///
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)() const, A0 const& a0)
+ {
+ return (a0.*f)();
+ }
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)() const, A0 const* a0)
+ {
+ return ((*a0).*f)();
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) const, A0 const& a0, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return (a0.*f)(boost::forward<A1>(a1));
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) const, A0 const* a0, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return ((*a0).*f)(boost::forward<A1>(a1));
+ }
+
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) const, A0 const& a0, A1 a1)
+ {
+ return (a0.*f)(a1);
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) const,
+ A0 const& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
+ )
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)
+ );
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) const, A0 const& a0, A1 a1, A2 a2)
+ {
+ return (a0.*f)(a1, a2);
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) const,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3
+ )
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) const, A0 a0, A1 a1, A2 a2, A3 a3)
+ {
+ return (a0.*f)(a1, a2, a3);
+ }
+ ///
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)() volatile, BOOST_THREAD_RV_REF(A0) a0)
+ {
+ return (boost::forward<A0>(a0).*f)();
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) volatile, A0 a0, A1 a1)
+ {
+ return (a0.*f)(a1);
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) volatile,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) volatile, A0 a0, A1 a1, A2 a2 )
+ {
+ return (a0.*f)(a1, a2);
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) volatile,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3
+ )
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) volatile, A0 a0, A1 a1, A2 a2, A3 a3)
+ {
+ return (a0.*f)(a1, a2, a3);
+ }
+ ///
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)() const volatile, BOOST_THREAD_RV_REF(A0) a0)
+ {
+ return (boost::forward<A0>(a0).*f)();
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) const volatile, A0 a0, A1 a1)
+ {
+ return (a0.*f)(a1);
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) const volatile,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
+ )
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) const volatile,
+ A0 a0, A1 a1, A2 a2
+ )
+ {
+ return (a0.*f)(a1, a2);
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) const volatile,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3
+ )
+ {
+ return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) const volatile,
+ A0 a0, A1 a1, A2 a2, A3 a3
+ )
+ {
+ return (a0.*f)(a1, a2, a3);
+ }
+
+ // bullet 2
+ // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of
+ // the types described in the previous item;
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(), BOOST_THREAD_RV_REF(A0) a0)
+ {
+ return ((*boost::forward<A0>(a0)).*f)();
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1), A0 a0, A1 a1)
+ {
+ return ((*a0).*f)(a1);
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, BOOST_THREAD_RV_REF(A2)),
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2), A0 a0, A1 a1, A2 a2)
+ {
+ return ((*a0).*f)(a1, a2);
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, BOOST_THREAD_RV_REF(A2), BOOST_THREAD_RV_REF(A3)),
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)
+ );
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3), A0 a0, A1 a1, A2 a2, A3 a3)
+ {
+ return ((*a0).*f)(a1, a2, a3);
+ }
+
+///
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)() const, BOOST_THREAD_RV_REF(A0) a0)
+ {
+ return ((*boost::forward<A0>(a0)).*f)();
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) const,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) const, BOOST_THREAD_RV_REF(A0) a0, A1 a1)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(a1);
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) const, A0 a0, A1 a1)
+ {
+ return ((*a0).*f)(a1);
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) const,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) const, A0 a0, A1 a1, A2 a2)
+ {
+ return ((*a0).*f)(a1, a2);
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) const,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) const,
+ A0 a0, A1 a1, A2 a2, A3 a3)
+ {
+ return ((*a0).*f)(a1, a2, a3);
+ }
+ ///
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)() volatile, BOOST_THREAD_RV_REF(A0) a0)
+ {
+ return ((*boost::forward<A0>(a0)).*f)();
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) volatile,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) volatile, A0 a0, A1 a1)
+ {
+ return ((*a0).*f)(a1);
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) volatile,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) volatile, A0 a0, A1 a1, A2 a2)
+ {
+ return ((*a0).*f)(a1, a2);
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) volatile,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) volatile, A0 a0, A1 a1, A2 a2, A3 a3)
+ {
+ return ((*a0).*f)(a1, a2, a3);
+ }
+ ///
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)() const volatile, BOOST_THREAD_RV_REF(A0) a0)
+ {
+ return ((*boost::forward<A0>(a0)).*f)();
+ }
+ template <class Ret, class A, class A0>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)() const volatile, A0 a0)
+ {
+ return ((*a0).*f)();
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) const volatile,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
+ }
+ template <class Ret, class A, class A0, class A1>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1) const volatile, A0 a0, A1 a1)
+ {
+ return ((*a0).*f)(a1);
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) const volatile,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Ret, class A, class A0, class A1, class A2>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2) const volatile,
+ A0 a0, A1 a1, A2 a2)
+ {
+ return ((*a0).*f)(a1, a2);
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) const volatile,
+ BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ {
+ return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+ template <class Ret, class A, class A0, class A1, class A2, class A3>
+ inline
+ typename enable_if_c
+ <
+ ! is_base_of<A, typename remove_reference<A0>::type>::value,
+ Ret
+ >::type
+ invoke(Ret (A::*f)(A1, A2, A3) const volatile,
+ A0 a0, A1 a1, A2 a2, A3 a3)
+ {
+ return ((*a0).*f)(a1, a2, a3);
+ }
+ // bullet 3
+ // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a
+ // reference to an object of type T or a reference to an object of a type derived from T;
+// template <class Ret, class A, class A0>
+// inline
+// typename enable_if_c
+// <
+// is_base_of<A, typename remove_reference<A0>::type>::value,
+// typename detail::apply_cv<A0, A>::type&
+// >::type
+// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
+// {
+// return boost::forward<A0>(a0).*f;
+// }
+
+ // bullet 4
+ // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types
+ //described in the previous item;
+
+// template <class A0, class Ret, bool>
+// struct d4th_helper
+// {
+// };
+//
+// template <class A0, class Ret>
+// struct d4th_helper<A0, Ret, true>
+// {
+// typedef typename apply_cv<decltype(*declval<A0>()), Ret>::type type;
+// };
+//
+// template <class Ret, class A, class A0>
+// inline
+// typename detail::4th_helper<A, Ret,
+// !is_base_of<A,
+// typename remove_reference<A0>::type
+// >::value
+// >::type&
+// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
+// {
+// return (*boost::forward<A0>(a0)).*f;
+// }
+
+// template <class Ret, class A, class A0>
+// inline
+// typename enable_if_c
+// <
+// !is_base_of<A, typename remove_reference<A0>::type>::value,
+// typename detail::ref_return1<Ret A::*, A0>::type
+// >::type
+// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
+// {
+// return (*boost::forward<A0>(a0)).*f;
+// }
+
+ // bullet 5
+ // f(t1, t2, ..., tN) in all other cases.
+
+ template <class Ret, class Fp>
+ inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ return boost::forward<Fp>(f)();
+ }
+ template <class Ret, class Fp>
+ inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ return f();
+ }
+ template <class Ret, class Fp>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f));
+ }
+
+ template <class Ret, class Fp, class A1>
+ inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return boost::forward<Fp>(f)(boost::forward<A1>(a1));
+ }
+ template <class Ret, class Fp, class A1>
+ inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return f(boost::forward<A1>(a1));
+ }
+ template <class Ret, class Fp, class A1>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1));
+ }
+
+ template <class Ret, class Fp, class A1, class A2>
+ inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ {
+ return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Ret, class Fp, class A1, class A2>
+ inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ {
+ return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Ret, class Fp, class A1, class A2>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ {
+ return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+
+ template <class Ret, class Fp, class A1, class A2, class A3>
+ inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ {
+ return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+ template <class Ret, class Fp, class A1, class A2, class A3>
+ inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ {
+ return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+ template <class Ret, class Fp, class A1, class A2, class A3>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ {
+ return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+
+
+ template <class Ret, class Fp, class A1>
+ inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
+ {
+ return boost::forward<Fp>(f)(a1);
+ }
+ template <class Ret, class Fp, class A1>
+ inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
+ {
+ return f(a1);
+ }
+ template <class Ret, class Fp, class A1>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
+ {
+ return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1);
+ }
+
+ template <class Ret, class Fp, class A1, class A2>
+ inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
+ {
+ return boost::forward<Fp>(f)(a1, a2);
+ }
+ template <class Ret, class Fp, class A1, class A2>
+ inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
+ {
+ return f(a1, a2);
+ }
+ template <class Ret, class Fp, class A1, class A2>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
+ {
+ return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2);
+ }
+
+ template <class Ret, class Fp, class A1, class A2, class A3>
+ inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
+ {
+ return boost::forward<Fp>(f)(a1, a2, a3);
+ }
+ template <class Ret, class Fp, class A1, class A2, class A3>
+ inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
+ {
+ return f(a1, a2, a3);
+ }
+ template <class Ret, class Fp, class A1, class A2, class A3>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
+ {
+ return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2, a3);
+ }
+
+
+ ///
+ template <class Ret, class Fp>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(Fp &f)
+ {
+ return f();
+ }
+ template <class Ret, class Fp, class A1>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1)
+ {
+ return f(boost::forward<A1>(a1));
+ }
+ template <class Ret, class Fp, class A1>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(Fp &f, A1 a1)
+ {
+ return f(a1);
+ }
+ template <class Ret, class Fp, class A1, class A2>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
+ {
+ return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
+ }
+ template <class Ret, class Fp, class A1, class A2>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(Fp &f, A1 a1, A2 a2)
+ {
+ return f(a1, a2);
+ }
+ template <class Ret, class Fp, class A1, class A2, class A3>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
+ {
+ return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
+ }
+ template <class Ret, class Fp, class A1, class A2, class A3>
+ inline
+ typename disable_if_c
+ <
+ is_member_function_pointer<Fp>::value,
+ Ret
+ >::type
+ invoke(Fp &f, A1 a1, A2 a2, A3 a3)
+ {
+ return f(a1, a2, a3);
+ }
+ ///
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+#endif // all
+ }
+ }
+
+#endif // header
diff --git a/boost/thread/detail/invoker.hpp b/boost/thread/detail/invoker.hpp
new file mode 100644
index 0000000000..44deb1645b
--- /dev/null
+++ b/boost/thread/detail/invoker.hpp
@@ -0,0 +1,754 @@
+// Copyright (C) 2012 Vicente J. Botet Escriba
+//
+// 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)
+
+// 2013/04 Vicente J. Botet Escriba
+// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined.
+// Make use of Boost.Move
+// Make use of Boost.Tuple (movable)
+// 2012/11 Vicente J. Botet Escriba
+// Adapt to boost libc++ implementation
+
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+// The invoker code is based on the one from libcxx.
+//===----------------------------------------------------------------------===//
+
+#ifndef BOOST_THREAD_DETAIL_INVOKER_HPP
+#define BOOST_THREAD_DETAIL_INVOKER_HPP
+
+#include <boost/config.hpp>
+
+#include <boost/utility/result_of.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/detail/invoke.hpp>
+#include <boost/thread/detail/make_tuple_indices.hpp>
+#include <boost/thread/csbl/tuple.hpp>
+#include <boost/tuple/tuple.hpp>
+
+#include <boost/thread/detail/variadic_header.hpp>
+
+namespace boost
+{
+ namespace detail
+ {
+
+#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
+
+ template <class Fp, class ... Args>
+ class invoker
+ {
+ //typedef typename decay<Fp>::type Fpd;
+ //typedef tuple<typename decay<Args>::type...> Argsd;
+
+ //csbl::tuple<Fpd, Argsd...> f_;
+ csbl::tuple<Fp, Args...> f_;
+
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker)
+ //typedef typename invoke_of<_Fp, _Args...>::type Rp;
+ typedef typename result_of<Fp(Args...)>::type result_type;
+
+ template <class F, class ... As>
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args)
+ : f_(boost::forward<F>(f), boost::forward<As>(args)...)
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f) : f_(boost::move(BOOST_THREAD_RV(f).f_))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker( const invoker& f) : f_(f.f_)
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker& operator=(BOOST_THREAD_RV_REF(invoker) f)
+ {
+ f_ = boost::move(BOOST_THREAD_RV(f).f_);
+ }
+
+ BOOST_SYMBOL_VISIBLE
+ invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
+ {
+ f_ = f.f_;
+ }
+
+ result_type operator()()
+ {
+ typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
+ return execute(Index());
+ }
+ private:
+ template <size_t ...Indices>
+ result_type
+ execute(tuple_indices<Indices...>)
+ {
+ return invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
+ }
+ };
+
+ template <class R, class Fp, class ... Args>
+ class invoker_ret
+ {
+ //typedef typename decay<Fp>::type Fpd;
+ //typedef tuple<typename decay<Args>::type...> Argsd;
+
+ //csbl::tuple<Fpd, Argsd...> f_;
+ csbl::tuple<Fp, Args...> f_;
+
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker_ret)
+ typedef R result_type;
+
+ template <class F, class ... As>
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker_ret(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args)
+ : f_(boost::forward<F>(f), boost::forward<As>(args)...)
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker_ret(BOOST_THREAD_RV_REF(invoker_ret) f) : f_(boost::move(BOOST_THREAD_RV(f).f_))
+ {}
+
+ result_type operator()()
+ {
+ typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index;
+ return execute(Index());
+ }
+ private:
+ template <size_t ...Indices>
+ result_type
+ execute(tuple_indices<Indices...>)
+ {
+ return invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...);
+ }
+ };
+ //BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END
+#else
+
+#if ! defined BOOST_MSVC
+
+#define BOOST_THREAD_RV_REF_ARG_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(Arg##n)
+#define BOOST_THREAD_RV_REF_A_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(A##n)
+#define BOOST_THREAD_RV_REF_ARG(z, n, unused) , BOOST_THREAD_RV_REF(Arg##n) arg##n
+#define BOOST_THREAD_FWD_REF_A(z, n, unused) , BOOST_THREAD_FWD_REF(A##n) arg##n
+#define BOOST_THREAD_FWD_REF_ARG(z, n, unused) , BOOST_THREAD_FWD_REF(Arg##n) arg##n
+#define BOOST_THREAD_FWD_PARAM(z, n, unused) , boost::forward<Arg##n>(arg##n)
+#define BOOST_THREAD_FWD_PARAM_A(z, n, unused) , boost::forward<A##n>(arg##n)
+#define BOOST_THREAD_DCL(z, n, unused) Arg##n v##n;
+#define BOOST_THREAD_MOVE_PARAM(z, n, unused) , v##n(boost::move(arg##n))
+#define BOOST_THREAD_FORWARD_PARAM_A(z, n, unused) , v##n(boost::forward<A##n>(arg##n))
+#define BOOST_THREAD_MOVE_RHS_PARAM(z, n, unused) , v##n(boost::move(x.v##n))
+#define BOOST_THREAD_MOVE_DCL(z, n, unused) , boost::move(v##n)
+#define BOOST_THREAD_MOVE_DCL_T(z, n, unused) BOOST_PP_COMMA_IF(n) boost::move(v##n)
+#define BOOST_THREAD_ARG_DEF(z, n, unused) , class Arg##n = tuples::null_type
+
+ template <class Fp, class Arg = tuples::null_type
+ BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ARG_DEF, ~)
+ >
+ class invoker;
+
+#define BOOST_THREAD_ASYNC_FUNCT(z, n, unused) \
+ template <class Fp BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class Arg) > \
+ class invoker<Fp BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Arg)> \
+ { \
+ Fp fp_; \
+ BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
+ public: \
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
+ typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
+ \
+ template <class F BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
+ BOOST_SYMBOL_VISIBLE \
+ explicit invoker(BOOST_THREAD_FWD_REF(F) f \
+ BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \
+ ) \
+ : fp_(boost::forward<F>(f)) \
+ BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \
+ {} \
+ \
+ BOOST_SYMBOL_VISIBLE \
+ invoker(BOOST_THREAD_RV_REF(invoker) x) \
+ : fp_(boost::move(x.fp_)) \
+ BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
+ {} \
+ \
+ result_type operator()() { \
+ return invoke(boost::move(fp_) \
+ BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \
+ ); \
+ } \
+ }; \
+ \
+ template <class R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class Arg) > \
+ class invoker<R(*)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)) BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Arg)> \
+ { \
+ typedef R(*Fp)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)); \
+ Fp fp_; \
+ BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \
+ public: \
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \
+ typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \
+ \
+ template <class R2 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \
+ BOOST_SYMBOL_VISIBLE \
+ explicit invoker(R2(*f)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_A_T, ~)) \
+ BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \
+ ) \
+ : fp_(f) \
+ BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \
+ {} \
+ \
+ BOOST_SYMBOL_VISIBLE \
+ invoker(BOOST_THREAD_RV_REF(invoker) x) \
+ : fp_(x.fp_) \
+ BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
+ {} \
+ \
+ result_type operator()() { \
+ return fp_( \
+ BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL_T, ~) \
+ ); \
+ } \
+ };
+
+ BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ASYNC_FUNCT, ~)
+
+ #undef BOOST_THREAD_RV_REF_ARG_T
+ #undef BOOST_THREAD_RV_REF_ARG
+ #undef BOOST_THREAD_FWD_REF_ARG
+ #undef BOOST_THREAD_FWD_REF_A
+ #undef BOOST_THREAD_FWD_PARAM
+ #undef BOOST_THREAD_FWD_PARAM_A
+ #undef BOOST_THREAD_DCL
+ #undef BOOST_THREAD_MOVE_PARAM
+ #undef BOOST_THREAD_MOVE_RHS_PARAM
+ #undef BOOST_THREAD_MOVE_DCL
+ #undef BOOST_THREAD_ARG_DEF
+ #undef BOOST_THREAD_ASYNC_FUNCT
+
+#else
+
+ template <class Fp,
+ class T0 = tuples::null_type, class T1 = tuples::null_type, class T2 = tuples::null_type,
+ class T3 = tuples::null_type, class T4 = tuples::null_type, class T5 = tuples::null_type,
+ class T6 = tuples::null_type, class T7 = tuples::null_type, class T8 = tuples::null_type
+ , class T9 = tuples::null_type
+ >
+ class invoker;
+
+ template <class Fp,
+ class T0 , class T1 , class T2 ,
+ class T3 , class T4 , class T5 ,
+ class T6 , class T7 , class T8 >
+ class invoker<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8>
+ {
+ Fp fp_;
+ T0 v0_;
+ T1 v1_;
+ T2 v2_;
+ T3 v3_;
+ T4 v4_;
+ T5 v5_;
+ T6 v6_;
+ T7 v7_;
+ T8 v8_;
+ //::boost::tuple<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> f_;
+
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7, T8)>::type result_type;
+
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
+ , BOOST_THREAD_RV_REF(T0) a0
+ , BOOST_THREAD_RV_REF(T1) a1
+ , BOOST_THREAD_RV_REF(T2) a2
+ , BOOST_THREAD_RV_REF(T3) a3
+ , BOOST_THREAD_RV_REF(T4) a4
+ , BOOST_THREAD_RV_REF(T5) a5
+ , BOOST_THREAD_RV_REF(T6) a6
+ , BOOST_THREAD_RV_REF(T7) a7
+ , BOOST_THREAD_RV_REF(T8) a8
+ )
+ : fp_(boost::move(f))
+ , v0_(boost::move(a0))
+ , v1_(boost::move(a1))
+ , v2_(boost::move(a2))
+ , v3_(boost::move(a3))
+ , v4_(boost::move(a4))
+ , v5_(boost::move(a5))
+ , v6_(boost::move(a6))
+ , v7_(boost::move(a7))
+ , v8_(boost::move(a8))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(boost::move(BOOST_THREAD_RV(f).fp))
+ , v0_(boost::move(BOOST_THREAD_RV(f).v0_))
+ , v1_(boost::move(BOOST_THREAD_RV(f).v1_))
+ , v2_(boost::move(BOOST_THREAD_RV(f).v2_))
+ , v3_(boost::move(BOOST_THREAD_RV(f).v3_))
+ , v4_(boost::move(BOOST_THREAD_RV(f).v4_))
+ , v5_(boost::move(BOOST_THREAD_RV(f).v5_))
+ , v6_(boost::move(BOOST_THREAD_RV(f).v6_))
+ , v7_(boost::move(BOOST_THREAD_RV(f).v7_))
+ , v8_(boost::move(BOOST_THREAD_RV(f).v8_))
+ {}
+
+ result_type operator()()
+ {
+ return invoke(boost::move(fp_)
+ , boost::move(v0_)
+ , boost::move(v1_)
+ , boost::move(v2_)
+ , boost::move(v3_)
+ , boost::move(v4_)
+ , boost::move(v5_)
+ , boost::move(v6_)
+ , boost::move(v7_)
+ , boost::move(v8_)
+ );
+ }
+ };
+ template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
+ class invoker<Fp, T0, T1, T2, T3, T4, T5, T6, T7>
+ {
+ Fp fp_;
+ T0 v0_;
+ T1 v1_;
+ T2 v2_;
+ T3 v3_;
+ T4 v4_;
+ T5 v5_;
+ T6 v6_;
+ T7 v7_;
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7)>::type result_type;
+
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
+ , BOOST_THREAD_RV_REF(T0) a0
+ , BOOST_THREAD_RV_REF(T1) a1
+ , BOOST_THREAD_RV_REF(T2) a2
+ , BOOST_THREAD_RV_REF(T3) a3
+ , BOOST_THREAD_RV_REF(T4) a4
+ , BOOST_THREAD_RV_REF(T5) a5
+ , BOOST_THREAD_RV_REF(T6) a6
+ , BOOST_THREAD_RV_REF(T7) a7
+ )
+ : fp_(boost::move(f))
+ , v0_(boost::move(a0))
+ , v1_(boost::move(a1))
+ , v2_(boost::move(a2))
+ , v3_(boost::move(a3))
+ , v4_(boost::move(a4))
+ , v5_(boost::move(a5))
+ , v6_(boost::move(a6))
+ , v7_(boost::move(a7))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(boost::move(BOOST_THREAD_RV(f).fp))
+ , v0_(boost::move(BOOST_THREAD_RV(f).v0_))
+ , v1_(boost::move(BOOST_THREAD_RV(f).v1_))
+ , v2_(boost::move(BOOST_THREAD_RV(f).v2_))
+ , v3_(boost::move(BOOST_THREAD_RV(f).v3_))
+ , v4_(boost::move(BOOST_THREAD_RV(f).v4_))
+ , v5_(boost::move(BOOST_THREAD_RV(f).v5_))
+ , v6_(boost::move(BOOST_THREAD_RV(f).v6_))
+ , v7_(boost::move(BOOST_THREAD_RV(f).v7_))
+ {}
+
+ result_type operator()()
+ {
+ return invoke(boost::move(fp_)
+ , boost::move(v0_)
+ , boost::move(v1_)
+ , boost::move(v2_)
+ , boost::move(v3_)
+ , boost::move(v4_)
+ , boost::move(v5_)
+ , boost::move(v6_)
+ , boost::move(v7_)
+ );
+ }
+ };
+ template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6>
+ class invoker<Fp, T0, T1, T2, T3, T4, T5, T6>
+ {
+ Fp fp_;
+ T0 v0_;
+ T1 v1_;
+ T2 v2_;
+ T3 v3_;
+ T4 v4_;
+ T5 v5_;
+ T6 v6_;
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6)>::type result_type;
+
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
+ , BOOST_THREAD_RV_REF(T0) a0
+ , BOOST_THREAD_RV_REF(T1) a1
+ , BOOST_THREAD_RV_REF(T2) a2
+ , BOOST_THREAD_RV_REF(T3) a3
+ , BOOST_THREAD_RV_REF(T4) a4
+ , BOOST_THREAD_RV_REF(T5) a5
+ , BOOST_THREAD_RV_REF(T6) a6
+ )
+ : fp_(boost::move(f))
+ , v0_(boost::move(a0))
+ , v1_(boost::move(a1))
+ , v2_(boost::move(a2))
+ , v3_(boost::move(a3))
+ , v4_(boost::move(a4))
+ , v5_(boost::move(a5))
+ , v6_(boost::move(a6))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(boost::move(BOOST_THREAD_RV(f).fp))
+ , v0_(boost::move(BOOST_THREAD_RV(f).v0_))
+ , v1_(boost::move(BOOST_THREAD_RV(f).v1_))
+ , v2_(boost::move(BOOST_THREAD_RV(f).v2_))
+ , v3_(boost::move(BOOST_THREAD_RV(f).v3_))
+ , v4_(boost::move(BOOST_THREAD_RV(f).v4_))
+ , v5_(boost::move(BOOST_THREAD_RV(f).v5_))
+ , v6_(boost::move(BOOST_THREAD_RV(f).v6_))
+ {}
+
+ result_type operator()()
+ {
+ return invoke(boost::move(fp_)
+ , boost::move(v0_)
+ , boost::move(v1_)
+ , boost::move(v2_)
+ , boost::move(v3_)
+ , boost::move(v4_)
+ , boost::move(v5_)
+ , boost::move(v6_)
+ );
+ }
+ };
+ template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5>
+ class invoker<Fp, T0, T1, T2, T3, T4, T5>
+ {
+ Fp fp_;
+ T0 v0_;
+ T1 v1_;
+ T2 v2_;
+ T3 v3_;
+ T4 v4_;
+ T5 v5_;
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5)>::type result_type;
+
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
+ , BOOST_THREAD_RV_REF(T0) a0
+ , BOOST_THREAD_RV_REF(T1) a1
+ , BOOST_THREAD_RV_REF(T2) a2
+ , BOOST_THREAD_RV_REF(T3) a3
+ , BOOST_THREAD_RV_REF(T4) a4
+ , BOOST_THREAD_RV_REF(T5) a5
+ )
+ : fp_(boost::move(f))
+ , v0_(boost::move(a0))
+ , v1_(boost::move(a1))
+ , v2_(boost::move(a2))
+ , v3_(boost::move(a3))
+ , v4_(boost::move(a4))
+ , v5_(boost::move(a5))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(boost::move(BOOST_THREAD_RV(f).fp))
+ , v0_(boost::move(BOOST_THREAD_RV(f).v0_))
+ , v1_(boost::move(BOOST_THREAD_RV(f).v1_))
+ , v2_(boost::move(BOOST_THREAD_RV(f).v2_))
+ , v3_(boost::move(BOOST_THREAD_RV(f).v3_))
+ , v4_(boost::move(BOOST_THREAD_RV(f).v4_))
+ , v5_(boost::move(BOOST_THREAD_RV(f).v5_))
+ {}
+
+ result_type operator()()
+ {
+ return invoke(boost::move(fp_)
+ , boost::move(v0_)
+ , boost::move(v1_)
+ , boost::move(v2_)
+ , boost::move(v3_)
+ , boost::move(v4_)
+ , boost::move(v5_)
+ );
+ }
+ };
+ template <class Fp, class T0, class T1, class T2, class T3, class T4>
+ class invoker<Fp, T0, T1, T2, T3, T4>
+ {
+ Fp fp_;
+ T0 v0_;
+ T1 v1_;
+ T2 v2_;
+ T3 v3_;
+ T4 v4_;
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp(T0, T1, T2, T3, T4)>::type result_type;
+
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
+ , BOOST_THREAD_RV_REF(T0) a0
+ , BOOST_THREAD_RV_REF(T1) a1
+ , BOOST_THREAD_RV_REF(T2) a2
+ , BOOST_THREAD_RV_REF(T3) a3
+ , BOOST_THREAD_RV_REF(T4) a4
+ )
+ : fp_(boost::move(f))
+ , v0_(boost::move(a0))
+ , v1_(boost::move(a1))
+ , v2_(boost::move(a2))
+ , v3_(boost::move(a3))
+ , v4_(boost::move(a4))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(boost::move(BOOST_THREAD_RV(f).fp))
+ , v0_(boost::move(BOOST_THREAD_RV(f).v0_))
+ , v1_(boost::move(BOOST_THREAD_RV(f).v1_))
+ , v2_(boost::move(BOOST_THREAD_RV(f).v2_))
+ , v3_(boost::move(BOOST_THREAD_RV(f).v3_))
+ , v4_(boost::move(BOOST_THREAD_RV(f).v4_))
+ {}
+
+ result_type operator()()
+ {
+ return invoke(boost::move(fp_)
+ , boost::move(v0_)
+ , boost::move(v1_)
+ , boost::move(v2_)
+ , boost::move(v3_)
+ , boost::move(v4_)
+ );
+ }
+ };
+ template <class Fp, class T0, class T1, class T2, class T3>
+ class invoker<Fp, T0, T1, T2, T3>
+ {
+ Fp fp_;
+ T0 v0_;
+ T1 v1_;
+ T2 v2_;
+ T3 v3_;
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp(T0, T1, T2, T3)>::type result_type;
+
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
+ , BOOST_THREAD_RV_REF(T0) a0
+ , BOOST_THREAD_RV_REF(T1) a1
+ , BOOST_THREAD_RV_REF(T2) a2
+ , BOOST_THREAD_RV_REF(T3) a3
+ )
+ : fp_(boost::move(f))
+ , v0_(boost::move(a0))
+ , v1_(boost::move(a1))
+ , v2_(boost::move(a2))
+ , v3_(boost::move(a3))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(boost::move(BOOST_THREAD_RV(f).fp))
+ , v0_(boost::move(BOOST_THREAD_RV(f).v0_))
+ , v1_(boost::move(BOOST_THREAD_RV(f).v1_))
+ , v2_(boost::move(BOOST_THREAD_RV(f).v2_))
+ , v3_(boost::move(BOOST_THREAD_RV(f).v3_))
+ {}
+
+ result_type operator()()
+ {
+ return invoke(boost::move(fp_)
+ , boost::move(v0_)
+ , boost::move(v1_)
+ , boost::move(v2_)
+ , boost::move(v3_)
+ );
+ }
+ };
+ template <class Fp, class T0, class T1, class T2>
+ class invoker<Fp, T0, T1, T2>
+ {
+ Fp fp_;
+ T0 v0_;
+ T1 v1_;
+ T2 v2_;
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp(T0, T1, T2)>::type result_type;
+
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
+ , BOOST_THREAD_RV_REF(T0) a0
+ , BOOST_THREAD_RV_REF(T1) a1
+ , BOOST_THREAD_RV_REF(T2) a2
+ )
+ : fp_(boost::move(f))
+ , v0_(boost::move(a0))
+ , v1_(boost::move(a1))
+ , v2_(boost::move(a2))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(boost::move(BOOST_THREAD_RV(f).fp))
+ , v0_(boost::move(BOOST_THREAD_RV(f).v0_))
+ , v1_(boost::move(BOOST_THREAD_RV(f).v1_))
+ , v2_(boost::move(BOOST_THREAD_RV(f).v2_))
+ {}
+
+ result_type operator()()
+ {
+ return invoke(boost::move(fp_)
+ , boost::move(v0_)
+ , boost::move(v1_)
+ , boost::move(v2_)
+ );
+ }
+ };
+ template <class Fp, class T0, class T1>
+ class invoker<Fp, T0, T1>
+ {
+ Fp fp_;
+ T0 v0_;
+ T1 v1_;
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp(T0, T1)>::type result_type;
+
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
+ , BOOST_THREAD_RV_REF(T0) a0
+ , BOOST_THREAD_RV_REF(T1) a1
+ )
+ : fp_(boost::move(f))
+ , v0_(boost::move(a0))
+ , v1_(boost::move(a1))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(boost::move(BOOST_THREAD_RV(f).fp))
+ , v0_(boost::move(BOOST_THREAD_RV(f).v0_))
+ , v1_(boost::move(BOOST_THREAD_RV(f).v1_))
+ {}
+
+ result_type operator()()
+ {
+ return invoke(boost::move(fp_)
+ , boost::move(v0_)
+ , boost::move(v1_)
+ );
+ }
+ };
+ template <class Fp, class T0>
+ class invoker<Fp, T0>
+ {
+ Fp fp_;
+ T0 v0_;
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp(T0)>::type result_type;
+
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(Fp) f
+ , BOOST_THREAD_RV_REF(T0) a0
+ )
+ : fp_(boost::move(f))
+ , v0_(boost::move(a0))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(boost::move(BOOST_THREAD_RV(f).fp))
+ , v0_(boost::move(BOOST_THREAD_RV(f).v0_))
+ {}
+
+ result_type operator()()
+ {
+ return invoke(boost::move(fp_)
+ , boost::move(v0_)
+ );
+ }
+ };
+ template <class Fp>
+ class invoker<Fp>
+ {
+ Fp fp_;
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp()>::type result_type;
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(BOOST_THREAD_FWD_REF(Fp) f)
+ : fp_(boost::move(f))
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(boost::move(f.fp_))
+ {}
+ result_type operator()()
+ {
+ return fp_();
+ }
+ };
+ template <class R>
+ class invoker<R(*)()>
+ {
+ typedef R(*Fp)();
+ Fp fp_;
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker)
+ typedef typename result_of<Fp()>::type result_type;
+ BOOST_SYMBOL_VISIBLE
+ explicit invoker(Fp f)
+ : fp_(f)
+ {}
+
+ BOOST_SYMBOL_VISIBLE
+ invoker(BOOST_THREAD_RV_REF(invoker) f)
+ : fp_(f.fp_)
+ {}
+ result_type operator()()
+ {
+ return fp_();
+ }
+ };
+#endif
+#endif
+
+ }
+}
+
+#include <boost/thread/detail/variadic_footer.hpp>
+
+#endif // header
diff --git a/boost/thread/detail/is_convertible.hpp b/boost/thread/detail/is_convertible.hpp
new file mode 100644
index 0000000000..b77620cf17
--- /dev/null
+++ b/boost/thread/detail/is_convertible.hpp
@@ -0,0 +1,49 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2011-2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_THREAD_DETAIL_IS_CONVERTIBLE_HPP
+#define BOOST_THREAD_DETAIL_IS_CONVERTIBLE_HPP
+
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/thread/detail/move.hpp>
+
+namespace boost
+{
+ namespace thread_detail
+ {
+ template <typename T1, typename T2>
+ struct is_convertible : boost::is_convertible<T1,T2> {};
+
+#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#if defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION <= 1300)
+
+#if defined BOOST_THREAD_USES_MOVE
+ template <typename T1, typename T2>
+ struct is_convertible<
+ rv<T1> &,
+ rv<rv<T2> > &
+ > : false_type {};
+#endif
+
+#elif defined __GNUC__ && (__GNUC__ < 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ <= 4 ))
+
+ template <typename T1, typename T2>
+ struct is_convertible<T1&, T2&> : boost::is_convertible<T1, T2> {};
+#endif
+
+#endif
+ }
+
+} // namespace boost
+
+
+#endif // BOOST_THREAD_DETAIL_MEMORY_HPP
diff --git a/boost/thread/detail/lockable_wrapper.hpp b/boost/thread/detail/lockable_wrapper.hpp
new file mode 100644
index 0000000000..8dc5a6cc78
--- /dev/null
+++ b/boost/thread/detail/lockable_wrapper.hpp
@@ -0,0 +1,45 @@
+// 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)
+// (C) Copyright 2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_DETAIL_LOCKABLE_WRAPPER_HPP
+#define BOOST_THREAD_DETAIL_LOCKABLE_WRAPPER_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST
+#include <initializer_list>
+#endif
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST
+ namespace thread_detail
+ {
+ template <typename Mutex>
+ struct lockable_wrapper
+ {
+ Mutex* m;
+ explicit lockable_wrapper(Mutex& m_) :
+ m(&m_)
+ {}
+ };
+ template <typename Mutex>
+ struct lockable_adopt_wrapper
+ {
+ Mutex* m;
+ explicit lockable_adopt_wrapper(Mutex& m_) :
+ m(&m_)
+ {}
+ };
+ }
+#endif
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // header
diff --git a/boost/thread/detail/log.hpp b/boost/thread/detail/log.hpp
new file mode 100644
index 0000000000..84dcc8cb41
--- /dev/null
+++ b/boost/thread/detail/log.hpp
@@ -0,0 +1,83 @@
+// Copyright (C) 2012 Vicente J. Botet Escriba
+//
+// 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)
+
+#ifndef BOOST_THREAD_DETAIL_LOG_HPP
+#define BOOST_THREAD_DETAIL_LOG_HPP
+
+#include <boost/thread/detail/config.hpp>
+#if defined BOOST_THREAD_USES_LOG
+#include <boost/thread/recursive_mutex.hpp>
+#include <boost/thread/lock_guard.hpp>
+#if defined BOOST_THREAD_USES_LOG_THREAD_ID
+#include <boost/thread/thread.hpp>
+#endif
+#include <iostream>
+
+namespace boost
+{
+ namespace thread_detail
+ {
+ inline boost::recursive_mutex& terminal_mutex()
+ {
+ static boost::recursive_mutex mtx;
+ return mtx;
+ }
+
+ }
+}
+#if defined BOOST_THREAD_USES_LOG_THREAD_ID
+
+#define BOOST_THREAD_LOG \
+ { \
+ boost::lock_guard<boost::recursive_mutex> _lk_(boost::thread_detail::terminal_mutex()); \
+ std::cout << boost::this_thread::get_id() << " - "<<__FILE__<<"["<<__LINE__<<"] " <<std::dec
+#else
+
+#define BOOST_THREAD_LOG \
+{ \
+ boost::lock_guard<boost::recursive_mutex> _lk_(boost::thread_detail::terminal_mutex()); \
+ std::cout << __FILE__<<"["<<__LINE__<<"] " <<std::dec
+
+#endif
+#define BOOST_THREAD_END_LOG \
+ std::dec << std::endl; \
+ }
+
+#else
+
+namespace boost
+{
+ namespace thread_detail
+ {
+ struct dummy_stream_t
+ {
+ };
+
+ template <typename T>
+ inline dummy_stream_t const& operator<<(dummy_stream_t const& os, T)
+ {
+ return os;
+ }
+
+ inline dummy_stream_t const& operator<<(dummy_stream_t const& os, dummy_stream_t const&)
+ {
+ return os;
+ }
+
+
+ BOOST_CONSTEXPR_OR_CONST dummy_stream_t dummy_stream = {};
+
+ }
+}
+
+#define BOOST_THREAD_LOG if (true) {} else boost::thread_detail::dummy_stream
+#define BOOST_THREAD_END_LOG boost::thread_detail::dummy_stream
+
+#endif
+
+#define BOOST_THREAD_TRACE BOOST_THREAD_LOG << BOOST_THREAD_END_LOG
+
+
+#endif // header
diff --git a/boost/thread/detail/make_tuple_indices.hpp b/boost/thread/detail/make_tuple_indices.hpp
new file mode 100644
index 0000000000..73d54f11f8
--- /dev/null
+++ b/boost/thread/detail/make_tuple_indices.hpp
@@ -0,0 +1,224 @@
+// Copyright (C) 2012-2013 Vicente J. Botet Escriba
+//
+// 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)
+
+// 2013/04 Vicente J. Botet Escriba
+// Provide implementation up to 10 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined.
+// 2012/11 Vicente J. Botet Escriba
+// Adapt to boost libc++ implementation
+
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+// The make_tuple_indices C++11 code is based on the one from libcxx.
+//===----------------------------------------------------------------------===//
+
+#ifndef BOOST_THREAD_DETAIL_MAKE_TUPLE_INDICES_HPP
+#define BOOST_THREAD_DETAIL_MAKE_TUPLE_INDICES_HPP
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+
+namespace boost
+{
+ namespace detail
+ {
+
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ // make_tuple_indices
+
+ template <std::size_t...> struct tuple_indices
+ {};
+
+ template <std::size_t Sp, class IntTuple, std::size_t Ep>
+ struct make_indices_imp;
+
+ template <std::size_t Sp, std::size_t ...Indices, std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<Indices...>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<Indices..., Sp>, Ep>::type type;
+ };
+
+ template <std::size_t Ep, std::size_t ...Indices>
+ struct make_indices_imp<Ep, tuple_indices<Indices...>, Ep>
+ {
+ typedef tuple_indices<Indices...> type;
+ };
+
+ template <std::size_t Ep, std::size_t Sp = 0>
+ struct make_tuple_indices
+ {
+ BOOST_STATIC_ASSERT_MSG(Sp <= Ep, "make_tuple_indices input error");
+ typedef typename make_indices_imp<Sp, tuple_indices<>, Ep>::type type;
+ };
+#else
+
+ // - tuple forward declaration -----------------------------------------------
+ template <
+ std::size_t T0 = 0, std::size_t T1 = 0, std::size_t T2 = 0,
+ std::size_t T3 = 0, std::size_t T4 = 0, std::size_t T5 = 0,
+ std::size_t T6 = 0, std::size_t T7 = 0, std::size_t T8 = 0,
+ std::size_t T9 = 0>
+ class tuple_indices {};
+
+ template <std::size_t Sp, class IntTuple, std::size_t Ep>
+ struct make_indices_imp;
+
+ template <std::size_t Sp, std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<Sp>, Ep>::type type;
+ };
+ template <std::size_t Sp, std::size_t I0, std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<I0>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<I0, Sp>, Ep>::type type;
+ };
+ template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<I0, I1>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, Sp>, Ep>::type type;
+ };
+ template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, Sp>, Ep>::type type;
+ };
+ template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, Sp>, Ep>::type type;
+ };
+ template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, Sp>, Ep>::type type;
+ };
+ template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5, std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4, I5>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, I5, Sp>, Ep>::type type;
+ };
+ template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5
+ , std::size_t I6
+ , std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4, I5, I6>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, I5, I6, Sp>, Ep>::type type;
+ };
+ template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5
+ , std::size_t I6
+ , std::size_t I7
+ , std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4, I5, I6, I7>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, Sp>, Ep>::type type;
+ };
+ template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5
+ , std::size_t I6
+ , std::size_t I7
+ , std::size_t I8
+ , std::size_t Ep>
+ struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4, I5, I6, I7, I8>, Ep>
+ {
+ typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8, Sp>, Ep>::type type;
+ };
+// template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5
+// , std::size_t I6
+// , std::size_t I7
+// , std::size_t I8
+// , std::size_t I9
+// , std::size_t Ep>
+// struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4, I5, I6, I7, I8, I9>, Ep>
+// {
+// typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, Sp>, Ep>::type type;
+// };
+
+ template <std::size_t Ep>
+ struct make_indices_imp<Ep, tuple_indices<>, Ep>
+ {
+ typedef tuple_indices<> type;
+ };
+ template <std::size_t Ep, std::size_t I0>
+ struct make_indices_imp<Ep, tuple_indices<I0>, Ep>
+ {
+ typedef tuple_indices<I0> type;
+ };
+ template <std::size_t Ep, std::size_t I0, std::size_t I1>
+ struct make_indices_imp<Ep, tuple_indices<I0, I1>, Ep>
+ {
+ typedef tuple_indices<I0, I1> type;
+ };
+ template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2>
+ struct make_indices_imp<Ep, tuple_indices<I0, I1, I2>, Ep>
+ {
+ typedef tuple_indices<I0, I1, I2> type;
+ };
+ template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3>
+ struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3>, Ep>
+ {
+ typedef tuple_indices<I0, I1, I2, I3> type;
+ };
+ template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4>
+ struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4>, Ep>
+ {
+ typedef tuple_indices<I0, I1, I2, I3, I4> type;
+ };
+ template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5>
+ struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4, I5>, Ep>
+ {
+ typedef tuple_indices<I0, I1, I2, I3, I4, I5> type;
+ };
+ template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5
+ , std::size_t I6
+ >
+ struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4, I5, I6>, Ep>
+ {
+ typedef tuple_indices<I0, I1, I2, I3, I4, I5, I6> type;
+ };
+ template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5
+ , std::size_t I6
+ , std::size_t I7
+ >
+ struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7>, Ep>
+ {
+ typedef tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7> type;
+ };
+ template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5
+ , std::size_t I6
+ , std::size_t I7
+ , std::size_t I8
+ >
+ struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8>, Ep>
+ {
+ typedef tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8> type;
+ };
+
+ template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5
+ , std::size_t I6
+ , std::size_t I7
+ , std::size_t I8
+ , std::size_t I9
+ >
+ struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8, I9>, Ep>
+ {
+ typedef tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8, I9> type;
+ };
+
+ template <std::size_t Ep, std::size_t Sp = 0>
+ struct make_tuple_indices
+ {
+ BOOST_STATIC_ASSERT_MSG(Sp <= Ep, "make_tuple_indices input error");
+ typedef typename make_indices_imp<Sp, tuple_indices<>, Ep>::type type;
+ };
+
+#endif
+ }
+}
+
+#endif // header
diff --git a/boost/thread/detail/memory.hpp b/boost/thread/detail/memory.hpp
index 7d47efc781..51ce84f40b 100644
--- a/boost/thread/detail/memory.hpp
+++ b/boost/thread/detail/memory.hpp
@@ -1,8 +1,9 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright 2011-2012 Vicente J. Botet Escriba
-// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright (C) 2011-2013 Vicente J. Botet Escriba
+//
+// 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)
//
// See http://www.boost.org/libs/thread for documentation.
//
@@ -11,10 +12,13 @@
#ifndef BOOST_THREAD_DETAIL_MEMORY_HPP
#define BOOST_THREAD_DETAIL_MEMORY_HPP
-#include <boost/container/allocator_traits.hpp>
-#include <boost/container/scoped_allocator.hpp>
#include <boost/config.hpp>
+#include <boost/thread/csbl/memory/pointer_traits.hpp>
+#include <boost/thread/csbl/memory/allocator_arg.hpp>
+#include <boost/thread/csbl/memory/allocator_traits.hpp>
+#include <boost/thread/csbl/memory/scoped_allocator.hpp>
+
namespace boost
{
namespace thread_detail
@@ -22,12 +26,12 @@ namespace boost
template <class _Alloc>
class allocator_destructor
{
- typedef container::allocator_traits<_Alloc> alloc_traits;
+ typedef csbl::allocator_traits<_Alloc> alloc_traits;
public:
typedef typename alloc_traits::pointer pointer;
typedef typename alloc_traits::size_type size_type;
private:
- _Alloc& alloc_;
+ _Alloc alloc_;
size_type s_;
public:
allocator_destructor(_Alloc& a, size_type s)BOOST_NOEXCEPT
@@ -35,20 +39,10 @@ namespace boost
{}
void operator()(pointer p)BOOST_NOEXCEPT
{
+ alloc_traits::destroy(alloc_, p);
alloc_traits::deallocate(alloc_, p, s_);
}
};
} //namespace thread_detail
-
- typedef container::allocator_arg_t allocator_arg_t;
- BOOST_CONSTEXPR_OR_CONST allocator_arg_t allocator_arg = {};
-
- template <class T, class Alloc>
- struct uses_allocator: public container::uses_allocator<T, Alloc>
- {
- };
-
-} // namespace boost
-
-
+}
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP
diff --git a/boost/thread/detail/move.hpp b/boost/thread/detail/move.hpp
index 748b8dc241..611557093e 100644
--- a/boost/thread/detail/move.hpp
+++ b/boost/thread/detail/move.hpp
@@ -9,24 +9,34 @@
#include <boost/thread/detail/config.hpp>
#ifndef BOOST_NO_SFINAE
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/decay.hpp>
+#include <boost/type_traits/conditional.hpp>
+#include <boost/type_traits/remove_extent.hpp>
+#include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+#include <boost/type_traits/decay.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/move/traits.hpp>
#include <boost/config/abi_prefix.hpp>
-
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#include <type_traits>
+#endif
namespace boost
{
namespace detail
{
template <typename T>
- struct has_move_emulation_enabled_aux_dummy_specialization;
+ struct enable_move_utility_emulation_dummy_specialization;
template<typename T>
struct thread_move_t
{
@@ -49,6 +59,7 @@ namespace boost
};
}
+#if !defined BOOST_THREAD_USES_MOVE
#ifndef BOOST_NO_SFINAE
template<typename T>
@@ -63,11 +74,15 @@ namespace boost
{
return t;
}
+
+#endif //#if !defined BOOST_THREAD_USES_MOVE
}
-#if ! defined BOOST_NO_RVALUE_REFERENCES
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
+#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END
#define BOOST_THREAD_RV(V) V
@@ -77,16 +92,18 @@ namespace boost
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
- struct has_move_emulation_enabled_aux_dummy_specialization<
+ struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
- : integral_constant<bool, true> \
+ : integral_constant<bool, false> \
{}; \
}
-#elif ! defined BOOST_NO_RVALUE_REFERENCES && defined BOOST_MSVC
+#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_MSVC
+#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
+#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END
#define BOOST_THREAD_RV(V) V
@@ -96,17 +113,19 @@ namespace boost
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
- struct has_move_emulation_enabled_aux_dummy_specialization<
+ struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
- : integral_constant<bool, true> \
+ : integral_constant<bool, false> \
{}; \
}
#else
#if defined BOOST_THREAD_USES_MOVE
+#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE)
+#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE)
#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG
#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END
#define BOOST_THREAD_RV(V) V
@@ -115,15 +134,16 @@ namespace boost
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
- struct has_move_emulation_enabled_aux_dummy_specialization<
+ struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
- : integral_constant<bool, true> \
+ : integral_constant<bool, false> \
{}; \
}
#else
+#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) const TYPE&
#define BOOST_THREAD_RV_REF(TYPE) boost::detail::thread_move_t< TYPE >
#define BOOST_THREAD_RV_REF_BEG boost::detail::thread_move_t<
#define BOOST_THREAD_RV_REF_END >
@@ -132,17 +152,19 @@ namespace boost
#define BOOST_THREAD_DCL_MOVABLE(TYPE) \
template <> \
-struct has_move_emulation_enabled_aux< TYPE > \
- : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> \
-{};
+struct enable_move_utility_emulation< TYPE > \
+{ \
+ static const bool value = false; \
+};
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
template <typename T> \
-struct has_move_emulation_enabled_aux<
+struct enable_move_utility_emulation<
#define BOOST_THREAD_DCL_MOVABLE_END > \
- : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> \
-{};
+{ \
+ static const bool value = false; \
+};
#endif
@@ -176,10 +198,12 @@ namespace detail
#endif
-#if ! defined BOOST_NO_RVALUE_REFERENCES
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_MOVABLE(TYPE)
+#define BOOST_THREAD_COPYABLE(TYPE)
+
#else
#if defined BOOST_THREAD_USES_MOVE
@@ -202,6 +226,11 @@ namespace detail
return *static_cast<const ::boost::rv<TYPE>* >(this); \
}\
+#define BOOST_THREAD_COPYABLE(TYPE) \
+ TYPE& operator=(TYPE &t)\
+ { this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}
+
+
#else
#define BOOST_THREAD_MOVABLE(TYPE) \
@@ -215,31 +244,111 @@ namespace detail
return x; \
} \
+#define BOOST_THREAD_COPYABLE(TYPE)
+
#endif
#endif
#define BOOST_THREAD_MOVABLE_ONLY(TYPE) \
BOOST_THREAD_NO_COPYABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
+ typedef int boost_move_no_copy_constructor_or_assign; \
+
#define BOOST_THREAD_COPYABLE_AND_MOVABLE(TYPE) \
- BOOST_THREAD_MOVABLE(TYPE) \
+ BOOST_THREAD_COPYABLE(TYPE) \
+ BOOST_THREAD_MOVABLE(TYPE) \
-#ifndef BOOST_NO_RVALUE_REFERENCES
namespace boost
-{ namespace thread_detail
+{
+ namespace thread_detail
+ {
+
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#elif defined BOOST_THREAD_USES_MOVE
+ template <class T>
+ struct is_rv
+ : ::boost::move_detail::is_rv<T>
+ {};
+
+#else
+ template <class T>
+ struct is_rv
+ : ::boost::integral_constant<bool, false>
+ {};
+
+ template <class T>
+ struct is_rv< ::boost::detail::thread_move_t<T> >
+ : ::boost::integral_constant<bool, true>
+ {};
+
+ template <class T>
+ struct is_rv< const ::boost::detail::thread_move_t<T> >
+ : ::boost::integral_constant<bool, true>
+ {};
+#endif
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class Tp>
+ struct remove_reference : boost::remove_reference<Tp> {};
+ template <class Tp>
+ struct decay : boost::decay<Tp> {};
+#else
+ template <class Tp>
+ struct remove_reference
+ {
+ typedef Tp type;
+ };
+ template <class Tp>
+ struct remove_reference<Tp&>
+ {
+ typedef Tp type;
+ };
+ template <class Tp>
+ struct remove_reference< rv<Tp> > {
+ typedef Tp type;
+ };
+
+ template <class Tp>
+ struct decay
{
+ private:
+ typedef typename boost::move_detail::remove_rvalue_reference<Tp>::type Up0;
+ typedef typename boost::remove_reference<Up0>::type Up;
+ public:
+ typedef typename conditional
+ <
+ is_array<Up>::value,
+ typename remove_extent<Up>::type*,
+ typename conditional
+ <
+ is_function<Up>::value,
+ typename add_pointer<Up>::type,
+ typename remove_cv<Up>::type
+ >::type
+ >::type type;
+ };
+#endif
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class T>
typename decay<T>::type
decay_copy(T&& t)
{
return boost::forward<T>(t);
}
+#else
+ template <class T>
+ typename decay<T>::type
+ decay_copy(BOOST_THREAD_FWD_REF(T) t)
+ {
+ return boost::forward<T>(t);
}
-}
#endif
+ }
+}
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/detail/nullary_function.hpp b/boost/thread/detail/nullary_function.hpp
new file mode 100644
index 0000000000..a0e9fd456a
--- /dev/null
+++ b/boost/thread/detail/nullary_function.hpp
@@ -0,0 +1,234 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/09 Vicente J. Botet Escriba
+// Adapt to boost from CCIA C++11 implementation
+// Make use of Boost.Move
+
+#ifndef BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP
+#define BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP
+
+#include <boost/config.hpp>
+#include <boost/thread/detail/memory.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/csbl/memory/shared_ptr.hpp>
+#include <boost/type_traits/decay.hpp>
+
+namespace boost
+{
+ namespace detail
+ {
+
+ template <typename F>
+ class nullary_function;
+ template <>
+ class nullary_function<void()>
+ {
+ struct impl_base
+ {
+ virtual void call()=0;
+ virtual ~impl_base()
+ {
+ }
+ };
+ csbl::shared_ptr<impl_base> impl;
+ template <typename F>
+ struct impl_type: impl_base
+ {
+ F f;
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ impl_type(F &f_)
+ : f(f_)
+ {}
+#endif
+ impl_type(BOOST_THREAD_RV_REF(F) f_)
+ : f(boost::move(f_))
+ {}
+
+ void call()
+ {
+ f();
+ }
+ };
+ struct impl_type_ptr: impl_base
+ {
+ void (*f)();
+ impl_type_ptr(void (*f_)())
+ : f(f_)
+ {}
+ void call()
+ {
+ f();
+ }
+ };
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
+
+ explicit nullary_function(void (*f)()):
+ impl(new impl_type_ptr(f))
+ {}
+
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template<typename F>
+ explicit nullary_function(F& f):
+ impl(new impl_type<F>(f))
+ {}
+#endif
+ template<typename F>
+ nullary_function(BOOST_THREAD_RV_REF(F) f):
+ impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
+ {}
+
+ nullary_function()
+ : impl()
+ {
+ }
+ nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
+ impl(other.impl)
+ {
+ }
+ nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
+#if defined BOOST_NO_CXX11_SMART_PTR
+ impl(BOOST_THREAD_RV(other).impl)
+ {
+ BOOST_THREAD_RV(other).impl.reset();
+ }
+#else
+ impl(boost::move(other.impl))
+ {
+ }
+#endif
+ ~nullary_function()
+ {
+ }
+
+ nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
+ {
+ impl=other.impl;
+ return *this;
+ }
+ nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
+ {
+#if defined BOOST_NO_CXX11_SMART_PTR
+ impl=BOOST_THREAD_RV(other).impl;
+ BOOST_THREAD_RV(other).impl.reset();
+#else
+ impl = boost::move(other.impl);
+#endif
+ return *this;
+ }
+
+
+ void operator()()
+ { if (impl) impl->call();}
+
+ };
+
+ template <typename R>
+ class nullary_function<R()>
+ {
+ struct impl_base
+ {
+ virtual R call()=0;
+ virtual ~impl_base()
+ {
+ }
+ };
+ csbl::shared_ptr<impl_base> impl;
+ template <typename F>
+ struct impl_type: impl_base
+ {
+ F f;
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ impl_type(F &f_)
+ : f(f_)
+ {}
+#endif
+ impl_type(BOOST_THREAD_RV_REF(F) f_)
+ : f(boost::move(f_))
+ {}
+
+ R call()
+ {
+ return f();
+ }
+ };
+ struct impl_type_ptr: impl_base
+ {
+ R (*f)();
+ impl_type_ptr(R (*f_)())
+ : f(f_)
+ {}
+
+ R call()
+ {
+ return f();
+ }
+ };
+ public:
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
+
+ nullary_function(R (*f)()):
+ impl(new impl_type_ptr(f))
+ {}
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template<typename F>
+ nullary_function(F& f):
+ impl(new impl_type<F>(f))
+ {}
+#endif
+ template<typename F>
+ nullary_function(BOOST_THREAD_RV_REF(F) f):
+ impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
+ {}
+
+ nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
+ impl(other.impl)
+ {
+ }
+ nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
+#if defined BOOST_NO_CXX11_SMART_PTR
+ impl(BOOST_THREAD_RV(other).impl)
+ {
+ BOOST_THREAD_RV(other).impl.reset();
+ }
+#else
+ impl(boost::move(other.impl))
+ {
+ }
+#endif
+ nullary_function()
+ : impl()
+ {
+ }
+ ~nullary_function()
+ {
+ }
+
+ nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
+ {
+ impl=other.impl;
+ return *this;
+ }
+ nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
+ {
+#if defined BOOST_NO_CXX11_SMART_PTR
+ impl=BOOST_THREAD_RV(other).impl;
+ BOOST_THREAD_RV(other).impl.reset();
+#else
+ impl = boost::move(other.impl);
+#endif
+ return *this;
+ }
+
+ R operator()()
+ { if (impl) return impl->call(); else return R();}
+
+ };
+ }
+ //BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
+}
+
+#endif // header
diff --git a/boost/thread/detail/thread.hpp b/boost/thread/detail/thread.hpp
index 3c71b53cf7..b80eacfa1b 100644
--- a/boost/thread/detail/thread.hpp
+++ b/boost/thread/detail/thread.hpp
@@ -3,27 +3,34 @@
// 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)
-// (C) Copyright 2007-10 Anthony Williams
-// (C) Copyright 20011-12 Vicente J. Botet Escriba
+// (C) Copyright 2007-2010 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
+#include <boost/predef/platform.h>
+
#include <boost/thread/exceptions.hpp>
#ifndef BOOST_NO_IOSTREAM
#include <ostream>
#endif
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
+#if defined BOOST_THREAD_USES_DATETIME
#include <boost/thread/xtime.hpp>
+#endif
#include <boost/thread/detail/thread_heap_alloc.hpp>
+#include <boost/thread/detail/make_tuple_indices.hpp>
+#include <boost/thread/detail/invoke.hpp>
+#include <boost/thread/detail/is_convertible.hpp>
#include <boost/assert.hpp>
#include <list>
#include <algorithm>
-#include <boost/ref.hpp>
+#include <boost/core/ref.hpp>
#include <boost/cstdint.hpp>
#include <boost/bind.hpp>
#include <stdlib.h>
#include <memory>
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/io/ios_state.hpp>
#include <boost/type_traits/is_same.hpp>
@@ -34,6 +41,9 @@
#include <boost/chrono/ceil.hpp>
#endif
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+#include <tuple>
+#endif
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_MSVC
@@ -46,13 +56,43 @@ namespace boost
namespace detail
{
+
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+
+ template<typename F, class ...ArgTypes>
+ class thread_data:
+ public detail::thread_data_base
+ {
+ public:
+ BOOST_THREAD_NO_COPYABLE(thread_data)
+ thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_):
+ fp(boost::forward<F>(f_), boost::forward<ArgTypes>(args_)...)
+ {}
+ template <std::size_t ...Indices>
+ void run2(tuple_indices<Indices...>)
+ {
+
+ invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
+ }
+ void run()
+ {
+ typedef typename make_tuple_indices<std::tuple_size<std::tuple<F, ArgTypes...> >::value, 1>::type index_type;
+
+ run2(index_type());
+ }
+
+ private:
+ std::tuple<typename decay<F>::type, typename decay<ArgTypes>::type...> fp;
+ };
+#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+
template<typename F>
class thread_data:
public detail::thread_data_base
{
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
thread_data(BOOST_THREAD_RV_REF(F) f_):
f(boost::forward<F>(f_))
{}
@@ -69,10 +109,13 @@ namespace boost
f(f_)
{}
#endif
+ //thread_data() {}
+
void run()
{
f();
}
+
private:
F f;
};
@@ -110,6 +153,7 @@ namespace boost
f();
}
};
+#endif
}
class BOOST_THREAD_DECL thread
@@ -120,24 +164,55 @@ namespace boost
BOOST_THREAD_MOVABLE_ONLY(thread)
private:
+ struct dummy;
+
void release_handle();
detail::thread_data_ptr thread_info;
- void start_thread();
- void start_thread(const attributes& attr);
+ private:
+ bool start_thread_noexcept();
+ bool start_thread_noexcept(const attributes& attr);
+ //public:
+ void start_thread()
+ {
+ if (!start_thread_noexcept())
+ {
+ boost::throw_exception(thread_resource_error());
+ }
+ }
+ void start_thread(const attributes& attr)
+ {
+ if (!start_thread_noexcept(attr))
+ {
+ boost::throw_exception(thread_resource_error());
+ }
+ }
explicit thread(detail::thread_data_ptr data);
detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const;
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template<typename F, class ...ArgTypes>
+ static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_RV_REF(ArgTypes)... args)
+ {
+ return detail::thread_data_ptr(detail::heap_new<
+ detail::thread_data<typename boost::remove_reference<F>::type, ArgTypes...>
+ >(
+ boost::forward<F>(f), boost::forward<ArgTypes>(args)...
+ )
+ );
+ }
+#else
template<typename F>
static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(
boost::forward<F>(f)));
}
+#endif
static inline detail::thread_data_ptr make_thread_info(void (*f)())
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(
@@ -145,7 +220,12 @@ namespace boost
}
#else
template<typename F>
- static inline detail::thread_data_ptr make_thread_info(F f)
+ static inline detail::thread_data_ptr make_thread_info(F f
+ , typename disable_if_c<
+ //boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value ||
+ is_same<typename decay<F>::type, thread>::value,
+ dummy* >::type=0
+ )
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
@@ -156,7 +236,6 @@ namespace boost
}
#endif
- struct dummy;
public:
#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
@@ -166,6 +245,7 @@ namespace boost
thread() BOOST_NOEXCEPT;
~thread()
{
+
#if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
if (joinable()) {
std::terminate();
@@ -174,12 +254,12 @@ namespace boost
detach();
#endif
}
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <
class F
>
explicit thread(BOOST_THREAD_RV_REF(F) f
- , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
+ //, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
{
@@ -188,7 +268,7 @@ namespace boost
template <
class F
>
- thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f):
+ thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f):
thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
{
start_thread(attrs);
@@ -203,7 +283,7 @@ namespace boost
start_thread();
}
template <class F>
- thread(attributes& attrs, F f):
+ thread(attributes const& attrs, F f):
thread_info(make_thread_info(f))
{
start_thread(attrs);
@@ -211,15 +291,21 @@ namespace boost
#else
template <class F>
explicit thread(F f
- // todo Disable also if Or is_same<typename decay<F>::type, thread>
- , typename disable_if<boost::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0):
+ , typename disable_if_c<
+ boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
+ //boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
+ //|| is_same<typename decay<F>::type, thread>::value
+ , dummy* >::type=0
+ ):
thread_info(make_thread_info(f))
{
start_thread();
}
template <class F>
- thread(attributes& attrs, F f
- , typename disable_if<boost::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0):
+ thread(attributes const& attrs, F f
+ , typename disable_if<boost::thread_detail::is_rv<F>, dummy* >::type=0
+ //, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
+ ):
thread_info(make_thread_info(f))
{
start_thread(attrs);
@@ -229,19 +315,27 @@ namespace boost
explicit thread(BOOST_THREAD_RV_REF(F) f
, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
- thread_info(make_thread_info(f))
+#ifdef BOOST_THREAD_USES_MOVE
+ thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward
+#else
+ thread_info(make_thread_info(f)) // todo : Add forward
+#endif
{
start_thread();
}
template <class F>
- thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f):
- thread_info(make_thread_info(f))
+ thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f):
+#ifdef BOOST_THREAD_USES_MOVE
+ thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward
+#else
+ thread_info(make_thread_info(f)) // todo : Add forward
+#endif
{
start_thread(attrs);
}
#endif
- thread(BOOST_THREAD_RV_REF(thread) x)
+ thread(BOOST_THREAD_RV_REF(thread) x) BOOST_NOEXCEPT
{
thread_info=BOOST_THREAD_RV(x).thread_info;
BOOST_THREAD_RV(x).thread_info.reset();
@@ -267,8 +361,32 @@ namespace boost
return *this;
}
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template <class F, class Arg, class ...Args>
+ thread(F&& f, Arg&& arg, Args&&... args) :
+ thread_info(make_thread_info(
+ thread_detail::decay_copy(boost::forward<F>(f)),
+ thread_detail::decay_copy(boost::forward<Arg>(arg)),
+ thread_detail::decay_copy(boost::forward<Args>(args))...)
+ )
+
+ {
+ start_thread();
+ }
+ template <class F, class Arg, class ...Args>
+ thread(attributes const& attrs, F&& f, Arg&& arg, Args&&... args) :
+ thread_info(make_thread_info(
+ thread_detail::decay_copy(boost::forward<F>(f)),
+ thread_detail::decay_copy(boost::forward<Arg>(arg)),
+ thread_detail::decay_copy(boost::forward<Args>(args))...)
+ )
+
+ {
+ start_thread(attrs);
+ }
+#else
template <class F,class A1>
- thread(F f,A1 a1,typename disable_if<boost::is_convertible<F&,thread_attributes >, dummy* >::type=0):
+ thread(F f,A1 a1,typename disable_if<boost::thread_detail::is_convertible<F&,thread_attributes >, dummy* >::type=0):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
{
start_thread();
@@ -328,31 +446,53 @@ namespace boost
{
start_thread();
}
-
+#endif
void swap(thread& x) BOOST_NOEXCEPT
{
thread_info.swap(x.thread_info);
}
- class BOOST_SYMBOL_VISIBLE id;
+ class id;
+#ifdef BOOST_THREAD_PLATFORM_PTHREAD
+ inline id get_id() const BOOST_NOEXCEPT;
+#else
id get_id() const BOOST_NOEXCEPT;
+#endif
bool joinable() const BOOST_NOEXCEPT;
- void join();
+ private:
+ bool join_noexcept();
+ public:
+ inline void join();
+
#ifdef BOOST_THREAD_USES_CHRONO
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+ template <class Rep, class Period>
+ bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ chrono::milliseconds rel_time2= chrono::ceil<chrono::milliseconds>(rel_time);
+ return do_try_join_until(rel_time2.count());
+ }
+#else
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_join_until(chrono::steady_clock::now() + rel_time);
}
+#endif
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
- typename Clock::time_point c_now = Clock::now();
- return try_join_until(s_now + ceil<nanoseconds>(t - c_now));
+ bool joined= false;
+ do {
+ 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);
+ } while (! joined);
+ return true;
}
template <class Duration>
bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t)
@@ -363,57 +503,72 @@ namespace boost
}
#endif
#if defined(BOOST_THREAD_PLATFORM_WIN32)
+ private:
+ bool do_try_join_until_noexcept(uintmax_t milli, bool& res);
+ inline bool do_try_join_until(uintmax_t milli);
+ public:
bool timed_join(const system_time& abs_time);
+ //{
+ // return do_try_join_until(get_milliseconds_until(wait_until));
+ //}
#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<chrono::system_clock, chrono::nanoseconds>& tp)
+ {
+ chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
+ return do_try_join_until(rel_time.count());
+ }
#endif
- public:
+
#else
+ private:
+ bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res);
+ inline bool do_try_join_until(struct timespec const &timeout);
+ public:
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_join(const system_time& abs_time)
{
- struct timespec const ts=detail::get_timespec(abs_time);
+ struct timespec const ts=detail::to_timespec(abs_time);
return do_try_join_until(ts);
}
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
- timespec ts;
- seconds s = duration_cast<seconds>(d);
- ts.tv_sec = static_cast<long>(s.count());
- ts.tv_nsec = static_cast<long>((d - s).count());
+ timespec ts = boost::detail::to_timespec(d);
return do_try_join_until(ts);
}
#endif
- private:
- bool do_try_join_until(struct timespec const &timeout);
- public:
#endif
+ public:
+#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
inline bool timed_join(TimeDuration const& rel_time)
{
return timed_join(get_system_time()+rel_time);
}
-
- void detach() BOOST_NOEXCEPT;
+#endif
+ void detach();
static unsigned hardware_concurrency() BOOST_NOEXCEPT;
+ static unsigned physical_concurrency() BOOST_NOEXCEPT;
#define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
typedef detail::thread_data_base::native_handle_type native_handle_type;
native_handle_type native_handle();
-#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+#if defined BOOST_THREAD_PROVIDES_THREAD_EQ
// Use thread::id when comparisions are needed
// backwards compatibility
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
#endif
+#if defined BOOST_THREAD_USES_DATETIME
static inline void yield() BOOST_NOEXCEPT
{
this_thread::yield();
@@ -423,10 +578,13 @@ namespace boost
{
this_thread::sleep(xt);
}
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// extensions
void interrupt();
bool interruption_requested() const BOOST_NOEXCEPT;
+#endif
};
inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT
@@ -434,7 +592,7 @@ namespace boost
return lhs.swap(rhs);
}
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
inline thread&& move(thread& t) BOOST_NOEXCEPT
{
return static_cast<thread&&>(t);
@@ -445,16 +603,24 @@ namespace boost
namespace this_thread
{
+#ifdef BOOST_THREAD_PLATFORM_PTHREAD
+ inline thread::id get_id() BOOST_NOEXCEPT;
+#else
thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT;
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
void BOOST_THREAD_DECL interruption_point();
bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
+#endif
+#if defined BOOST_THREAD_USES_DATETIME
inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
{
sleep(system_time(abs_time));
}
+#endif
}
class BOOST_SYMBOL_VISIBLE thread::id
@@ -490,12 +656,8 @@ namespace boost
public:
id() BOOST_NOEXCEPT:
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
-#if defined(BOOST_THREAD_PLATFORM_WIN32)
thread_data(0)
#else
- thread_data(0)
-#endif
-#else
thread_data()
#endif
{}
@@ -572,6 +734,61 @@ namespace boost
#endif
};
+#ifdef BOOST_THREAD_PLATFORM_PTHREAD
+ thread::id thread::get_id() const BOOST_NOEXCEPT
+ {
+ #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
+ return const_cast<thread*>(this)->native_handle();
+ #else
+ detail::thread_data_ptr const local_thread_info=(get_thread_info)();
+ return (local_thread_info? id(local_thread_info) : id());
+ #endif
+ }
+
+ namespace this_thread
+ {
+ inline thread::id get_id() BOOST_NOEXCEPT
+ {
+ #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
+ return pthread_self();
+ #else
+ boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
+ return (thread_info?thread::id(thread_info->shared_from_this()):thread::id());
+ #endif
+ }
+ }
+#endif
+ void thread::join() {
+ if (this_thread::get_id() == get_id())
+ boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
+
+ BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(),
+ thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")
+ );
+ }
+
+#ifdef BOOST_THREAD_PLATFORM_PTHREAD
+ bool thread::do_try_join_until(struct timespec const &timeout)
+#else
+ bool thread::do_try_join_until(uintmax_t timeout)
+#endif
+ {
+ if (this_thread::get_id() == get_id())
+ boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
+ bool res;
+ if (do_try_join_until_noexcept(timeout, res))
+ {
+ return res;
+ }
+ else
+ {
+ BOOST_THREAD_THROW_ELSE_RETURN(
+ (thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")),
+ false
+ );
+ }
+ }
+
#if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<class charT, class traits>
BOOST_SYMBOL_VISIBLE
@@ -582,7 +799,7 @@ namespace boost
}
#endif
-#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+#if defined BOOST_THREAD_PROVIDES_THREAD_EQ
inline bool thread::operator==(const thread& other) const
{
return get_id()==other.get_id();
@@ -620,6 +837,19 @@ namespace boost
};
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
+ struct shared_state_base;
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+ inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
+ {
+ detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
+ if(current_thread_data)
+ {
+ current_thread_data->make_ready_at_thread_exit(as);
+ }
+ }
+#else
+ void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
+#endif
}
namespace this_thread
diff --git a/boost/thread/detail/thread_group.hpp b/boost/thread/detail/thread_group.hpp
index f1ccdf84e2..69ce991e78 100644
--- a/boost/thread/detail/thread_group.hpp
+++ b/boost/thread/detail/thread_group.hpp
@@ -8,6 +8,7 @@
#include <list>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/mutex.hpp>
+#include <boost/thread/lock_guard.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -22,7 +23,7 @@ namespace boost
{
private:
thread_group(thread_group const&);
- thread_group& operator=(thread_group const&);
+ thread_group& operator=(thread_group const&);
public:
thread_group() {}
~thread_group()
@@ -35,6 +36,41 @@ namespace boost
}
}
+ bool is_this_thread_in()
+ {
+ thread::id id = this_thread::get_id();
+ boost::shared_lock<shared_mutex> guard(m);
+ for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
+ it!=end;
+ ++it)
+ {
+ if ((*it)->get_id() == id)
+ return true;
+ }
+ return false;
+ }
+
+ bool is_thread_in(thread* thrd)
+ {
+ if(thrd)
+ {
+ thread::id id = thrd->get_id();
+ boost::shared_lock<shared_mutex> guard(m);
+ for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
+ it!=end;
+ ++it)
+ {
+ if ((*it)->get_id() == id)
+ return true;
+ }
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
template<typename F>
thread* create_thread(F threadfunc)
{
@@ -43,16 +79,20 @@ namespace boost
threads.push_back(new_thread.get());
return new_thread.release();
}
-
+
void add_thread(thread* thrd)
{
if(thrd)
{
+ BOOST_THREAD_ASSERT_PRECONDITION( ! is_thread_in(thrd) ,
+ thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying to add a duplicated thread")
+ );
+
boost::lock_guard<shared_mutex> guard(m);
threads.push_back(thrd);
}
}
-
+
void remove_thread(thread* thrd)
{
boost::lock_guard<shared_mutex> guard(m);
@@ -62,23 +102,28 @@ namespace boost
threads.erase(it);
}
}
-
+
void join_all()
{
+ BOOST_THREAD_ASSERT_PRECONDITION( ! is_this_thread_in() ,
+ thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying joining itself")
+ );
boost::shared_lock<shared_mutex> guard(m);
-
+
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
+ if ((*it)->joinable())
(*it)->join();
}
}
-
+
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
void interrupt_all()
{
boost::shared_lock<shared_mutex> guard(m);
-
+
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
@@ -86,13 +131,14 @@ namespace boost
(*it)->interrupt();
}
}
-
+#endif
+
size_t size() const
{
boost::shared_lock<shared_mutex> guard(m);
return threads.size();
}
-
+
private:
std::list<thread*> threads;
mutable shared_mutex m;
diff --git a/boost/thread/detail/thread_interruption.hpp b/boost/thread/detail/thread_interruption.hpp
index f1a165c33e..5d7d10fecd 100644
--- a/boost/thread/detail/thread_interruption.hpp
+++ b/boost/thread/detail/thread_interruption.hpp
@@ -9,6 +9,8 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+
namespace boost
{
namespace this_thread
@@ -33,4 +35,5 @@ namespace boost
}
}
-#endif
+#endif // BOOST_THREAD_PROVIDES_INTERRUPTIONS
+#endif // header
diff --git a/boost/thread/detail/variadic_footer.hpp b/boost/thread/detail/variadic_footer.hpp
new file mode 100644
index 0000000000..9ae25a847c
--- /dev/null
+++ b/boost/thread/detail/variadic_footer.hpp
@@ -0,0 +1,10 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+
+
+#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+
+#endif
diff --git a/boost/thread/detail/variadic_header.hpp b/boost/thread/detail/variadic_header.hpp
new file mode 100644
index 0000000000..8015ae33cc
--- /dev/null
+++ b/boost/thread/detail/variadic_header.hpp
@@ -0,0 +1,19 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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>
+
+//#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+#include <boost/preprocessor/facilities/intercept.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+#ifndef BOOST_THREAD_MAX_ARGS
+#define BOOST_THREAD_MAX_ARGS 9
+#endif
+
+//#endif
+
diff --git a/boost/thread/detail/work.hpp b/boost/thread/detail/work.hpp
new file mode 100644
index 0000000000..1e10c837bb
--- /dev/null
+++ b/boost/thread/detail/work.hpp
@@ -0,0 +1,23 @@
+// (C) Copyright 2013 Vicente J. Botet Escriba
+//
+// 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)
+
+#ifndef BOOST_THREAD_DETAIL_WORK_HPP
+#define BOOST_THREAD_DETAIL_WORK_HPP
+
+
+#include <boost/thread/detail/nullary_function.hpp>
+
+namespace boost
+{
+ namespace thread_detail
+ {
+
+ typedef detail::nullary_function<void()> work;
+ }
+
+} // namespace boost
+
+#endif // BOOST_THREAD_DETAIL_MEMORY_HPP
diff --git a/boost/thread/exceptional_ptr.hpp b/boost/thread/exceptional_ptr.hpp
new file mode 100644
index 0000000000..49547923d9
--- /dev/null
+++ b/boost/thread/exceptional_ptr.hpp
@@ -0,0 +1,44 @@
+// 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)
+// (C) Copyright 2014 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_EXCEPTIONAL_PTR_HPP
+#define BOOST_THREAD_EXCEPTIONAL_PTR_HPP
+
+#include <boost/thread/detail/move.hpp>
+#include <boost/exception_ptr.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ struct exceptional_ptr {
+ exception_ptr ptr_;
+
+ exceptional_ptr() : ptr_() {}
+ explicit exceptional_ptr(exception_ptr ex) : ptr_(ex) {}
+ template <class E>
+ explicit exceptional_ptr(BOOST_FWD_REF(E) ex) : ptr_(boost::copy_exception(boost::forward<E>(ex))) {}
+ };
+
+ template <class E>
+ inline exceptional_ptr make_exceptional(BOOST_FWD_REF(E) ex) {
+ return exceptional_ptr(boost::forward<E>(ex));
+ }
+
+ inline exceptional_ptr make_exceptional(exception_ptr ex)
+ {
+ return exceptional_ptr(ex);
+ }
+
+ inline exceptional_ptr make_exceptional()
+ {
+ return exceptional_ptr();
+ }
+
+} // namespace boost
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/exceptions.hpp b/boost/thread/exceptions.hpp
index 08c28d3d17..d97465b754 100644
--- a/boost/thread/exceptions.hpp
+++ b/boost/thread/exceptions.hpp
@@ -28,8 +28,10 @@
namespace boost
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
class BOOST_SYMBOL_VISIBLE thread_interrupted
{};
+#endif
class BOOST_SYMBOL_VISIBLE thread_exception:
public system::system_error
@@ -122,7 +124,7 @@ namespace boost
typedef thread_exception base_type;
public:
thread_resource_error()
- : base_type(system::errc::resource_unavailable_try_again, "boost::thread_resource_error")
+ : base_type(static_cast<int>(system::errc::resource_unavailable_try_again), "boost::thread_resource_error")
{}
thread_resource_error( int ev )
@@ -150,7 +152,7 @@ namespace boost
typedef thread_exception base_type;
public:
unsupported_thread_option()
- : base_type(system::errc::invalid_argument, "boost::unsupported_thread_option")
+ : base_type(static_cast<int>(system::errc::invalid_argument), "boost::unsupported_thread_option")
{}
unsupported_thread_option( int ev )
@@ -174,7 +176,7 @@ namespace boost
typedef thread_exception base_type;
public:
invalid_thread_argument()
- : base_type(system::errc::invalid_argument, "boost::invalid_thread_argument")
+ : base_type(static_cast<int>(system::errc::invalid_argument), "boost::invalid_thread_argument")
{}
invalid_thread_argument( int ev )
@@ -198,7 +200,7 @@ namespace boost
typedef thread_exception base_type;
public:
thread_permission_error()
- : base_type(system::errc::permission_denied, "boost::thread_permission_error")
+ : base_type(static_cast<int>(system::errc::permission_denied), "boost::thread_permission_error")
{}
thread_permission_error( int ev )
diff --git a/boost/thread/executor.hpp b/boost/thread/executor.hpp
new file mode 100644
index 0000000000..c2b85a0eab
--- /dev/null
+++ b/boost/thread/executor.hpp
@@ -0,0 +1,15 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/09 Vicente J. Botet Escriba
+// Adapt to boost from CCIA C++11 implementation
+
+#ifndef BOOST_THREAD_EXECUTOR_HPP
+#define BOOST_THREAD_EXECUTOR_HPP
+
+#include <boost/thread/executors/executor.hpp>
+#include <boost/thread/executors/executor_adaptor.hpp>
+
+#endif
diff --git a/boost/thread/executors/basic_thread_pool.hpp b/boost/thread/executors/basic_thread_pool.hpp
new file mode 100644
index 0000000000..11283ddf42
--- /dev/null
+++ b/boost/thread/executors/basic_thread_pool.hpp
@@ -0,0 +1,317 @@
+// Copyright (C) 2013-2014 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/09 Vicente J. Botet Escriba
+// Adapt to boost from CCIA C++11 implementation
+// first implementation of a simple pool thread using a vector of threads and a sync_queue.
+
+#ifndef BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP
+#define BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/scoped_thread.hpp>
+#include <boost/thread/sync_queue.hpp>
+#include <boost/thread/executors/work.hpp>
+#include <boost/thread/csbl/vector.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+namespace executors
+{
+ class basic_thread_pool
+ {
+ public:
+ /// type-erasure to store the works to do
+ typedef executors::work work;
+ private:
+ /// the kind of stored threads are scoped threads to ensure that the threads are joined.
+ /// A move aware vector type
+ typedef scoped_thread<> thread_t;
+ typedef csbl::vector<thread_t> thread_vector;
+
+ /// the thread safe work queue
+ sync_queue<work > work_queue;
+ /// A move aware vector
+ thread_vector threads;
+
+ public:
+ /**
+ * Effects: try to execute one task.
+ * Returns: whether a task has been executed.
+ * Throws: whatever the current task constructor throws or the task() throws.
+ */
+ bool try_executing_one()
+ {
+ work task;
+ try
+ {
+ if (work_queue.try_pull_front(task) == queue_op_status::success)
+ {
+ task();
+ return true;
+ }
+ return false;
+ }
+ catch (std::exception& )
+ {
+ return false;
+ }
+ catch (...)
+ {
+ return false;
+ }
+ }
+ /**
+ * 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();
+ }
+ }
+ private:
+
+ /**
+ * The main loop of the worker threads
+ */
+ void worker_thread()
+ {
+ try
+ {
+ for(;;)
+ {
+ work task;
+ queue_op_status st = work_queue.wait_pull_front(task);
+ if (st == queue_op_status::closed) return;
+ task();
+ }
+ }
+ catch (std::exception& )
+ {
+ return;
+ }
+ catch (...)
+ {
+ return;
+ }
+ }
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <class AtThreadEntry>
+ void worker_thread1(AtThreadEntry& at_thread_entry)
+ {
+ at_thread_entry(*this);
+ worker_thread();
+ }
+#endif
+ void worker_thread2(void(*at_thread_entry)(basic_thread_pool&))
+ {
+ at_thread_entry(*this);
+ worker_thread();
+ }
+ template <class AtThreadEntry>
+ void worker_thread3(BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry)
+ {
+ at_thread_entry(*this);
+ worker_thread();
+ }
+ static void do_nothing_at_thread_entry(basic_thread_pool&) {}
+
+ public:
+ /// basic_thread_pool is not copyable.
+ BOOST_THREAD_NO_COPYABLE(basic_thread_pool)
+
+ /**
+ * \b Effects: creates a thread pool that runs closures on \c thread_count threads.
+ *
+ * \b Throws: Whatever exception is thrown while initializing the needed resources.
+ */
+ basic_thread_pool(unsigned const thread_count = thread::hardware_concurrency())
+ {
+ try
+ {
+ threads.reserve(thread_count);
+ for (unsigned i = 0; i < thread_count; ++i)
+ {
+#if 1
+ thread th (&basic_thread_pool::worker_thread, this);
+ threads.push_back(thread_t(boost::move(th)));
+#else
+ threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
+#endif
+ }
+ }
+ catch (...)
+ {
+ close();
+ throw;
+ }
+ }
+ /**
+ * \b Effects: creates a thread pool that runs closures on \c thread_count threads
+ * and executes the at_thread_entry function at the entry of each created thread. .
+ *
+ * \b Throws: Whatever exception is thrown while initializing the needed resources.
+ */
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <class AtThreadEntry>
+ basic_thread_pool( unsigned const thread_count, AtThreadEntry& at_thread_entry)
+ {
+ try
+ {
+ threads.reserve(thread_count);
+ for (unsigned i = 0; i < thread_count; ++i)
+ {
+ thread th (&basic_thread_pool::worker_thread1<AtThreadEntry>, this, at_thread_entry);
+ threads.push_back(thread_t(boost::move(th)));
+ //threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
+ }
+ }
+ catch (...)
+ {
+ close();
+ throw;
+ }
+ }
+#endif
+ basic_thread_pool( unsigned const thread_count, void(*at_thread_entry)(basic_thread_pool&))
+ {
+ try
+ {
+ threads.reserve(thread_count);
+ for (unsigned i = 0; i < thread_count; ++i)
+ {
+ thread th (&basic_thread_pool::worker_thread2, this, at_thread_entry);
+ threads.push_back(thread_t(boost::move(th)));
+ //threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
+ }
+ }
+ catch (...)
+ {
+ close();
+ throw;
+ }
+ }
+ template <class AtThreadEntry>
+ basic_thread_pool( unsigned const thread_count, BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry)
+ {
+ try
+ {
+ threads.reserve(thread_count);
+ for (unsigned i = 0; i < thread_count; ++i)
+ {
+ thread th (&basic_thread_pool::worker_thread3<AtThreadEntry>, this, boost::forward<AtThreadEntry>(at_thread_entry));
+ threads.push_back(thread_t(boost::move(th)));
+ //threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile
+ }
+ }
+ catch (...)
+ {
+ close();
+ throw;
+ }
+ }
+ /**
+ * \b Effects: Destroys the thread pool.
+ *
+ * \b Synchronization: The completion of all the closures happen before the completion of the \c basic_thread_pool destructor.
+ */
+ ~basic_thread_pool()
+ {
+ // signal to all the worker threads that there will be no more submissions.
+ close();
+ // joins all the threads as the threads were scoped_threads
+ }
+
+ /**
+ * \b Effects: join all the threads.
+ */
+ void join()
+ {
+ for (unsigned i = 0; i < threads.size(); ++i)
+ {
+ threads[i].join();
+ }
+ }
+
+ /**
+ * \b Effects: close the \c basic_thread_pool for submissions.
+ * The worker threads will work until there is no more closures to run.
+ */
+ void close()
+ {
+ work_queue.close();
+ }
+
+ /**
+ * \b Returns: whether the pool is closed for submissions.
+ */
+ bool closed()
+ {
+ return work_queue.closed();
+ }
+
+ /**
+ * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
+ *
+ * \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the \c basic_thread_pool will call \c std::terminate, as is the case with threads.
+ *
+ * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \b Throws: \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename Closure>
+ void submit(Closure & closure)
+ {
+ work_queue.push_back(work(closure));
+ }
+#endif
+ void submit(void (*closure)())
+ {
+ work_queue.push_back(work(closure));
+ }
+
+ template <typename Closure>
+ void submit(BOOST_THREAD_RV_REF(Closure) closure)
+ {
+ work_queue.push_back(work(boost::forward<Closure>(closure)));
+ }
+
+ /**
+ * \b Requires: This must be called from an scheduled task.
+ *
+ * \b Effects: reschedule functions until pred()
+ */
+ template <typename Pred>
+ bool reschedule_until(Pred const& pred)
+ {
+ do {
+ if ( ! try_executing_one())
+ {
+ return false;
+ }
+ } while (! pred());
+ return true;
+ }
+
+ };
+}
+using executors::basic_thread_pool;
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/executors/executor.hpp b/boost/thread/executors/executor.hpp
new file mode 100644
index 0000000000..1075bce733
--- /dev/null
+++ b/boost/thread/executors/executor.hpp
@@ -0,0 +1,147 @@
+// Copyright (C) 2013,2014 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/09 Vicente J. Botet Escriba
+// Adapt to boost from CCIA C++11 implementation
+
+#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
+#define BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/executors/work.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ namespace executors
+ {
+ class executor
+ {
+ public:
+ /// type-erasure to store the works to do
+ typedef executors::work work;
+
+ /// executor is not copyable.
+ BOOST_THREAD_NO_COPYABLE(executor)
+ executor() {}
+
+ /**
+ * \par Effects
+ * Destroys the executor.
+ *
+ * \par Synchronization
+ * The completion of all the closures happen before the completion of the executor destructor.
+ */
+ virtual ~executor() {};
+
+ /**
+ * \par Effects
+ * Close the \c executor for submissions.
+ * The worker threads will work until there is no more closures to run.
+ */
+ virtual void close() = 0;
+
+ /**
+ * \par Returns
+ * Whether the pool is closed for submissions.
+ */
+ virtual bool closed() = 0;
+
+ /**
+ * \par Effects
+ * The specified closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
+ *
+ * \par Synchronization
+ * Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \par Throws
+ * \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+ virtual void submit(BOOST_THREAD_RV_REF(work) closure) = 0;
+// virtual void submit(work& closure) = 0;
+
+ /**
+ * \par Requires
+ * \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
+ *
+ * \par Effects
+ * The specified closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
+ *
+ * \par Synchronization
+ * Completion of closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \par Throws
+ * \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename Closure>
+ void submit(Closure & closure)
+ {
+ work w ((closure));
+ submit(boost::move(w));
+ }
+#endif
+ void submit(void (*closure)())
+ {
+ work w ((closure));
+ submit(boost::move(w));
+ }
+
+ template <typename Closure>
+ void submit(BOOST_THREAD_RV_REF(Closure) closure)
+ {
+ work w = boost::move(closure);
+ submit(boost::move(w));
+ }
+
+ /**
+ * \par Effects
+ * Try to execute one task.
+ *
+ * \par Returns
+ * Whether a task has been executed.
+ *
+ * \par Throws
+ * Whatever the current task constructor throws or the task() throws.
+ */
+ virtual bool try_executing_one() = 0;
+
+ /**
+ * \par Requires
+ * This must be called from an scheduled task.
+ *
+ * \par Effects
+ * Reschedule functions until pred()
+ */
+ template <typename Pred>
+ bool reschedule_until(Pred const& pred)
+ {
+ do {
+ //schedule_one_or_yield();
+ if ( ! try_executing_one())
+ {
+ return false;
+ }
+ } while (! pred());
+ return true;
+ }
+ };
+
+ }
+ using executors::executor;
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/executors/executor_adaptor.hpp b/boost/thread/executors/executor_adaptor.hpp
new file mode 100644
index 0000000000..ebe4e3476c
--- /dev/null
+++ b/boost/thread/executors/executor_adaptor.hpp
@@ -0,0 +1,137 @@
+// Copyright (C) 2013,2014 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/09 Vicente J. Botet Escriba
+// Adapt to boost from CCIA C++11 implementation
+
+#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
+#define BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#include <boost/thread/executors/executor.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+namespace executors
+{
+ /**
+ * Polymorphic adaptor of a model of Executor to an executor.
+ */
+ template <typename Executor>
+ class executor_adaptor : public executor
+ {
+ Executor ex;
+ public:
+ /// type-erasure to store the works to do
+ typedef executor::work work;
+
+ /// executor is not copyable.
+ BOOST_THREAD_NO_COPYABLE(executor_adaptor)
+
+ /**
+ * executor_adaptor constructor
+ */
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <typename ...Args>
+ executor_adaptor(BOOST_THREAD_RV_REF(Args) ... args) : ex(boost::forward<Args>(args)...) {}
+#else
+ /**
+ * executor_adaptor constructor
+ */
+ executor_adaptor() : ex() {}
+
+ template <typename A1>
+ executor_adaptor(
+ BOOST_THREAD_FWD_REF(A1) a1
+ ) :
+ ex(
+ boost::forward<A1>(a1)
+ ) {}
+ template <typename A1, typename A2>
+ executor_adaptor(
+ BOOST_THREAD_FWD_REF(A1) a1,
+ BOOST_THREAD_FWD_REF(A2) a2
+ ) :
+ ex(
+ boost::forward<A1>(a1),
+ boost::forward<A2>(a2)
+ ) {}
+ template <typename A1, typename A2, typename A3>
+ executor_adaptor(
+ BOOST_THREAD_FWD_REF(A1) a1,
+ BOOST_THREAD_FWD_REF(A2) a2,
+ BOOST_THREAD_FWD_REF(A3) a3
+ ) :
+ ex(
+ boost::forward<A1>(a1),
+ boost::forward<A2>(a2),
+ boost::forward<A3>(a3)
+ ) {}
+#endif
+ Executor& underlying_executor() { return ex; }
+
+ /**
+ * \b Effects: close the \c executor for submissions.
+ * The worker threads will work until there is no more closures to run.
+ */
+ void close() { ex.close(); }
+
+ /**
+ * \b Returns: whether the pool is closed for submissions.
+ */
+ bool closed() { return ex.closed(); }
+
+ /**
+ * \b Effects: The specified closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
+ *
+ * \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \b Throws: \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+ void submit(BOOST_THREAD_RV_REF(work) closure) {
+ return ex.submit(boost::move(closure));
+ }
+// void submit(work & closure) {
+// return ex.submit(closure);
+// }
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename Closure>
+ void submit(Closure & closure)
+ {
+ submit(work(closure));
+ }
+#endif
+ void submit(void (*closure)())
+ {
+ submit(work(closure));
+ }
+
+ template <typename Closure>
+ void submit(BOOST_THREAD_RV_REF(Closure) closure)
+ {
+ submit(work(boost::forward<Closure>(closure)));
+ }
+
+ /**
+ * Effects: try to execute one task.
+ * Returns: whether a task has been executed.
+ * Throws: whatever the current task constructor throws or the task() throws.
+ */
+ bool try_executing_one() { return ex.try_executing_one(); }
+
+ };
+}
+using executors::executor_adaptor;
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/executors/generic_executor_ref.hpp b/boost/thread/executors/generic_executor_ref.hpp
new file mode 100644
index 0000000000..57609c91f0
--- /dev/null
+++ b/boost/thread/executors/generic_executor_ref.hpp
@@ -0,0 +1,211 @@
+// Copyright (C) 2014 Vicente J. Botet Escriba
+//
+// 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)
+//
+
+#ifndef BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
+#define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/executors/executor.hpp>
+
+#include <boost/shared_ptr.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ namespace executors
+ {
+
+ template <class Executor>
+ class executor_ref : public executor
+ {
+ Executor& ex;
+ public:
+ /// type-erasure to store the works to do
+ typedef executors::work work;
+
+ /// executor is not copyable.
+ BOOST_THREAD_NO_COPYABLE(executor_ref)
+ executor_ref(Executor& ex) : ex(ex) {}
+
+ /**
+ * \par Effects
+ * Destroys the executor.
+ *
+ * \par Synchronization
+ * The completion of all the closures happen before the completion of the executor destructor.
+ */
+ ~executor_ref() {};
+
+ /**
+ * \par Effects
+ * Close the \c executor for submissions.
+ * The worker threads will work until there is no more closures to run.
+ */
+ void close() { ex.close(); }
+
+ /**
+ * \par Returns
+ * Whether the pool is closed for submissions.
+ */
+ bool closed() { return ex.closed(); }
+
+ /**
+ * \par Effects
+ * The specified closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
+ *
+ * \par Synchronization
+ * Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \par Throws
+ * \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+ void submit(BOOST_THREAD_RV_REF(work) closure) {
+ ex.submit(boost::move(closure));
+ }
+// void submit(work& closure) {
+// ex.submit(closure);
+// }
+
+
+ /**
+ * \par Effects
+ * Try to execute one task.
+ *
+ * \par Returns
+ * Whether a task has been executed.
+ *
+ * \par Throws
+ * Whatever the current task constructor throws or the task() throws.
+ */
+ bool try_executing_one() { return ex.try_executing_one(); }
+
+ };
+
+ class generic_executor_ref
+ {
+ shared_ptr<executor> ex;
+ public:
+ /// type-erasure to store the works to do
+ typedef executors::work work;
+
+ template<typename Executor>
+ generic_executor_ref(Executor& ex)
+ //: ex(make_shared<executor_ref<Executor> >(ex)) // todo check why this doesn't works with C++03
+ : ex( new executor_ref<Executor>(ex) )
+ {
+ }
+
+ //generic_executor_ref(generic_executor_ref const& other) noexcept {}
+ //generic_executor_ref& operator=(generic_executor_ref const& other) noexcept {}
+
+
+ /**
+ * \par Effects
+ * Close the \c executor for submissions.
+ * The worker threads will work until there is no more closures to run.
+ */
+ void close() { ex->close(); }
+
+ /**
+ * \par Returns
+ * Whether the pool is closed for submissions.
+ */
+ bool closed() { return ex->closed(); }
+
+ void submit(BOOST_THREAD_RV_REF(work) closure)
+ {
+ ex->submit(boost::forward<work>(closure));
+ }
+
+ /**
+ * \par Requires
+ * \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
+ *
+ * \par Effects
+ * The specified closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
+ *
+ * \par Synchronization
+ * Completion of closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \par Throws
+ * \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename Closure>
+ void submit(Closure & closure)
+ {
+ work w ((closure));
+ submit(boost::move(w));
+ }
+#endif
+ void submit(void (*closure)())
+ {
+ work w ((closure));
+ submit(boost::move(w));
+ }
+
+ template <typename Closure>
+ void submit(BOOST_THREAD_RV_REF(Closure) closure)
+ {
+ work w = boost::move(closure);
+ submit(boost::move(w));
+ }
+
+// size_t num_pending_closures() const
+// {
+// return ex->num_pending_closures();
+// }
+
+ /**
+ * \par Effects
+ * Try to execute one task.
+ *
+ * \par Returns
+ * Whether a task has been executed.
+ *
+ * \par Throws
+ * Whatever the current task constructor throws or the task() throws.
+ */
+ bool try_executing_one() { return ex->try_executing_one(); }
+
+ /**
+ * \par Requires
+ * This must be called from an scheduled task.
+ *
+ * \par Effects
+ * reschedule functions until pred()
+ */
+ template <typename Pred>
+ bool reschedule_until(Pred const& pred)
+ {
+ do {
+ //schedule_one_or_yield();
+ if ( ! try_executing_one())
+ {
+ return false;
+ }
+ } while (! pred());
+ return true;
+ }
+
+ };
+ }
+ using executors::executor_ref;
+ using executors::generic_executor_ref;
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/executors/inline_executor.hpp b/boost/thread/executors/inline_executor.hpp
new file mode 100644
index 0000000000..bc6bd9fe7e
--- /dev/null
+++ b/boost/thread/executors/inline_executor.hpp
@@ -0,0 +1,131 @@
+// Copyright (C) 2014 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/11 Vicente J. Botet Escriba
+// first implementation of a simple serial scheduler.
+
+#ifndef BOOST_THREAD_INLINE_EXECUTOR_HPP
+#define BOOST_THREAD_INLINE_EXECUTOR_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/executors/work.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+namespace executors
+{
+ class inline_executor
+ {
+ public:
+ /// type-erasure to store the works to do
+ typedef executors::work work;
+ bool closed_;
+ /**
+ * Effects: try to execute one task.
+ * Returns: whether a task has been executed.
+ * Throws: whatever the current task constructor throws or the task() throws.
+ */
+ bool try_executing_one()
+ {
+ return false;
+ }
+
+ public:
+ /// inline_executor is not copyable.
+ BOOST_THREAD_NO_COPYABLE(inline_executor)
+
+ /**
+ * \b Effects: creates a inline executor that runs closures immediately.
+ *
+ * \b Throws: Nothing.
+ */
+ inline_executor()
+ : closed_(false)
+ {
+ }
+ /**
+ * \b Effects: Destroys the inline executor.
+ *
+ * \b Synchronization: The completion of all the closures happen before the completion of the \c inline_executor destructor.
+ */
+ ~inline_executor()
+ {
+ // signal to all the worker thread that there will be no more submissions.
+ close();
+ }
+
+ /**
+ * \b Effects: close the \c inline_executor for submissions.
+ * The loop will work until there is no more closures to run.
+ */
+ void close()
+ {
+ closed_ = true;
+ }
+
+ /**
+ * \b Returns: whether the pool is closed for submissions.
+ */
+ bool closed()
+ {
+ return closed_;
+ }
+
+ /**
+ * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
+ *
+ * \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the \c inline_executor will call \c std::terminate, as is the case with threads.
+ *
+ * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \b Throws: \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename Closure>
+ void submit(Closure & closure)
+ {
+ if (closed()) return;
+ closure();
+ }
+#endif
+ void submit(void (*closure)())
+ {
+ if (closed()) return;
+ closure();
+ }
+
+ template <typename Closure>
+ void submit(BOOST_THREAD_FWD_REF(Closure) closure)
+ {
+ if (closed()) return;
+ closure();
+ }
+
+ /**
+ * \b Requires: This must be called from an scheduled task.
+ *
+ * \b Effects: reschedule functions until pred()
+ */
+ template <typename Pred>
+ bool reschedule_until(Pred const& )
+ {
+ return false;
+ }
+
+ };
+}
+using executors::inline_executor;
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/executors/loop_executor.hpp b/boost/thread/executors/loop_executor.hpp
new file mode 100644
index 0000000000..c2798b4461
--- /dev/null
+++ b/boost/thread/executors/loop_executor.hpp
@@ -0,0 +1,204 @@
+// Copyright (C) 2013,2014 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/11 Vicente J. Botet Escriba
+// first implementation of a simple user scheduler.
+// 2013/11 Vicente J. Botet Escriba
+// rename loop_executor.
+
+#ifndef BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
+#define BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/sync_queue.hpp>
+#include <boost/thread/executors/work.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+namespace executors
+{
+
+ class loop_executor
+ {
+ public:
+ /// type-erasure to store the works to do
+ typedef executors::work work;
+ private:
+ /// the thread safe work queue
+ sync_queue<work > work_queue;
+
+ public:
+ /**
+ * Effects: try to execute one task.
+ * Returns: whether a task has been executed.
+ * Throws: whatever the current task constructor throws or the task() throws.
+ */
+ bool try_executing_one()
+ {
+ work task;
+ try
+ {
+ if (work_queue.try_pull_front(task) == queue_op_status::success)
+ {
+ task();
+ return true;
+ }
+ return false;
+ }
+ catch (std::exception& )
+ {
+ return false;
+ }
+ catch (...)
+ {
+ 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();
+ }
+ }
+
+
+ /**
+ * The main loop of the worker thread
+ */
+ void worker_thread()
+ {
+ while (!closed())
+ {
+ schedule_one_or_yield();
+ }
+ while (try_executing_one())
+ {
+ }
+ }
+
+ public:
+ /// loop_executor is not copyable.
+ BOOST_THREAD_NO_COPYABLE(loop_executor)
+
+ /**
+ * \b Effects: creates a thread pool that runs closures using one of its closure-executing methods.
+ *
+ * \b Throws: Whatever exception is thrown while initializing the needed resources.
+ */
+ loop_executor()
+ {
+ }
+ /**
+ * \b Effects: Destroys the thread pool.
+ *
+ * \b Synchronization: The completion of all the closures happen before the completion of the \c loop_executor destructor.
+ */
+ ~loop_executor()
+ {
+ // signal to all the worker thread that there will be no more submissions.
+ close();
+ }
+
+ /**
+ * loop
+ */
+ void loop() { worker_thread(); }
+ /**
+ * \b Effects: close the \c loop_executor for submissions.
+ * The loop will work until there is no more closures to run.
+ */
+ void close()
+ {
+ work_queue.close();
+ }
+
+ /**
+ * \b Returns: whether the pool is closed for submissions.
+ */
+ bool closed()
+ {
+ return work_queue.closed();
+ }
+
+ /**
+ * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
+ *
+ * \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the \c loop_executor will call \c std::terminate, as is the case with threads.
+ *
+ * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \b Throws: \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename Closure>
+ void submit(Closure & closure)
+ {
+ work_queue.push_back(work(closure));
+ }
+#endif
+ void submit(void (*closure)())
+ {
+ work_queue.push_back(work(closure));
+ }
+
+ template <typename Closure>
+ void submit(BOOST_THREAD_RV_REF(Closure) closure)
+ {
+ work_queue.push_back(work(boost::forward<Closure>(closure)));
+ }
+
+ /**
+ * \b Requires: This must be called from an scheduled task.
+ *
+ * \b Effects: reschedule functions until pred()
+ */
+ template <typename Pred>
+ bool reschedule_until(Pred const& pred)
+ {
+ do {
+ if ( ! try_executing_one())
+ {
+ return false;
+ }
+ } while (! pred());
+ return true;
+ }
+
+ /**
+ * run queued closures
+ */
+ void run_queued_closures()
+ {
+ sync_queue<work>::underlying_queue_type q = work_queue.underlying_queue();
+ while (! q.empty())
+ {
+ work& task = q.front();
+ task();
+ q.pop_front();
+ }
+ }
+
+ };
+}
+using executors::loop_executor;
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/executors/serial_executor.hpp b/boost/thread/executors/serial_executor.hpp
new file mode 100644
index 0000000000..dae1014b47
--- /dev/null
+++ b/boost/thread/executors/serial_executor.hpp
@@ -0,0 +1,214 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/11 Vicente J. Botet Escriba
+// first implementation of a simple serial scheduler.
+
+#ifndef BOOST_THREAD_SERIAL_EXECUTOR_HPP
+#define BOOST_THREAD_SERIAL_EXECUTOR_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/sync_queue.hpp>
+#include <boost/thread/executors/work.hpp>
+#include <boost/thread/executors/generic_executor_ref.hpp>
+#include <boost/thread/future.hpp>
+#include <boost/thread/scoped_thread.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+namespace executors
+{
+ class serial_executor
+ {
+ public:
+ /// type-erasure to store the works to do
+ typedef executors::work work;
+ private:
+ typedef scoped_thread<> thread_t;
+
+ /// the thread safe work queue
+ sync_queue<work > work_queue;
+ generic_executor_ref ex;
+ thread_t thr;
+
+ struct try_executing_one_task {
+ work& task;
+ boost::promise<void> &p;
+ try_executing_one_task(work& task, boost::promise<void> &p)
+ : task(task), p(p) {}
+ void operator()() {
+ task(); // if task() throws promise is not set but as the the program terminates and should terminate there is no need to use try-catch here.
+ p.set_value();
+ }
+ };
+ public:
+ /**
+ * \par Returns
+ * The underlying executor wrapped on a generic executor reference.
+ */
+ generic_executor_ref underlying_executor() BOOST_NOEXCEPT { return ex; }
+
+ /**
+ * Effects: try to execute one task.
+ * Returns: whether a task has been executed.
+ * Throws: whatever the current task constructor throws or the task() throws.
+ */
+ bool try_executing_one()
+ {
+ work task;
+ try
+ {
+ if (work_queue.try_pull_front(task) == queue_op_status::success)
+ {
+ boost::promise<void> p;
+ try_executing_one_task tmp(task,p);
+ ex.submit(tmp);
+// ex.submit([&task, &p]()
+// {
+// task(); // if task() throws promise is not set but as the the program terminates and should terminate there is no need to use try-catch here.
+// p.set_value();
+// });
+ p.get_future().wait();
+ return true;
+ }
+ return false;
+ }
+ catch (std::exception& )
+ {
+ return false;
+ }
+ catch (...)
+ {
+ 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();
+ }
+ }
+
+ /**
+ * The main loop of the worker thread
+ */
+ void worker_thread()
+ {
+ while (!closed())
+ {
+ schedule_one_or_yield();
+ }
+ while (try_executing_one())
+ {
+ }
+ }
+
+ public:
+ /// serial_executor is not copyable.
+ BOOST_THREAD_NO_COPYABLE(serial_executor)
+
+ /**
+ * \b Effects: creates a thread pool that runs closures using one of its closure-executing methods.
+ *
+ * \b Throws: Whatever exception is thrown while initializing the needed resources.
+ */
+ template <class Executor>
+ serial_executor(Executor& ex)
+ : ex(ex), thr(&serial_executor::worker_thread, this)
+ {
+ }
+ /**
+ * \b Effects: Destroys the thread pool.
+ *
+ * \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor destructor.
+ */
+ ~serial_executor()
+ {
+ // signal to all the worker thread that there will be no more submissions.
+ close();
+ }
+
+ /**
+ * \b Effects: close the \c serial_executor for submissions.
+ * The loop will work until there is no more closures to run.
+ */
+ void close()
+ {
+ work_queue.close();
+ }
+
+ /**
+ * \b Returns: whether the pool is closed for submissions.
+ */
+ bool closed()
+ {
+ return work_queue.closed();
+ }
+
+ /**
+ * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
+ *
+ * \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the \c serial_executor will call \c std::terminate, as is the case with threads.
+ *
+ * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \b Throws: \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename Closure>
+ void submit(Closure & closure)
+ {
+ work_queue.push_back(work(closure));
+ }
+#endif
+ void submit(void (*closure)())
+ {
+ work_queue.push_back(work(closure));
+ }
+
+ template <typename Closure>
+ void submit(BOOST_THREAD_RV_REF(Closure) closure)
+ {
+ work_queue.push_back(work(boost::forward<Closure>(closure)));
+ }
+
+ /**
+ * \b Requires: This must be called from an scheduled task.
+ *
+ * \b Effects: reschedule functions until pred()
+ */
+ template <typename Pred>
+ bool reschedule_until(Pred const& pred)
+ {
+ do {
+ if ( ! try_executing_one())
+ {
+ return false;
+ }
+ } while (! pred());
+ return true;
+ }
+
+ };
+}
+using executors::serial_executor;
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/executors/thread_executor.hpp b/boost/thread/executors/thread_executor.hpp
new file mode 100644
index 0000000000..9fc3362fde
--- /dev/null
+++ b/boost/thread/executors/thread_executor.hpp
@@ -0,0 +1,136 @@
+// Copyright (C) 2014 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2014/01 Vicente J. Botet Escriba
+// first implementation of a thread_executor.
+
+#ifndef BOOST_THREAD_THREAD_EXECUTOR_HPP
+#define BOOST_THREAD_THREAD_EXECUTOR_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/executors/work.hpp>
+#include <boost/thread/executors/executor.hpp>
+#include <boost/thread/thread_only.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+namespace executors
+{
+ class thread_executor
+ {
+ public:
+ /// type-erasure to store the works to do
+ typedef executors::work work;
+ bool closed_;
+ /**
+ * Effects: try to execute one task.
+ * Returns: whether a task has been executed.
+ * Throws: whatever the current task constructor throws or the task() throws.
+ */
+ bool try_executing_one()
+ {
+ return false;
+ }
+
+ public:
+ /// thread_executor is not copyable.
+ BOOST_THREAD_NO_COPYABLE(thread_executor)
+
+ /**
+ * \b Effects: creates a inline executor that runs closures immediately.
+ *
+ * \b Throws: Nothing.
+ */
+ thread_executor()
+ : closed_(false)
+ {
+ }
+ /**
+ * \b Effects: Destroys the inline executor.
+ *
+ * \b Synchronization: The completion of all the closures happen before the completion of the \c thread_executor destructor.
+ */
+ ~thread_executor()
+ {
+ // signal to all the worker thread that there will be no more submissions.
+ close();
+ }
+
+ /**
+ * \b Effects: close the \c thread_executor for submissions.
+ * The loop will work until there is no more closures to run.
+ */
+ void close()
+ {
+ closed_ = true;
+ }
+
+ /**
+ * \b Returns: whether the pool is closed for submissions.
+ */
+ bool closed()
+ {
+ return closed_;
+ }
+
+ /**
+ * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
+ *
+ * \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the \c thread_executor will call \c std::terminate, as is the case with threads.
+ *
+ * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \b Throws: \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename Closure>
+ void submit(Closure & closure)
+ {
+ if (closed()) return;
+ thread th(closure);
+ th.detach();
+ }
+#endif
+ void submit(void (*closure)())
+ {
+ if (closed()) return;
+ thread th(closure);
+ th.detach();
+ }
+
+ template <typename Closure>
+ void submit(BOOST_THREAD_FWD_REF(Closure) closure)
+ {
+ if (closed()) return;
+ thread th(boost::forward<Closure>(closure));
+ th.detach();
+ }
+
+ /**
+ * \b Requires: This must be called from an scheduled task.
+ *
+ * \b Effects: reschedule functions until pred()
+ */
+ template <typename Pred>
+ bool reschedule_until(Pred const&)
+ {
+ return false;
+ }
+
+ };
+}
+using executors::thread_executor;
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/executors/work.hpp b/boost/thread/executors/work.hpp
new file mode 100644
index 0000000000..df1512cd95
--- /dev/null
+++ b/boost/thread/executors/work.hpp
@@ -0,0 +1,43 @@
+// (C) Copyright 2013,2014 Vicente J. Botet Escriba
+//
+// 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)
+
+#ifndef BOOST_THREAD_EXECUTORS_WORK_HPP
+#define BOOST_THREAD_EXECUTORS_WORK_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#if ! defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE \
+ && ! defined BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
+#define BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
+//#define BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
+#endif
+
+#if defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
+
+#include <boost/thread/detail/nullary_function.hpp>
+
+namespace boost
+{
+ namespace executors
+ {
+ typedef detail::nullary_function<void()> work;
+ }
+} // namespace boost
+
+#else
+#include <boost/thread/csbl/functional.hpp>
+
+namespace boost
+{
+ namespace executors
+ {
+ typedef csbl::function<void()> work;
+ }
+} // namespace boost
+
+#endif
+
+#endif // BOOST_THREAD_EXECUTORS_WORK_HPP
diff --git a/boost/thread/externally_locked.hpp b/boost/thread/externally_locked.hpp
new file mode 100644
index 0000000000..0d4baaa512
--- /dev/null
+++ b/boost/thread/externally_locked.hpp
@@ -0,0 +1,351 @@
+// (C) Copyright 2012 Vicente J. Botet Escriba
+// 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)
+
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_HPP
+#define BOOST_THREAD_EXTERNALLY_LOCKED_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#include <boost/thread/exceptions.hpp>
+#include <boost/thread/lock_concepts.hpp>
+#include <boost/thread/lock_traits.hpp>
+#include <boost/thread/lockable_concepts.hpp>
+#include <boost/thread/strict_lock.hpp>
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/core/swap.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ /**
+ * externally_locked cloaks an object of type T, and actually provides full
+ * access to that object through the get and set member functions, provided you
+ * pass a reference to a strict lock object
+ */
+
+ //[externally_locked
+ template <typename T, typename MutexType = boost::mutex>
+ class externally_locked;
+ template <typename T, typename MutexType>
+ class externally_locked
+ {
+ //BOOST_CONCEPT_ASSERT(( CopyConstructible<T> ));
+ BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> ));
+
+ public:
+ typedef MutexType mutex_type;
+
+ BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked )
+ /**
+ * Requires: T is a model of CopyConstructible.
+ * Effects: Constructs an externally locked object copying the cloaked type.
+ */
+ externally_locked(mutex_type& mtx, const T& obj) :
+ obj_(obj), mtx_(&mtx)
+ {
+ }
+
+ /**
+ * Requires: T is a model of Movable.
+ * Effects: Constructs an externally locked object by moving the cloaked type.
+ */
+ externally_locked(mutex_type& mtx, BOOST_THREAD_RV_REF(T) obj) :
+ obj_(move(obj)), mtx_(&mtx)
+ {
+ }
+
+ /**
+ * Requires: T is a model of DefaultConstructible.
+ * Effects: Constructs an externally locked object initializing the cloaked type with the default constructor.
+ */
+ externally_locked(mutex_type& mtx) // BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T()))
+ : obj_(), mtx_(&mtx)
+ {
+ }
+
+ /**
+ * Copy constructor
+ */
+ externally_locked(externally_locked const& rhs) //BOOST_NOEXCEPT
+ : obj_(rhs.obj_), mtx_(rhs.mtx_)
+ {
+ }
+ /**
+ * Move constructor
+ */
+ externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) //BOOST_NOEXCEPT
+ : obj_(move(rhs.obj_)), mtx_(rhs.mtx_)
+ {
+ }
+
+ /// assignment
+ externally_locked& operator=(externally_locked const& rhs) //BOOST_NOEXCEPT
+ {
+ obj_=rhs.obj_;
+ mtx_=rhs.mtx_;
+ return *this;
+ }
+
+ /// move assignment
+ externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) // BOOST_NOEXCEPT
+ {
+ obj_=move(BOOST_THREAD_RV(rhs).obj_);
+ mtx_=rhs.mtx_;
+ return *this;
+ }
+
+ void swap(externally_locked& rhs) //BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR)
+ {
+ swap(obj_, rhs.obj_);
+ swap(mtx_, rhs.mtx_);
+ }
+
+ /**
+ * Requires: The lk parameter must be locking the associated mtx.
+ *
+ * Returns: The address of the cloaked object..
+ *
+ * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions
+ */
+ T& get(strict_lock<mutex_type>& lk)
+ {
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+ return obj_;
+ }
+
+ const T& get(strict_lock<mutex_type>& lk) const
+ {
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+ return obj_;
+ }
+
+ template <class Lock>
+ T& get(nested_strict_lock<Lock>& lk)
+ {
+ BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+ return obj_;
+ }
+
+ template <class Lock>
+ const T& get(nested_strict_lock<Lock>& lk) const
+ {
+ BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+ return obj_;
+ }
+
+ /**
+ * Requires: The lk parameter must be locking the associated mtx.
+ * Returns: The address of the cloaked object..
+ *
+ * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions
+ */
+ template <class Lock>
+ T& get(Lock& lk)
+ {
+ BOOST_CONCEPT_ASSERT(( StrictLock<Lock> ));
+ BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/
+ BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+
+ return obj_;
+ }
+
+ mutex_type* mutex() const BOOST_NOEXCEPT
+ {
+ return mtx_;
+ }
+
+ // modifiers
+
+ void lock()
+ {
+ mtx_->lock();
+ }
+ void unlock()
+ {
+ mtx_->unlock();
+ }
+ bool try_lock()
+ {
+ return mtx_->try_lock();
+ }
+ // todo add time related functions
+
+ private:
+ T obj_;
+ mutex_type* mtx_;
+ };
+ //]
+
+ /**
+ * externally_locked<T&,M> specialization for T& that cloaks an reference to an object of type T, and actually
+ * provides full access to that object through the get and set member functions, provided you
+ * pass a reference to a strict lock object.
+ */
+
+ //[externally_locked_ref
+ template <typename T, typename MutexType>
+ class externally_locked<T&, MutexType>
+ {
+ //BOOST_CONCEPT_ASSERT(( CopyConstructible<T> ));
+ BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> ));
+
+ public:
+ typedef MutexType mutex_type;
+
+ BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked )
+
+ /**
+ * Effects: Constructs an externally locked object storing the cloaked reference object.
+ */
+ externally_locked(T& obj, mutex_type& mtx) BOOST_NOEXCEPT :
+ obj_(&obj), mtx_(&mtx)
+ {
+ }
+
+ /// copy constructor
+ externally_locked(externally_locked const& rhs) BOOST_NOEXCEPT :
+ obj_(rhs.obj_), mtx_(rhs.mtx_)
+ {
+ }
+
+ /// move constructor
+ externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) BOOST_NOEXCEPT :
+ obj_(rhs.obj_), mtx_(rhs.mtx_)
+ {
+ }
+
+ /// assignment
+ externally_locked& operator=(externally_locked const& rhs) BOOST_NOEXCEPT
+ {
+ obj_=rhs.obj_;
+ mtx_=rhs.mtx_;
+ return *this;
+ }
+
+ /// move assignment
+ externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) BOOST_NOEXCEPT
+ {
+ obj_=rhs.obj_;
+ mtx_=rhs.mtx_;
+ return *this;
+ }
+
+ void swap(externally_locked& rhs) BOOST_NOEXCEPT
+ {
+ swap(obj_, rhs.obj_);
+ swap(mtx_, rhs.mtx_);
+ }
+ /**
+ * Requires: The lk parameter must be locking the associated mtx.
+ *
+ * Returns: The address of the cloaked object..
+ *
+ * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions
+ */
+ T& get(strict_lock<mutex_type> const& lk)
+ {
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+ return *obj_;
+ }
+
+ const T& get(strict_lock<mutex_type> const& lk) const
+ {
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+ return *obj_;
+ }
+
+ template <class Lock>
+ T& get(nested_strict_lock<Lock> const& lk)
+ {
+ BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+ return *obj_;
+ }
+
+ template <class Lock>
+ const T& get(nested_strict_lock<Lock> const& lk) const
+ {
+ BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+ return *obj_;
+ }
+
+ /**
+ * Requires: The lk parameter must be locking the associated mtx.
+ * Returns: The address of the cloaked object..
+ *
+ * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions
+ */
+ template <class Lock>
+ T& get(Lock const& lk)
+ {
+ BOOST_CONCEPT_ASSERT(( StrictLock<Lock> ));
+ BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/
+ BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+ return *obj_;
+ }
+
+ /**
+ * Requires: The lk parameter must be locking the associated mtx.
+ * Returns: The address of the cloaked object..
+ *
+ * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions
+ */
+ template <class Lock>
+ T const& get(Lock const& lk) const
+ {
+ BOOST_CONCEPT_ASSERT(( StrictLock<Lock> ));
+ BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/
+ BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/
+ return *obj_;
+ }
+ mutex_type* mutex() const BOOST_NOEXCEPT
+ {
+ return mtx_;
+ }
+
+ void lock()
+ {
+ mtx_->lock();
+ }
+ void unlock()
+ {
+ mtx_->unlock();
+ }
+ bool try_lock()
+ {
+ return mtx_->try_lock();
+ }
+ // todo add time related functions
+
+ protected:
+ T* obj_;
+ mutex_type* mtx_;
+ };
+ //]
+
+ template <typename T, typename MutexType>
+ void swap(externally_locked<T, MutexType> & lhs, externally_locked<T, MutexType> & rhs) // BOOST_NOEXCEPT
+ {
+ lhs.swap(rhs);
+ }
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // header
diff --git a/boost/thread/externally_locked_stream.hpp b/boost/thread/externally_locked_stream.hpp
new file mode 100644
index 0000000000..aa9aeff79d
--- /dev/null
+++ b/boost/thread/externally_locked_stream.hpp
@@ -0,0 +1,170 @@
+// (C) Copyright 2012 Vicente J. Botet Escriba
+// 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)
+
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_STREAM_HPP
+#define BOOST_THREAD_EXTERNALLY_LOCKED_STREAM_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/detail/delete.hpp>
+
+#include <boost/thread/externally_locked.hpp>
+#include <boost/thread/lock_traits.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#include <boost/thread/strict_lock.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ template <typename Stream, typename RecursiveMutex=recursive_mutex>
+ class externally_locked_stream;
+
+ template <class Stream, typename RecursiveMutex=recursive_mutex>
+ class stream_guard
+ {
+
+ friend class externally_locked_stream<Stream, RecursiveMutex> ;
+ public:
+ typedef typename externally_locked_stream<Stream, RecursiveMutex>::mutex_type mutex_type;
+
+ BOOST_THREAD_MOVABLE_ONLY( stream_guard)
+
+ stream_guard(externally_locked_stream<Stream, RecursiveMutex>& mtx) :
+ mtx_(&mtx)
+ {
+ mtx.lock();
+ }
+
+ stream_guard(externally_locked_stream<Stream, RecursiveMutex>& mtx, adopt_lock_t) :
+ mtx_(&mtx)
+ {
+ }
+
+ stream_guard(BOOST_THREAD_RV_REF(stream_guard) rhs) BOOST_NOEXCEPT
+ : mtx_(rhs.mtx_)
+ {
+ rhs.mtx_= 0;
+ }
+
+ ~stream_guard()
+ {
+ if (mtx_ != 0) mtx_->unlock();
+ }
+
+ bool owns_lock(const mutex_type * l) const BOOST_NOEXCEPT
+ {
+ return l == mtx_->mutex();
+ }
+
+ /**
+ * @Requires mtx_
+ */
+ Stream& get() const
+ {
+ BOOST_THREAD_ASSERT_PRECONDITION( mtx_, lock_error() );
+ return mtx_->get(*this);
+ }
+ Stream& bypass() const
+ {
+ return get();
+ }
+
+
+ private:
+ externally_locked_stream<Stream, RecursiveMutex>* mtx_;
+ };
+
+ template <typename Stream, typename RecursiveMutex>
+ struct is_strict_lock_sur_parole<stream_guard<Stream, RecursiveMutex> > : true_type
+ {
+ };
+
+ /**
+ * externally_locked_stream cloaks a reference to an stream of type Stream, and actually
+ * provides full access to that object through the get and set member functions, provided you
+ * pass a reference to a strict lock object.
+ */
+
+ //[externally_locked_stream
+ template <typename Stream, typename RecursiveMutex>
+ class externally_locked_stream: public externally_locked<Stream&, RecursiveMutex>
+ {
+ typedef externally_locked<Stream&, RecursiveMutex> base_type;
+ public:
+ BOOST_THREAD_NO_COPYABLE( externally_locked_stream)
+
+ /**
+ * Effects: Constructs an externally locked object storing the cloaked reference object.
+ */
+ externally_locked_stream(Stream& stream, RecursiveMutex& mtx) BOOST_NOEXCEPT :
+ base_type(stream, mtx)
+ {
+ }
+
+ stream_guard<Stream, RecursiveMutex> hold() BOOST_NOEXCEPT
+ {
+ return stream_guard<Stream, RecursiveMutex> (*this);
+ }
+ Stream& bypass() const
+ {
+ stream_guard<Stream, RecursiveMutex> lk(*this);
+ return get(lk);
+ }
+ };
+ //]
+
+ template <typename Stream, typename RecursiveMutex, typename T>
+ inline const stream_guard<Stream, RecursiveMutex>& operator<<(const stream_guard<Stream, RecursiveMutex>& lck, T arg)
+ {
+ lck.get() << arg;
+ return lck;
+ }
+
+ template <typename Stream, typename RecursiveMutex>
+ inline const stream_guard<Stream, RecursiveMutex>& operator<<(const stream_guard<Stream, RecursiveMutex>& lck, Stream& (*arg)(Stream&))
+ {
+ lck.get() << arg;
+ return lck;
+ }
+
+ template <typename Stream, typename RecursiveMutex, typename T>
+ inline const stream_guard<Stream, RecursiveMutex>& operator>>(const stream_guard<Stream, RecursiveMutex>& lck, T& arg)
+ {
+ lck.get() >> arg;
+ return lck;
+ }
+
+ template <typename Stream, typename RecursiveMutex, typename T>
+ inline stream_guard<Stream, RecursiveMutex> operator<<(externally_locked_stream<Stream, RecursiveMutex>& mtx, T arg)
+ {
+ stream_guard<Stream, RecursiveMutex> lk(mtx);
+ mtx.get(lk) << arg;
+ return boost::move(lk);
+ }
+
+ template <typename Stream, typename RecursiveMutex>
+ inline stream_guard<Stream, RecursiveMutex> operator<<(externally_locked_stream<Stream, RecursiveMutex>& mtx, Stream& (*arg)(Stream&))
+ {
+ stream_guard<Stream, RecursiveMutex> lk(mtx);
+ mtx.get(lk) << arg;
+ return boost::move(lk);
+ }
+
+ template <typename Stream, typename RecursiveMutex, typename T>
+ inline stream_guard<Stream, RecursiveMutex> operator>>(externally_locked_stream<Stream, RecursiveMutex>& mtx, T& arg)
+ {
+ stream_guard<Stream, RecursiveMutex> lk(mtx);
+ mtx.get(lk) >> arg;
+ return boost::move(lk);
+ }
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // header
diff --git a/boost/thread/future.hpp b/boost/thread/future.hpp
index 8cad994de5..a1e69c355a 100644
--- a/boost/thread/future.hpp
+++ b/boost/thread/future.hpp
@@ -1,5 +1,5 @@
// (C) Copyright 2008-10 Anthony Williams
-// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+// (C) Copyright 2011-2014 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -15,42 +15,65 @@
#ifndef BOOST_NO_EXCEPTIONS
-#include <boost/detail/scoped_enum_emulation.hpp>
+#include <boost/core/scoped_enum.hpp>
#include <stdexcept>
+#include <iostream>
+#include <boost/thread/exceptional_ptr.hpp>
#include <boost/thread/detail/move.hpp>
+#include <boost/thread/detail/invoker.hpp>
+#include <boost/thread/detail/invoke.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/lock_algorithms.hpp>
+#include <boost/thread/lock_types.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/shared_ptr.hpp>
-#include <boost/scoped_ptr.hpp>
+#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
+#include <boost/optional.hpp>
+#else
+#include <boost/thread/csbl/memory/unique_ptr.hpp>
+//#include <boost/move/make_unique.hpp>
+#endif
#include <boost/type_traits/is_fundamental.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/remove_reference.hpp>
-#include <boost/type_traits/remove_cv.hpp>
-#include <boost/mpl/if.hpp>
+#include <boost/thread/detail/is_convertible.hpp>
+#include <boost/type_traits/decay.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/type_traits/conditional.hpp>
#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
#include <algorithm>
#include <boost/function.hpp>
#include <boost/bind.hpp>
-#include <boost/ref.hpp>
+#include <boost/core/ref.hpp>
#include <boost/scoped_array.hpp>
-#include <boost/utility/enable_if.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/core/enable_if.hpp>
+
#include <list>
#include <boost/next_prior.hpp>
#include <vector>
-#include <boost/system/error_code.hpp>
+
+#include <boost/thread/future_error_code.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include <boost/thread/detail/memory.hpp>
+#include <boost/container/scoped_allocator.hpp>
+#if ! defined BOOST_NO_CXX11_ALLOCATOR
+#include <memory>
+#endif
#endif
#include <boost/utility/result_of.hpp>
-//#include <boost/thread.hpp>
+#include <boost/thread/thread_only.hpp>
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
+#include <boost/thread/csbl/tuple.hpp>
+#include <boost/thread/csbl/vector.hpp>
+#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_FUTURE future
@@ -58,36 +81,18 @@
#define BOOST_THREAD_FUTURE unique_future
#endif
-
namespace boost
{
- //enum class future_errc
- BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc)
- {
- broken_promise,
- future_already_retrieved,
- promise_already_satisfied,
- no_state
- }
- BOOST_SCOPED_ENUM_DECLARE_END(future_errc)
-
- namespace system
- {
- template <>
- struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type {};
-
- #ifdef BOOST_NO_SCOPED_ENUMS
- template <>
- struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
- #endif
- }
-
//enum class launch
BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
{
+ none = 0,
async = 1,
deferred = 2,
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ executor = 4,
+#endif
any = async | deferred
}
BOOST_SCOPED_ENUM_DECLARE_END(launch)
@@ -101,26 +106,6 @@ namespace boost
}
BOOST_SCOPED_ENUM_DECLARE_END(future_status)
- BOOST_THREAD_DECL
- const system::error_category& future_category();
-
- namespace system
- {
- inline BOOST_THREAD_DECL
- error_code
- make_error_code(future_errc e)
- {
- return error_code(underlying_cast<int>(e), boost::future_category());
- }
-
- inline BOOST_THREAD_DECL
- error_condition
- make_error_condition(future_errc e)
- {
- return error_condition(underlying_cast<int>(e), future_category());
- }
- }
-
class BOOST_SYMBOL_VISIBLE future_error
: public std::logic_error
{
@@ -136,15 +121,13 @@ namespace boost
{
return ec_;
}
-
- //virtual ~future_error() BOOST_NOEXCEPT;
};
class BOOST_SYMBOL_VISIBLE future_uninitialized:
public future_error
{
public:
- future_uninitialized():
+ future_uninitialized() :
future_error(system::make_error_code(future_errc::no_state))
{}
};
@@ -179,69 +162,148 @@ namespace boost
public:
task_already_started():
future_error(system::make_error_code(future_errc::promise_already_satisfied))
- //std::logic_error("Task already started")
{}
};
- class BOOST_SYMBOL_VISIBLE task_moved:
- public future_error
- {
- public:
- task_moved():
- future_error(system::make_error_code(future_errc::no_state))
- //std::logic_error("Task moved")
- {}
- };
+ class BOOST_SYMBOL_VISIBLE task_moved:
+ public future_error
+ {
+ public:
+ task_moved():
+ future_error(system::make_error_code(future_errc::no_state))
+ {}
+ };
- class promise_moved:
- public future_error
- {
- public:
- promise_moved():
- future_error(system::make_error_code(future_errc::no_state))
- //std::logic_error("Promise moved")
- {}
- };
+ class promise_moved:
+ public future_error
+ {
+ public:
+ promise_moved():
+ future_error(system::make_error_code(future_errc::no_state))
+ {}
+ };
namespace future_state
{
- enum state { uninitialized, waiting, ready, moved };
+ enum state { uninitialized, waiting, ready, moved, deferred };
}
namespace detail
{
- struct future_object_base
+ struct relocker
+ {
+ boost::unique_lock<boost::mutex>& lock_;
+ bool unlocked_;
+
+ relocker(boost::unique_lock<boost::mutex>& lk):
+ lock_(lk)
+ {
+ lock_.unlock();
+ unlocked_=true;
+ }
+ ~relocker()
+ {
+ if (unlocked_) {
+ lock_.lock();
+ }
+ }
+ void lock() {
+ if (unlocked_) {
+ lock_.lock();
+ unlocked_=false;
+ }
+ }
+ private:
+ relocker& operator=(relocker const&);
+ };
+
+ struct shared_state_base : enable_shared_from_this<shared_state_base>
{
+ typedef std::list<boost::condition_variable_any*> waiter_list;
+ // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
+ typedef shared_ptr<shared_state_base> continuation_ptr_type;
+
boost::exception_ptr exception;
bool done;
- bool thread_was_interrupted;
- boost::mutex mutex;
+ bool is_deferred_;
+ launch policy_;
+ bool is_constructed;
+ mutable boost::mutex mutex;
boost::condition_variable waiters;
- typedef std::list<boost::condition_variable_any*> waiter_list;
waiter_list external_waiters;
boost::function<void()> callback;
+ // This declaration should be only included conditionally, but is included to maintain the same layout.
+ continuation_ptr_type continuation_ptr;
+
+ // This declaration should be only included conditionally, but is included to maintain the same layout.
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>&)
+ {
+ }
- future_object_base():
+ shared_state_base():
done(false),
- thread_was_interrupted(false)
+ is_deferred_(false),
+ policy_(launch::none),
+ is_constructed(false),
+ continuation_ptr()
{}
- virtual ~future_object_base()
+ virtual ~shared_state_base()
{}
+ void set_deferred()
+ {
+ is_deferred_ = true;
+ policy_ = launch::deferred;
+ }
+ void set_async()
+ {
+ is_deferred_ = false;
+ policy_ = launch::async;
+ }
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ void set_executor()
+ {
+ is_deferred_ = false;
+ policy_ = launch::executor;
+ }
+#endif
waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
{
- boost::unique_lock<boost::mutex> lock(mutex);
+ boost::unique_lock<boost::mutex> lock(this->mutex);
do_callback(lock);
return external_waiters.insert(external_waiters.end(),&cv);
}
void remove_external_waiter(waiter_list::iterator it)
{
- boost::lock_guard<boost::mutex> lock(mutex);
+ boost::lock_guard<boost::mutex> lock(this->mutex);
external_waiters.erase(it);
}
- void mark_finished_internal()
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ void do_continuation(boost::unique_lock<boost::mutex>& lock)
+ {
+ if (continuation_ptr) {
+ continuation_ptr_type this_continuation_ptr = continuation_ptr;
+ continuation_ptr.reset();
+ this_continuation_ptr->launch_continuation(lock);
+ }
+ }
+#else
+ void do_continuation(boost::unique_lock<boost::mutex>&)
+ {
+ }
+#endif
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
+ {
+ continuation_ptr= continuation;
+ if (done) {
+ do_continuation(lock);
+ }
+ }
+#endif
+ void mark_finished_internal(boost::unique_lock<boost::mutex>& lock)
{
done=true;
waiters.notify_all();
@@ -250,24 +312,13 @@ namespace boost
{
(*it)->notify_all();
}
+ do_continuation(lock);
}
-
- struct relocker
+ void make_ready()
{
- boost::unique_lock<boost::mutex>& lock;
-
- relocker(boost::unique_lock<boost::mutex>& lock_):
- lock(lock_)
- {
- lock.unlock();
- }
- ~relocker()
- {
- lock.lock();
- }
- private:
- relocker& operator=(relocker const&);
- };
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ mark_finished_internal(lock);
+ }
void do_callback(boost::unique_lock<boost::mutex>& lock)
{
@@ -279,28 +330,62 @@ namespace boost
}
}
+ virtual bool run_if_is_deferred()
+ {
+ boost::unique_lock<boost::mutex> lk(this->mutex);
+ if (is_deferred_)
+ {
+ is_deferred_=false;
+ execute(lk);
+ return true;
+ }
+ else
+ return false;
+ }
+ virtual bool run_if_is_deferred_or_ready()
+ {
+ boost::unique_lock<boost::mutex> lk(this->mutex);
+ if (is_deferred_)
+ {
+ is_deferred_=false;
+ execute(lk);
- void wait(bool rethrow=true)
+ return true;
+ }
+ else
+ return done;
+ }
+ void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true)
{
- boost::unique_lock<boost::mutex> lock(mutex);
- do_callback(lock);
- while(!done)
- {
- waiters.wait(lock);
- }
- if(rethrow && thread_was_interrupted)
- {
- throw boost::thread_interrupted();
- }
- if(rethrow && exception)
- {
- boost::rethrow_exception(exception);
- }
+ do_callback(lk);
+ if (is_deferred_)
+ {
+ is_deferred_=false;
+ execute(lk);
+ }
+ while(!done)
+ {
+ waiters.wait(lk);
+ }
+ if(rethrow && exception)
+ {
+ boost::rethrow_exception(exception);
+ }
}
+ virtual void wait(bool rethrow=true)
+ {
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ wait_internal(lock, rethrow);
+ }
+
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_wait_until(boost::system_time const& target_time)
{
- boost::unique_lock<boost::mutex> lock(mutex);
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ if (is_deferred_)
+ return false;
+
do_callback(lock);
while(!done)
{
@@ -312,14 +397,16 @@ namespace boost
}
return true;
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration>
future_status
wait_until(const chrono::time_point<Clock, Duration>& abs_time)
{
- boost::unique_lock<boost::mutex> lock(mutex);
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ if (is_deferred_)
+ return future_status::deferred;
do_callback(lock);
while(!done)
{
@@ -332,281 +419,604 @@ namespace boost
return future_status::ready;
}
#endif
- void mark_exceptional_finish_internal(boost::exception_ptr const& e)
+ void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
{
exception=e;
- mark_finished_internal();
+ mark_finished_internal(lock);
}
+
void mark_exceptional_finish()
{
- boost::lock_guard<boost::mutex> lock(mutex);
- mark_exceptional_finish_internal(boost::current_exception());
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ mark_exceptional_finish_internal(boost::current_exception(), lock);
}
+
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
void mark_interrupted_finish()
{
- boost::lock_guard<boost::mutex> lock(mutex);
- thread_was_interrupted=true;
- mark_finished_internal();
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ exception = boost::copy_exception(boost::thread_interrupted());
+ mark_finished_internal(lock);
+ }
+
+ void set_interrupted_at_thread_exit()
+ {
+ unique_lock<boost::mutex> lk(this->mutex);
+ if (has_value(lk))
+ {
+ throw_exception(promise_already_satisfied());
+ }
+ exception = boost::copy_exception(boost::thread_interrupted());
+ this->is_constructed = true;
+ detail::make_ready_at_thread_exit(shared_from_this());
+ }
+#endif
+
+ void set_exception_at_thread_exit(exception_ptr e)
+ {
+ unique_lock<boost::mutex> lk(this->mutex);
+ if (has_value(lk))
+ {
+ throw_exception(promise_already_satisfied());
+ }
+ exception=e;
+ this->is_constructed = true;
+ detail::make_ready_at_thread_exit(shared_from_this());
+ }
+
+ bool has_value() const
+ {
+ boost::lock_guard<boost::mutex> lock(this->mutex);
+ return done && ! exception;
+ }
+
+ bool has_value(unique_lock<boost::mutex>& ) const
+ {
+ return done && ! exception;
+ }
+
+ bool has_exception() const
+ {
+ boost::lock_guard<boost::mutex> lock(this->mutex);
+ return done && exception;
+ }
+
+ bool has_exception(unique_lock<boost::mutex>&) const
+ {
+ return done && exception;
+ }
+
+ bool is_deferred(boost::lock_guard<boost::mutex>&) const {
+ return is_deferred_;
+ }
+
+ launch launch_policy(boost::unique_lock<boost::mutex>&) const
+ {
+ return policy_;
+ }
+
+ future_state::state get_state() const
+ {
+ boost::lock_guard<boost::mutex> guard(this->mutex);
+ if(!done)
+ {
+ return future_state::waiting;
+ }
+ else
+ {
+ return future_state::ready;
+ }
}
- bool has_value()
+
+ exception_ptr get_exception_ptr()
{
- boost::lock_guard<boost::mutex> lock(mutex);
- return done && !(exception || thread_was_interrupted);
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ return get_exception_ptr(lock);
}
- bool has_exception()
+ exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock)
{
- boost::lock_guard<boost::mutex> lock(mutex);
- return done && (exception || thread_was_interrupted);
+ wait_internal(lock, false);
+ return exception;
}
template<typename F,typename U>
void set_wait_callback(F f,U* u)
{
+ boost::lock_guard<boost::mutex> lock(this->mutex);
callback=boost::bind(f,boost::ref(*u));
}
+ virtual void execute(boost::unique_lock<boost::mutex>&) {}
+
private:
- future_object_base(future_object_base const&);
- future_object_base& operator=(future_object_base const&);
+ shared_state_base(shared_state_base const&);
+ shared_state_base& operator=(shared_state_base const&);
};
+ // Used to create stand-alone futures
template<typename T>
- struct future_traits
+ struct shared_state:
+ detail::shared_state_base
{
- typedef boost::scoped_ptr<T> storage_type;
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
+ typedef boost::optional<T> storage_type;
+#else
+ typedef boost::csbl::unique_ptr<T> storage_type;
+#endif
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef T const& source_reference_type;
- struct dummy;
- typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
- typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type;
+ typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
+ typedef T move_dest_type;
#elif defined BOOST_THREAD_USES_MOVE
- typedef T& source_reference_type;
- typedef typename boost::mpl::if_<boost::has_move_emulation_enabled<T>,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
- typedef typename boost::mpl::if_<boost::has_move_emulation_enabled<T>,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
+ typedef typename conditional<boost::is_fundamental<T>::value,T,T const&>::type source_reference_type;
+ typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
+ typedef T move_dest_type;
#else
typedef T& source_reference_type;
- typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
- typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
+ typedef typename conditional<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >::value, BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
+ typedef typename conditional<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >::value, BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
#endif
typedef const T& shared_future_get_result_type;
- static void init(storage_type& storage,source_reference_type t)
+ storage_type result;
+
+ shared_state():
+ result()
+ {}
+
+ ~shared_state()
+ {}
+
+ void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
{
- storage.reset(new T(t));
+#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
+ result = result_;
+#else
+ result.reset(new T(result_));
+#endif
+ this->mark_finished_internal(lock);
}
- static void init(storage_type& storage,rvalue_source_type t)
+ void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
{
- storage.reset(new T(static_cast<rvalue_source_type>(t)));
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
+ result = boost::move(result_);
+#else
+ result.reset(new T(boost::move(result_)));
+#endif
+#else
+#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
+ result = boost::move(result_);
+#else
+ result.reset(new T(static_cast<rvalue_source_type>(result_)));
+#endif
+#endif
+ this->mark_finished_internal(lock);
}
- static void cleanup(storage_type& storage)
+ void mark_finished_with_result(source_reference_type result_)
{
- storage.reset();
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ this->mark_finished_with_result_internal(result_, lock);
}
+
+ void mark_finished_with_result(rvalue_source_type result_)
+ {
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ mark_finished_with_result_internal(boost::move(result_), lock);
+#else
+ mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
+#endif
+ }
+
+ storage_type& get_storage(boost::unique_lock<boost::mutex>& lock)
+ {
+ wait_internal(lock);
+ return result;
+ }
+ virtual move_dest_type get()
+ {
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ return boost::move(*get_storage(lock));
+ }
+
+ virtual shared_future_get_result_type get_sh()
+ {
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ return *get_storage(lock);
+ }
+
+ void set_value_at_thread_exit(source_reference_type result_)
+ {
+ unique_lock<boost::mutex> lk(this->mutex);
+ if (this->has_value(lk))
+ {
+ throw_exception(promise_already_satisfied());
+ }
+#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
+ result = result_;
+#else
+ result.reset(new T(result_));
+#endif
+
+ this->is_constructed = true;
+ detail::make_ready_at_thread_exit(shared_from_this());
+ }
+ void set_value_at_thread_exit(rvalue_source_type result_)
+ {
+ unique_lock<boost::mutex> lk(this->mutex);
+ if (this->has_value(lk))
+ throw_exception(promise_already_satisfied());
+
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
+ result = boost::move(result_);
+#else
+ result.reset(new T(boost::move(result_)));
+#endif
+#else
+#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
+ result = boost::move(result_);
+#else
+ result.reset(new T(static_cast<rvalue_source_type>(result_)));
+#endif
+#endif
+ this->is_constructed = true;
+ detail::make_ready_at_thread_exit(shared_from_this());
+ }
+
+ private:
+ shared_state(shared_state const&);
+ shared_state& operator=(shared_state const&);
};
template<typename T>
- struct future_traits<T&>
+ struct shared_state<T&>:
+ detail::shared_state_base
{
typedef T* storage_type;
typedef T& source_reference_type;
- struct rvalue_source_type
- {};
typedef T& move_dest_type;
typedef T& shared_future_get_result_type;
- static void init(storage_type& storage,T& t)
+ T* result;
+
+ shared_state():
+ result(0)
+ {}
+
+ ~shared_state()
{
- storage=&t;
}
- static void cleanup(storage_type& storage)
+ void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
{
- storage=0;
+ result= &result_;
+ mark_finished_internal(lock);
}
- };
- template<>
- struct future_traits<void>
- {
- typedef bool storage_type;
- typedef void move_dest_type;
- typedef void shared_future_get_result_type;
+ void mark_finished_with_result(source_reference_type result_)
+ {
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ mark_finished_with_result_internal(result_, lock);
+ }
- static void init(storage_type& storage)
+ virtual T& get()
{
- storage=true;
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ wait_internal(lock);
+ return *result;
}
- static void cleanup(storage_type& storage)
+ virtual T& get_sh()
{
- storage=false;
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ wait_internal(lock);
+ return *result;
}
+ void set_value_at_thread_exit(T& result_)
+ {
+ unique_lock<boost::mutex> lk(this->mutex);
+ if (this->has_value(lk))
+ throw_exception(promise_already_satisfied());
+ result= &result_;
+ this->is_constructed = true;
+ detail::make_ready_at_thread_exit(shared_from_this());
+ }
+
+ private:
+ shared_state(shared_state const&);
+ shared_state& operator=(shared_state const&);
};
- template<typename T>
- struct future_object:
- detail::future_object_base
+ template<>
+ struct shared_state<void>:
+ detail::shared_state_base
{
- typedef typename future_traits<T>::storage_type storage_type;
- typedef typename future_traits<T>::source_reference_type source_reference_type;
- typedef typename future_traits<T>::rvalue_source_type rvalue_source_type;
- typedef typename future_traits<T>::move_dest_type move_dest_type;
- typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type;
-
- storage_type result;
+ typedef void shared_future_get_result_type;
+ typedef void move_dest_type;
- future_object():
- result(0)
+ shared_state()
{}
- void mark_finished_with_result_internal(source_reference_type result_)
+ void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
{
- future_traits<T>::init(result,result_);
- mark_finished_internal();
+ mark_finished_internal(lock);
}
- void mark_finished_with_result_internal(rvalue_source_type result_)
+ void mark_finished_with_result()
{
- future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
- mark_finished_internal();
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ mark_finished_with_result_internal(lock);
}
- void mark_finished_with_result(source_reference_type result_)
+ virtual void get()
{
- boost::lock_guard<boost::mutex> lock(mutex);
- mark_finished_with_result_internal(result_);
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ this->wait_internal(lock);
}
- void mark_finished_with_result(rvalue_source_type result_)
+ virtual void get_sh()
{
- boost::lock_guard<boost::mutex> lock(mutex);
- mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_));
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ this->wait_internal(lock);
}
- move_dest_type get()
+ void set_value_at_thread_exit()
{
- wait();
- return static_cast<move_dest_type>(*result);
+ unique_lock<boost::mutex> lk(this->mutex);
+ if (this->has_value(lk))
+ {
+ throw_exception(promise_already_satisfied());
+ }
+ this->is_constructed = true;
+ detail::make_ready_at_thread_exit(shared_from_this());
}
+ private:
+ shared_state(shared_state const&);
+ shared_state& operator=(shared_state const&);
+ };
+
+ /////////////////////////
+ /// future_async_shared_state_base
+ /////////////////////////
+ template<typename Rp>
+ struct future_async_shared_state_base: shared_state<Rp>
+ {
+ typedef shared_state<Rp> base_type;
+ protected:
+ boost::thread thr_;
+ void join()
+ {
+ if (thr_.joinable()) thr_.join();
+ }
+ public:
+ future_async_shared_state_base()
+ {
+ this->set_async();
+ }
+
+ ~future_async_shared_state_base()
+ {
+ join();
+ }
+
+ virtual void wait(bool rethrow)
+ {
+ join();
+ this->base_type::wait(rethrow);
+ }
+ };
- shared_future_get_result_type get_sh()
+ /////////////////////////
+ /// future_async_shared_state
+ /////////////////////////
+ template<typename Rp, typename Fp>
+ struct future_async_shared_state: future_async_shared_state_base<Rp>
+ {
+ explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ this->thr_ = thread(&future_async_shared_state::run, this, boost::forward<Fp>(f));
+ }
+
+ static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ try
+ {
+ that->mark_finished_with_result(f());
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
{
- wait();
- return static_cast<shared_future_get_result_type>(*result);
+ that->mark_interrupted_finish();
}
+#endif
+ catch(...)
+ {
+ that->mark_exceptional_finish();
+ }
+ }
+ };
- future_state::state get_state()
+ template<typename Fp>
+ struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void>
+ {
+ explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ this->thr_ = thread(&future_async_shared_state::run, this, boost::move(f));
+ }
+
+ static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ try
{
- boost::lock_guard<boost::mutex> guard(mutex);
- if(!done)
- {
- return future_state::waiting;
- }
- else
- {
- return future_state::ready;
- }
+ f();
+ that->mark_finished_with_result();
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ that->mark_interrupted_finish();
}
+#endif
+ catch(...)
+ {
+ that->mark_exceptional_finish();
+ }
+ }
+ };
- private:
- future_object(future_object const&);
- future_object& operator=(future_object const&);
+ template<typename Rp, typename Fp>
+ struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&>
+ {
+ explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ this->thr_ = thread(&future_async_shared_state::run, this, boost::move(f));
+ }
+
+ static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ try
+ {
+ that->mark_finished_with_result(f());
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ that->mark_interrupted_finish();
+ }
+#endif
+ catch(...)
+ {
+ that->mark_exceptional_finish();
+ }
+ }
};
- template<>
- struct future_object<void>:
- detail::future_object_base
+ //////////////////////////
+ /// future_deferred_shared_state
+ //////////////////////////
+ template<typename Rp, typename Fp>
+ struct future_deferred_shared_state: shared_state<Rp>
{
- typedef void shared_future_get_result_type;
+ typedef shared_state<Rp> base_type;
+ Fp func_;
- future_object()
- {}
+ public:
+ explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
+ : func_(boost::move(f))
+ {
+ this->set_deferred();
+ }
- void mark_finished_with_result_internal()
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
+ try
{
- mark_finished_internal();
+ Fp local_fuct=boost::move(func_);
+ relocker relock(lck);
+ Rp res = local_fuct();
+ relock.lock();
+ this->mark_finished_with_result_internal(boost::move(res), lck);
}
-
- void mark_finished_with_result()
+ catch (...)
{
- boost::lock_guard<boost::mutex> lock(mutex);
- mark_finished_with_result_internal();
+ this->mark_exceptional_finish_internal(current_exception(), lck);
}
+ }
+ };
+ template<typename Rp, typename Fp>
+ struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&>
+ {
+ typedef shared_state<Rp&> base_type;
+ Fp func_;
+
+ public:
+ explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
+ : func_(boost::move(f))
+ {
+ this->set_deferred();
+ }
- void get()
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
+ try
{
- wait();
+ this->mark_finished_with_result_internal(func_(), lck);
}
- void get_sh()
+ catch (...)
{
- wait();
+ this->mark_exceptional_finish_internal(current_exception(), lck);
}
- future_state::state get_state()
+ }
+ };
+
+ template<typename Fp>
+ struct future_deferred_shared_state<void,Fp>: shared_state<void>
+ {
+ typedef shared_state<void> base_type;
+ Fp func_;
+
+ public:
+ explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
+ : func_(boost::move(f))
+ {
+ this->set_deferred();
+ }
+
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
+ try
{
- boost::lock_guard<boost::mutex> guard(mutex);
- if(!done)
- {
- return future_state::waiting;
- }
- else
- {
- return future_state::ready;
- }
+ Fp local_fuct=boost::move(func_);
+ relocker relock(lck);
+ local_fuct();
+ relock.lock();
+ this->mark_finished_with_result_internal(lck);
}
- private:
- future_object(future_object const&);
- future_object& operator=(future_object const&);
+ catch (...)
+ {
+ this->mark_exceptional_finish_internal(current_exception(), lck);
+ }
+ }
};
-// template<typename T, typename Allocator>
-// struct future_object_alloc: public future_object<T>
-// {
-// typedef future_object<T> base;
-// Allocator alloc_;
-//
-// public:
-// explicit future_object_alloc(const Allocator& a)
-// : alloc_(a) {}
-//
-// };
class future_waiter
{
struct registered_waiter;
- typedef std::vector<registered_waiter>::size_type count_type;
+ typedef std::vector<int>::size_type count_type;
struct registered_waiter
{
- boost::shared_ptr<detail::future_object_base> future_;
- detail::future_object_base::waiter_list::iterator wait_iterator;
+ boost::shared_ptr<detail::shared_state_base> future_;
+ detail::shared_state_base::waiter_list::iterator wait_iterator;
count_type index;
- registered_waiter(boost::shared_ptr<detail::future_object_base> const& a_future,
- detail::future_object_base::waiter_list::iterator wait_iterator_,
+ registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future,
+ detail::shared_state_base::waiter_list::iterator wait_iterator_,
count_type index_):
future_(a_future),wait_iterator(wait_iterator_),index(index_)
{}
-
};
struct all_futures_lock
{
- count_type count;
- boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
+#ifdef _MANAGED
+ typedef std::ptrdiff_t count_type_portable;
+#else
+ typedef count_type count_type_portable;
+#endif
+ count_type_portable count;
+ boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
all_futures_lock(std::vector<registered_waiter>& futures):
count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
{
- for(count_type i=0;i<count;++i)
+ for(count_type_portable i=0;i<count;++i)
{
-#if defined __DECCXX || defined __SUNPRO_CC
- locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move();
-#else
- locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex);
-#endif
+ locks[i]=BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(futures[i].future_->mutex));
}
}
@@ -617,7 +1027,7 @@ namespace boost
void unlock()
{
- for(count_type i=0;i<count;++i)
+ for(count_type_portable i=0;i<count;++i)
{
locks[i].unlock();
}
@@ -638,11 +1048,25 @@ namespace boost
{
if(f.future_)
{
- futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count));
+ registered_waiter waiter(f.future_,f.future_->register_external_waiter(cv),future_count);
+ try {
+ futures.push_back(waiter);
+ } catch(...) {
+ f.future_->remove_external_waiter(waiter.wait_iterator);
+ throw;
+ }
}
++future_count;
}
+#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ template<typename F1, typename... Fs>
+ void add(F1& f1, Fs&... fs)
+ {
+ add(f1); add(fs...);
+ }
+#endif
+
count_type wait()
{
all_futures_lock lk(futures);
@@ -666,7 +1090,6 @@ namespace boost
futures[i].future_->remove_external_waiter(futures[i].wait_iterator);
}
}
-
};
}
@@ -681,18 +1104,21 @@ namespace boost
struct is_future_type
{
BOOST_STATIC_CONSTANT(bool, value=false);
+ typedef void type;
};
template<typename T>
struct is_future_type<BOOST_THREAD_FUTURE<T> >
{
BOOST_STATIC_CONSTANT(bool, value=true);
+ typedef T type;
};
template<typename T>
struct is_future_type<shared_future<T> >
{
BOOST_STATIC_CONSTANT(bool, value=true);
+ typedef T type;
};
template<typename Iterator>
@@ -704,6 +1130,7 @@ namespace boost
}
}
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<typename F1,typename F2>
typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2)
{
@@ -737,6 +1164,16 @@ namespace boost
f4.wait();
f5.wait();
}
+#else
+ template<typename F1, typename... Fs>
+ void wait_for_all(F1& f1, Fs&... fs)
+ {
+ bool dummy[] = { (f1.wait(), true), (fs.wait(), true)... };
+
+ // prevent unused parameter warning
+ (void) dummy;
+ }
+#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename Iterator>
typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
@@ -752,6 +1189,7 @@ namespace boost
return boost::next(begin,waiter.wait());
}
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
template<typename F1,typename F2>
typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2)
{
@@ -793,6 +1231,15 @@ namespace boost
waiter.add(f5);
return waiter.wait();
}
+#else
+ template<typename F1, typename... Fs>
+ typename boost::enable_if<is_future_type<F1>, unsigned>::type wait_for_any(F1& f1, Fs&... fs)
+ {
+ detail::future_waiter waiter;
+ waiter.add(f1, fs...);
+ return waiter.wait();
+ }
+#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename R>
class promise;
@@ -800,72 +1247,78 @@ namespace boost
template <typename R>
class packaged_task;
- template <typename R>
- class BOOST_THREAD_FUTURE
+ namespace detail
{
- private:
+ /// Common implementation for all the futures independently of the return type
+ class base_future
+ {
+ };
+ /// Common implementation for future and shared_future.
+ template <typename R>
+ class basic_future : public base_future
+ {
+ protected:
+ public:
- typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+ typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
+ typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
- future_ptr future_;
+ static //BOOST_CONSTEXPR
+ future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) {
+ promise<R> p;
+ p.set_exception(ex.ptr_);
+ return p.get_future().future_;
+ }
- friend class shared_future<R>;
- friend class promise<R>;
- friend class packaged_task<R>;
- friend class detail::future_waiter;
+ void set_exceptional_if_invalid() {
+ if (valid()) return;
+ promise<R> p;
+ p.set_exception(future_uninitialized());
+ future_ = p.get_future().future_;
+ }
- typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
- BOOST_THREAD_FUTURE(future_ptr a_future):
- future_(a_future)
- {}
+ future_ptr future_;
- public:
- BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
+ basic_future(future_ptr a_future):
+ future_(a_future)
+ {
+ }
+ // Copy construction from a shared_future
+ explicit basic_future(const shared_future<R>&) BOOST_NOEXCEPT;
+
+ public:
typedef future_state::state state;
- BOOST_THREAD_FUTURE()
- {}
+ BOOST_THREAD_MOVABLE_ONLY(basic_future)
+ basic_future(): future_() {}
- ~BOOST_THREAD_FUTURE()
- {}
- BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
- future_(BOOST_THREAD_RV(other).future_)
+ //BOOST_CONSTEXPR
+ basic_future(exceptional_ptr const& ex)
+ : future_(make_exceptional_future_ptr(ex))
{
- BOOST_THREAD_RV(other).future_.reset();
}
- BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
- {
- future_=BOOST_THREAD_RV(other).future_;
- BOOST_THREAD_RV(other).future_.reset();
- return *this;
- }
+ ~basic_future() {}
- shared_future<R> share()
+ basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT:
+ future_(BOOST_THREAD_RV(other).future_)
{
- return shared_future<R>(::boost::move(*this));
+ BOOST_THREAD_RV(other).future_.reset();
}
-
- void swap(BOOST_THREAD_FUTURE& other)
+ basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT
{
- future_.swap(other.future_);
+ future_=BOOST_THREAD_RV(other).future_;
+ BOOST_THREAD_RV(other).future_.reset();
+ return *this;
}
-
- // retrieving the value
- move_dest_type get()
+ void swap(basic_future& that) BOOST_NOEXCEPT
{
- if(!future_)
- {
- boost::throw_exception(future_uninitialized());
- }
-
- return future_->get();
+ future_.swap(that.future_);
}
-
// functions to check state, and wait for ready
- state get_state() const BOOST_NOEXCEPT
+ state get_state() const
{
if(!future_)
{
@@ -874,27 +1327,39 @@ namespace boost
return future_->get_state();
}
- bool is_ready() const BOOST_NOEXCEPT
+ bool is_ready() const
{
return get_state()==future_state::ready;
}
- bool has_exception() const BOOST_NOEXCEPT
+ bool has_exception() const
{
return future_ && future_->has_exception();
}
- bool has_value() const BOOST_NOEXCEPT
+ bool has_value() const
{
return future_ && future_->has_value();
}
+ launch launch_policy(boost::unique_lock<boost::mutex>& lk) const
+ {
+ if ( future_ ) return future_->launch_policy(lk);
+ else return launch(launch::none);
+ }
+
+ exception_ptr get_exception_ptr()
+ {
+ return future_
+ ? future_->get_exception_ptr()
+ : exception_ptr();
+ }
+
bool valid() const BOOST_NOEXCEPT
{
return future_ != 0;
}
-
void wait() const
{
if(!future_)
@@ -904,6 +1369,7 @@ namespace boost
future_->wait(false);
}
+#if defined BOOST_THREAD_USES_DATETIME
template<typename Duration>
bool timed_wait(Duration const& rel_time) const
{
@@ -918,6 +1384,7 @@ namespace boost
}
return future_->timed_wait_until(abs_time);
}
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
future_status
@@ -937,177 +1404,764 @@ namespace boost
return future_->wait_until(abs_time);
}
#endif
+
+ };
+
+ } // detail
+ BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
+
+ namespace detail
+ {
+#if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
+ template <class Rp, class Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
+
+ template <class Rp, class Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
+#endif // #if (!defined _MSC_VER || _MSC_VER >= 1400)
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template<typename F, typename Rp, typename Fp>
+ struct future_deferred_continuation_shared_state;
+ template<typename F, typename Rp, typename Fp>
+ struct future_async_continuation_shared_state;
+
+ template <class F, class Rp, class Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+#endif
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ template<typename F, typename Rp>
+ struct future_unwrap_shared_state;
+ template <class F, class Rp>
+ inline BOOST_THREAD_FUTURE<Rp>
+ make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
+#endif
+ }
+
+ template <typename R>
+ class BOOST_THREAD_FUTURE : public detail::basic_future<R>
+ {
+ private:
+ typedef detail::basic_future<R> base_type;
+ typedef typename base_type::future_ptr future_ptr;
+
+ friend class shared_future<R>;
+ friend class promise<R>;
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template <typename, typename, typename>
+ friend struct detail::future_async_continuation_shared_state;
+ template <typename, typename, typename>
+ friend struct detail::future_deferred_continuation_shared_state;
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+#endif
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ template<typename F, typename Rp>
+ friend struct detail::future_unwrap_shared_state;
+ template <class F, class Rp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
+#endif
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ template <class> friend class packaged_task; // todo check if this works in windows
+#else
+ friend class packaged_task<R>;
+#endif
+ friend class detail::future_waiter;
+
+ template <class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
+
+ template <class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
+
+
+ typedef typename base_type::move_dest_type move_dest_type;
+ public: // when_all
+
+ BOOST_THREAD_FUTURE(future_ptr a_future):
+ base_type(a_future)
+ {
+ }
+
+ public:
+ BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
+ typedef future_state::state state;
+ typedef R value_type; // EXTENSION
+
+ BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
+ //BOOST_CONSTEXPR
+ BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
+ base_type(ex) {}
+
+ ~BOOST_THREAD_FUTURE() {}
+
+ BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
+ base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
+ {
+ }
+ inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
+
+ BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
+ {
+ this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
+ return *this;
+ }
+
+ shared_future<R> share()
+ {
+ return shared_future<R>(::boost::move(*this));
+ }
+
+ void swap(BOOST_THREAD_FUTURE& other)
+ {
+ static_cast<base_type*>(this)->swap(other);
+ }
+
+ // todo this function must be private and friendship provided to the internal users.
+ void set_async()
+ {
+ this->future_->set_async();
+ }
+ // todo this function must be private and friendship provided to the internal users.
+ void set_deferred()
+ {
+ this->future_->set_deferred();
+ }
+ bool run_if_is_deferred() {
+ return this->future_->run_if_is_deferred();
+ }
+ bool run_if_is_deferred_or_ready() {
+ return this->future_->run_if_is_deferred_or_ready();
+ }
+ // retrieving the value
+ move_dest_type get()
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ future_ptr fut_=this->future_;
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
+#endif
+ return fut_->get();
+ }
+
+ template <typename R2>
+ typename boost::disable_if< is_void<R2>, move_dest_type>::type
+ get_or(BOOST_THREAD_RV_REF(R2) v)
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ this->future_->wait(false);
+ future_ptr fut_=this->future_;
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
+#endif
+ if (fut_->has_value()) {
+ return fut_->get();
+ }
+ else {
+ return boost::move(v);
+ }
+ }
+
+ template <typename R2>
+ typename boost::disable_if< is_void<R2>, move_dest_type>::type
+ get_or(R2 const& v) // EXTENSION
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ this->future_->wait(false);
+ future_ptr fut_=this->future_;
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
+#endif
+ if (fut_->has_value()) {
+ return fut_->get();
+ }
+ else {
+ return v;
+ }
+ }
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template<typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
+ then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
+ template<typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
+ then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
+ #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ template<typename Ex, typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
+ then(Ex& ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
+ #endif
+
+ template <typename R2>
+ inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
+ fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION
+ template <typename R2>
+ inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
+ fallback_to(R2 const& v); // EXTENSION
+
+#endif
+
};
BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
+ template <typename R2>
+ class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> >
+ {
+ typedef BOOST_THREAD_FUTURE<R2> R;
+
+ private:
+ typedef detail::basic_future<R> base_type;
+ typedef typename base_type::future_ptr future_ptr;
+
+ friend class shared_future<R>;
+ friend class promise<R>;
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template <typename, typename, typename>
+ friend struct detail::future_async_continuation_shared_state;
+ template <typename, typename, typename>
+ friend struct detail::future_deferred_continuation_shared_state;
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+ #endif
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ template<typename F, typename Rp>
+ friend struct detail::future_unwrap_shared_state;
+ template <class F, class Rp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
+#endif
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ template <class> friend class packaged_task; // todo check if this works in windows
+ #else
+ friend class packaged_task<R>;
+ #endif
+ friend class detail::future_waiter;
+
+ template <class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
+
+ template <class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
+
+ typedef typename base_type::move_dest_type move_dest_type;
+
+ BOOST_THREAD_FUTURE(future_ptr a_future):
+ base_type(a_future)
+ {
+ }
+
+ public:
+ BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
+ typedef future_state::state state;
+ typedef R value_type; // EXTENSION
+
+ BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
+ //BOOST_CONSTEXPR
+ BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
+ base_type(ex) {}
+
+ ~BOOST_THREAD_FUTURE() {}
+
+ BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
+ base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
+ {
+ }
+
+ BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
+ {
+ this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
+ return *this;
+ }
+
+ shared_future<R> share()
+ {
+ return shared_future<R>(::boost::move(*this));
+ }
+
+ void swap(BOOST_THREAD_FUTURE& other)
+ {
+ static_cast<base_type*>(this)->swap(other);
+ }
+
+ // todo this function must be private and friendship provided to the internal users.
+ void set_async()
+ {
+ this->future_->set_async();
+ }
+ // todo this function must be private and friendship provided to the internal users.
+ void set_deferred()
+ {
+ this->future_->set_deferred();
+ }
+ bool run_if_is_deferred() {
+ return this->future_->run_if_is_deferred();
+ }
+ bool run_if_is_deferred_or_ready() {
+ return this->future_->run_if_is_deferred_or_ready();
+ }
+ // retrieving the value
+ move_dest_type get()
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ future_ptr fut_=this->future_;
+ #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
+ #endif
+ return fut_->get();
+ }
+ move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ this->future_->wait(false);
+ future_ptr fut_=this->future_;
+ #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
+ #endif
+ if (fut_->has_value()) return fut_->get();
+ else return boost::move(v);
+ }
+
+ move_dest_type get_or(R const& v) // EXTENSION
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ this->future_->wait(false);
+ future_ptr fut_=this->future_;
+ #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ this->future_.reset();
+ #endif
+ if (fut_->has_value()) return fut_->get();
+ else return v;
+ }
+
+
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template<typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
+ then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
+ template<typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
+ then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
+ #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ template<typename Ex, typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
+ then(Ex &ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
+ #endif
+ #endif
+
+ #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ inline
+ BOOST_THREAD_FUTURE<R2>
+ unwrap(); // EXTENSION
+ #endif
+
+ };
+
template <typename R>
- class shared_future
+ class shared_future : public detail::basic_future<R>
{
- typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
-
- future_ptr future_;
+ typedef detail::basic_future<R> base_type;
+ typedef typename base_type::future_ptr future_ptr;
friend class detail::future_waiter;
friend class promise<R>;
- friend class packaged_task<R>;
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template <typename, typename, typename>
+ friend struct detail::future_async_continuation_shared_state;
+ template <typename, typename, typename>
+ friend struct detail::future_deferred_continuation_shared_state;
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+#endif
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ template <class> friend class packaged_task;// todo check if this works in windows
+#else
+ friend class packaged_task<R>;
+#endif
shared_future(future_ptr a_future):
- future_(a_future)
+ base_type(a_future)
{}
public:
- BOOST_THREAD_MOVABLE(shared_future)
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_future)
+ typedef R value_type; // EXTENSION
shared_future(shared_future const& other):
- future_(other.future_)
+ base_type(other)
{}
typedef future_state::state state;
- shared_future()
+ BOOST_CONSTEXPR shared_future()
{}
-
+ //BOOST_CONSTEXPR
+ shared_future(exceptional_ptr const& ex):
+ base_type(ex) {}
~shared_future()
{}
- shared_future& operator=(shared_future const& other)
+ shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other)
{
- future_=other.future_;
+ shared_future(other).swap(*this);
return *this;
}
+
shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
- future_(BOOST_THREAD_RV(other).future_)
+ base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
{
BOOST_THREAD_RV(other).future_.reset();
}
- shared_future(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT :
- future_(BOOST_THREAD_RV(other).future_)
+ shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT :
+ base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
{
- BOOST_THREAD_RV(other).future_.reset();
}
+
shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
{
- future_.swap(BOOST_THREAD_RV(other).future_);
- BOOST_THREAD_RV(other).future_.reset();
+ base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
return *this;
}
- shared_future& operator=(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
+ shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
{
- future_.swap(BOOST_THREAD_RV(other).future_);
- BOOST_THREAD_RV(other).future_.reset();
+ base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
return *this;
}
void swap(shared_future& other) BOOST_NOEXCEPT
{
- future_.swap(other.future_);
+ static_cast<base_type*>(this)->swap(other);
+ }
+ bool run_if_is_deferred() {
+ return this->future_->run_if_is_deferred();
+ }
+ bool run_if_is_deferred_or_ready() {
+ return this->future_->run_if_is_deferred_or_ready();
}
-
// retrieving the value
- typename detail::future_object<R>::shared_future_get_result_type get()
+ typename detail::shared_state<R>::shared_future_get_result_type get()
{
- if(!future_)
+ if(!this->future_)
{
boost::throw_exception(future_uninitialized());
}
+ return this->future_->get_sh();
+ }
- return future_->get_sh();
+ template <typename R2>
+ typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
+ get_or(BOOST_THREAD_RV_REF(R2) v) // EXTENSION
+ {
+ if(!this->future_)
+ {
+ boost::throw_exception(future_uninitialized());
+ }
+ future_ptr fut_=this->future_;
+ fut_->wait();
+ if (fut_->has_value()) return fut_->get_sh();
+ else return boost::move(v);
}
- // functions to check state, and wait for ready
- state get_state() const BOOST_NOEXCEPT
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template<typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
+ then(BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
+ template<typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
+ then(launch policy, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
+ #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ template<typename Ex, typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
+ then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
+ #endif
+#endif
+
+ };
+
+ BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
+
+ namespace detail
+ {
+ /// Copy construction from a shared_future
+ template <typename R>
+ inline basic_future<R>::basic_future(const shared_future<R>& other) BOOST_NOEXCEPT
+ : future_(other.future_)
+ {
+ }
+ }
+
+ template <typename R>
+ class promise
+ {
+ typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
+
+ typedef typename detail::shared_state<R>::source_reference_type source_reference_type;
+ typedef typename detail::shared_state<R>::rvalue_source_type rvalue_source_type;
+ typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
+ typedef typename detail::shared_state<R>::shared_future_get_result_type shared_future_get_result_type;
+
+ future_ptr future_;
+ bool future_obtained;
+
+ void lazy_init()
{
- if(!future_)
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
+#include <boost/detail/atomic_undef_macros.hpp>
+ if(!atomic_load(&future_))
{
- return future_state::uninitialized;
+ future_ptr blank;
+ atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
}
- return future_->get_state();
+#include <boost/detail/atomic_redef_macros.hpp>
+#endif
}
- bool valid() const BOOST_NOEXCEPT
+ public:
+ BOOST_THREAD_MOVABLE_ONLY(promise)
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+ template <class Allocator>
+ promise(boost::allocator_arg_t, Allocator a)
{
- return future_ != 0;
+ typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2;
+ A2 a2(a);
+ typedef thread_detail::allocator_destructor<A2> D;
+
+ future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) );
+ future_obtained = false;
}
+#endif
+ promise():
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
+ future_(),
+#else
+ future_(new detail::shared_state<R>()),
+#endif
+ future_obtained(false)
+ {}
- bool is_ready() const BOOST_NOEXCEPT
+ ~promise()
{
- return get_state()==future_state::ready;
+ if(future_)
+ {
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
+
+ if(!future_->done && !future_->is_constructed)
+ {
+ future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
+ }
+ }
}
- bool has_exception() const BOOST_NOEXCEPT
+ // Assignment
+ promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
+ future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
{
- return future_ && future_->has_exception();
+ BOOST_THREAD_RV(rhs).future_.reset();
+ BOOST_THREAD_RV(rhs).future_obtained=false;
+ }
+ promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
+ {
+ future_=BOOST_THREAD_RV(rhs).future_;
+ future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
+ BOOST_THREAD_RV(rhs).future_.reset();
+ BOOST_THREAD_RV(rhs).future_obtained=false;
+ return *this;
}
- bool has_value() const BOOST_NOEXCEPT
+ void swap(promise& other)
{
- return future_ && future_->has_value();
+ future_.swap(other.future_);
+ std::swap(future_obtained,other.future_obtained);
}
- void wait() const
+ // Result retrieval
+ BOOST_THREAD_FUTURE<R> get_future()
{
- if(!future_)
+ lazy_init();
+ if (future_.get()==0)
{
- boost::throw_exception(future_uninitialized());
+ boost::throw_exception(promise_moved());
}
- future_->wait(false);
+ if (future_obtained)
+ {
+ boost::throw_exception(future_already_retrieved());
+ }
+ future_obtained=true;
+ return BOOST_THREAD_FUTURE<R>(future_);
}
- template<typename Duration>
- bool timed_wait(Duration const& rel_time) const
+#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class TR>
+ typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value(TR const & r)
{
- return timed_wait_until(boost::get_system_time()+rel_time);
+ lazy_init();
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
+ if(future_->done)
+ {
+ boost::throw_exception(promise_already_satisfied());
+ }
+ future_->mark_finished_with_result_internal(r, lock);
}
-
- bool timed_wait_until(boost::system_time const& abs_time) const
+#else
+ void set_value(source_reference_type r)
{
- if(!future_)
+ lazy_init();
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
+ if(future_->done)
{
- boost::throw_exception(future_uninitialized());
+ boost::throw_exception(promise_already_satisfied());
}
- return future_->timed_wait_until(abs_time);
+ future_->mark_finished_with_result_internal(r, lock);
}
-#ifdef BOOST_THREAD_USES_CHRONO
+#endif
- template <class Rep, class Period>
- future_status
- wait_for(const chrono::duration<Rep, Period>& rel_time) const
+ void set_value(rvalue_source_type r)
{
- return wait_until(chrono::steady_clock::now() + rel_time);
-
+ lazy_init();
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
+ if(future_->done)
+ {
+ boost::throw_exception(promise_already_satisfied());
+ }
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ future_->mark_finished_with_result_internal(boost::move(r), lock);
+#else
+ future_->mark_finished_with_result_internal(static_cast<rvalue_source_type>(r), lock);
+#endif
}
- template <class Clock, class Duration>
- future_status
- wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
+ void set_exception(boost::exception_ptr p)
{
- if(!future_)
+ lazy_init();
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
+ if(future_->done)
+ {
+ boost::throw_exception(promise_already_satisfied());
+ }
+ future_->mark_exceptional_finish_internal(p, lock);
+ }
+ template <typename E>
+ void set_exception(E ex)
+ {
+ set_exception(boost::copy_exception(ex));
+ }
+ // setting the result with deferred notification
+#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class TR>
+ typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value_at_thread_exit(TR const& r)
+ {
+ if (future_.get()==0)
{
- boost::throw_exception(future_uninitialized());
+ boost::throw_exception(promise_moved());
}
- return future_->wait_until(abs_time);
+ future_->set_value_at_thread_exit(r);
+ }
+#else
+ void set_value_at_thread_exit(source_reference_type r)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_value_at_thread_exit(r);
}
#endif
- };
+ void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_value_at_thread_exit(boost::move(r));
+ }
+ void set_exception_at_thread_exit(exception_ptr e)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_exception_at_thread_exit(e);
+ }
+ template <typename E>
+ void set_exception_at_thread_exit(E ex)
+ {
+ set_exception_at_thread_exit(boost::copy_exception(ex));
+ }
- BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ lazy_init();
+ future_->set_wait_callback(f,this);
+ }
+
+ };
template <typename R>
- class promise
+ class promise<R&>
{
- typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+ typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr;
future_ptr future_;
bool future_obtained;
void lazy_init()
{
-#if defined BOOST_THREAD_PROMISE_LAZY
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
+#include <boost/detail/atomic_undef_macros.hpp>
if(!atomic_load(&future_))
{
future_ptr blank;
- atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R>));
+ atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
}
+#include <boost/detail/atomic_redef_macros.hpp>
#endif
}
@@ -1117,19 +2171,19 @@ namespace boost
template <class Allocator>
promise(boost::allocator_arg_t, Allocator a)
{
- typedef typename Allocator::template rebind<detail::future_object<R> >::other A2;
+ typedef typename Allocator::template rebind<detail::shared_state<R&> >::other A2;
A2 a2(a);
typedef thread_detail::allocator_destructor<A2> D;
- future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<R>(), D(a2, 1) );
+ future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) );
future_obtained = false;
}
#endif
promise():
-#if defined BOOST_THREAD_PROMISE_LAZY
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
future_(),
#else
- future_(new detail::future_object<R>()),
+ future_(new detail::shared_state<R&>()),
#endif
future_obtained(false)
{}
@@ -1138,11 +2192,11 @@ namespace boost
{
if(future_)
{
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
- if(!future_->done)
+ if(!future_->done && !future_->is_constructed)
{
- future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
}
}
}
@@ -1170,7 +2224,7 @@ namespace boost
}
// Result retrieval
- BOOST_THREAD_FUTURE<R> get_future()
+ BOOST_THREAD_FUTURE<R&> get_future()
{
lazy_init();
if (future_.get()==0)
@@ -1182,41 +2236,58 @@ namespace boost
boost::throw_exception(future_already_retrieved());
}
future_obtained=true;
- return BOOST_THREAD_FUTURE<R>(future_);
+ return BOOST_THREAD_FUTURE<R&>(future_);
}
- void set_value(typename detail::future_traits<R>::source_reference_type r)
+ void set_value(R& r)
{
lazy_init();
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
if(future_->done)
{
boost::throw_exception(promise_already_satisfied());
}
- future_->mark_finished_with_result_internal(r);
+ future_->mark_finished_with_result_internal(r, lock);
}
-// void set_value(R && r);
- void set_value(typename detail::future_traits<R>::rvalue_source_type r)
+ void set_exception(boost::exception_ptr p)
{
lazy_init();
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
if(future_->done)
{
boost::throw_exception(promise_already_satisfied());
}
- future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r));
+ future_->mark_exceptional_finish_internal(p, lock);
+ }
+ template <typename E>
+ void set_exception(E ex)
+ {
+ set_exception(boost::copy_exception(ex));
}
- void set_exception(boost::exception_ptr p)
+ // setting the result with deferred notification
+ void set_value_at_thread_exit(R& r)
{
- lazy_init();
- boost::lock_guard<boost::mutex> lock(future_->mutex);
- if(future_->done)
- {
- boost::throw_exception(promise_already_satisfied());
- }
- future_->mark_exceptional_finish_internal(p);
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_value_at_thread_exit(r);
+ }
+
+ void set_exception_at_thread_exit(exception_ptr e)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_exception_at_thread_exit(e);
+ }
+ template <typename E>
+ void set_exception_at_thread_exit(E ex)
+ {
+ set_exception_at_thread_exit(boost::copy_exception(ex));
}
template<typename F>
@@ -1225,24 +2296,23 @@ namespace boost
lazy_init();
future_->set_wait_callback(f,this);
}
-
};
template <>
class promise<void>
{
- typedef boost::shared_ptr<detail::future_object<void> > future_ptr;
+ typedef boost::shared_ptr<detail::shared_state<void> > future_ptr;
future_ptr future_;
bool future_obtained;
void lazy_init()
{
-#if defined BOOST_THREAD_PROMISE_LAZY
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
if(!atomic_load(&future_))
{
future_ptr blank;
- atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<void>));
+ atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>));
}
#endif
}
@@ -1253,19 +2323,19 @@ namespace boost
template <class Allocator>
promise(boost::allocator_arg_t, Allocator a)
{
- typedef typename Allocator::template rebind<detail::future_object<void> >::other A2;
+ typedef typename Allocator::template rebind<detail::shared_state<void> >::other A2;
A2 a2(a);
typedef thread_detail::allocator_destructor<A2> D;
- future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<void>(), D(a2, 1) );
+ future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) );
future_obtained = false;
}
#endif
promise():
-#if defined BOOST_THREAD_PROMISE_LAZY
+#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
future_(),
#else
- future_(new detail::future_object<void>),
+ future_(new detail::shared_state<void>),
#endif
future_obtained(false)
{}
@@ -1274,11 +2344,11 @@ namespace boost
{
if(future_)
{
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
- if(!future_->done)
+ if(!future_->done && !future_->is_constructed)
{
- future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
}
}
}
@@ -1321,29 +2391,59 @@ namespace boost
boost::throw_exception(future_already_retrieved());
}
future_obtained=true;
+ //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<void>(future_));
return BOOST_THREAD_FUTURE<void>(future_);
}
void set_value()
{
lazy_init();
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
if(future_->done)
{
boost::throw_exception(promise_already_satisfied());
}
- future_->mark_finished_with_result_internal();
+ future_->mark_finished_with_result_internal(lock);
}
void set_exception(boost::exception_ptr p)
{
lazy_init();
- boost::lock_guard<boost::mutex> lock(future_->mutex);
+ boost::unique_lock<boost::mutex> lock(future_->mutex);
if(future_->done)
{
boost::throw_exception(promise_already_satisfied());
}
- future_->mark_exceptional_finish_internal(p);
+ future_->mark_exceptional_finish_internal(p,lock);
+ }
+ template <typename E>
+ void set_exception(E ex)
+ {
+ set_exception(boost::copy_exception(ex));
+ }
+
+ // setting the result with deferred notification
+ void set_value_at_thread_exit()
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_value_at_thread_exit();
+ }
+
+ void set_exception_at_thread_exit(exception_ptr e)
+ {
+ if (future_.get()==0)
+ {
+ boost::throw_exception(promise_moved());
+ }
+ future_->set_exception_at_thread_exit(e);
+ }
+ template <typename E>
+ void set_exception_at_thread_exit(E ex)
+ {
+ set_exception_at_thread_exit(boost::copy_exception(ex));
}
template<typename F>
@@ -1354,28 +2454,50 @@ namespace boost
}
};
-
+}
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
- namespace container
+namespace boost { namespace container {
+ template <class R, class Alloc>
+ struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
{
- template <class R, class Alloc>
- struct uses_allocator<promise<R> , Alloc> : true_type
- {
- };
- }
+ };
+}}
+#if ! defined BOOST_NO_CXX11_ALLOCATOR
+namespace std {
+ template <class R, class Alloc>
+ struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
+ {
+ };
+}
#endif
+#endif
+
+namespace boost
+{
BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
namespace detail
{
- template<typename R>
- struct task_base:
- detail::future_object<R>
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ template<typename R>
+ struct task_base_shared_state;
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template<typename R, typename ...ArgTypes>
+ struct task_base_shared_state<R(ArgTypes...)>:
+#else
+ template<typename R>
+ struct task_base_shared_state<R()>:
+#endif
+#else
+ template<typename R>
+ struct task_base_shared_state:
+#endif
+ detail::shared_state<R>
{
bool started;
- task_base():
+ task_base_shared_state():
started(false)
{}
@@ -1383,7 +2505,13 @@ namespace boost
{
started=false;
}
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
+ void run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+#else
+ virtual void do_run()=0;
void run()
+#endif
{
{
boost::lock_guard<boost::mutex> lk(this->mutex);
@@ -1393,54 +2521,212 @@ namespace boost
}
started=true;
}
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ do_run(boost::move(args)...);
+#else
do_run();
+#endif
+ }
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
+ void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+#else
+ virtual void do_apply()=0;
+ void apply()
+#endif
+ {
+ {
+ boost::lock_guard<boost::mutex> lk(this->mutex);
+ if(started)
+ {
+ boost::throw_exception(task_already_started());
+ }
+ started=true;
+ }
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ do_apply(boost::move(args)...);
+#else
+ do_apply();
+#endif
}
void owner_destroyed()
{
- boost::lock_guard<boost::mutex> lk(this->mutex);
+ boost::unique_lock<boost::mutex> lk(this->mutex);
if(!started)
{
started=true;
- this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()));
+ this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
}
}
-
-
- virtual void do_run()=0;
};
-
- template<typename R,typename F>
- struct task_object:
- task_base<R>
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ template<typename F, typename R>
+ struct task_shared_state;
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template<typename F, typename R, typename ...ArgTypes>
+ struct task_shared_state<F, R(ArgTypes...)>:
+ task_base_shared_state<R(ArgTypes...)>
+#else
+ template<typename F, typename R>
+ struct task_shared_state<F, R()>:
+ task_base_shared_state<R()>
+#endif
+#else
+ template<typename F, typename R>
+ struct task_shared_state:
+ task_base_shared_state<R>
+#endif
{
private:
- task_object(task_object&);
+ task_shared_state(task_shared_state&);
public:
F f;
- task_object(F const& f_):
+ task_shared_state(F const& f_):
f(f_)
{}
-#ifndef BOOST_NO_RVALUE_REFERENCES
- task_object(BOOST_THREAD_RV_REF(F) f_):
- f(boost::forward<F>(f_))
+ task_shared_state(BOOST_THREAD_RV_REF(F) f_):
+ f(boost::move(f_))
{}
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f(boost::move(args)...));
+ }
+#else
+ void do_apply()
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f());
+ }
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->set_interrupted_at_thread_exit();
+ }
+#endif
+ catch(...)
+ {
+ this->set_exception_at_thread_exit(current_exception());
+ }
+ }
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ this->mark_finished_with_result(f(boost::move(args)...));
+ }
+#else
+ void do_run()
+ {
+ try
+ {
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ R res((f()));
+ this->mark_finished_with_result(boost::move(res));
#else
- task_object(BOOST_THREAD_RV_REF(F) f_):
+ this->mark_finished_with_result(f());
+#endif
+ }
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->mark_interrupted_finish();
+ }
+#endif
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+ };
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template<typename F, typename R, typename ...ArgTypes>
+ struct task_shared_state<F, R&(ArgTypes...)>:
+ task_base_shared_state<R&(ArgTypes...)>
+#else
+ template<typename F, typename R>
+ struct task_shared_state<F, R&()>:
+ task_base_shared_state<R&()>
+#endif
+#else
+ template<typename F, typename R>
+ struct task_shared_state<F,R&>:
+ task_base_shared_state<R&>
+#endif
+ {
+ private:
+ task_shared_state(task_shared_state&);
+ public:
+ F f;
+ task_shared_state(F const& f_):
+ f(f_)
+ {}
+ task_shared_state(BOOST_THREAD_RV_REF(F) f_):
f(boost::move(f_))
{}
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f(boost::move(args)...));
+ }
+#else
+ void do_apply()
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f());
+ }
#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->set_interrupted_at_thread_exit();
+ }
+#endif
+ catch(...)
+ {
+ this->set_exception_at_thread_exit(current_exception());
+ }
+ }
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ this->mark_finished_with_result(f(boost::move(args)...));
+ }
+#else
void do_run()
{
try
{
- this->mark_finished_with_result(f());
+ R& res((f()));
+ this->mark_finished_with_result(res);
}
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->mark_interrupted_finish();
}
+#endif
catch(...)
{
this->mark_exceptional_finish();
@@ -1448,38 +2734,258 @@ namespace boost
}
};
+#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template<typename R, typename ...ArgTypes>
+ struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>:
+ task_base_shared_state<R(ArgTypes...)>
+#else
+ template<typename R>
+ struct task_shared_state<R (*)(), R()>:
+ task_base_shared_state<R()>
+#endif
+#else
+ template<typename R>
+ struct task_shared_state<R (*)(), R> :
+ task_base_shared_state<R>
+#endif
+ {
+ private:
+ task_shared_state(task_shared_state&);
+ public:
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ R (*f)(BOOST_THREAD_RV_REF(ArgTypes) ... );
+ task_shared_state(R (*f_)(BOOST_THREAD_RV_REF(ArgTypes) ... )):
+ f(f_)
+ {}
+#else
+ R (*f)();
+ task_shared_state(R (*f_)()):
+ f(f_)
+ {}
+#endif
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f(boost::move(args)...));
+ }
+#else
+ void do_apply()
+ {
+ try
+ {
+ R r((f()));
+ this->set_value_at_thread_exit(boost::move(r));
+ }
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->set_interrupted_at_thread_exit();
+ }
+#endif
+ catch(...)
+ {
+ this->set_exception_at_thread_exit(current_exception());
+ }
+ }
+
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ this->mark_finished_with_result(f(boost::move(args)...));
+ }
+#else
+ void do_run()
+ {
+ try
+ {
+ R res((f()));
+ this->mark_finished_with_result(boost::move(res));
+ }
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->mark_interrupted_finish();
+ }
+#endif
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+ };
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template<typename R, typename ...ArgTypes>
+ struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>:
+ task_base_shared_state<R&(ArgTypes...)>
+#else
+ template<typename R>
+ struct task_shared_state<R& (*)(), R&()>:
+ task_base_shared_state<R&()>
+#endif
+#else
+ template<typename R>
+ struct task_shared_state<R& (*)(), R&> :
+ task_base_shared_state<R&>
+#endif
+ {
+ private:
+ task_shared_state(task_shared_state&);
+ public:
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ R& (*f)(BOOST_THREAD_RV_REF(ArgTypes) ... );
+ task_shared_state(R& (*f_)(BOOST_THREAD_RV_REF(ArgTypes) ... )):
+ f(f_)
+ {}
+#else
+ R& (*f)();
+ task_shared_state(R& (*f_)()):
+ f(f_)
+ {}
+#endif
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f(boost::move(args)...));
+ }
+#else
+ void do_apply()
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f());
+ }
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->set_interrupted_at_thread_exit();
+ }
+#endif
+ catch(...)
+ {
+ this->set_exception_at_thread_exit(current_exception());
+ }
+ }
+
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ this->mark_finished_with_result(f(boost::move(args)...));
+ }
+#else
+ void do_run()
+ {
+ try
+ {
+ this->mark_finished_with_result(f());
+ }
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->mark_interrupted_finish();
+ }
+#endif
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+ };
+#endif
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template<typename F, typename ...ArgTypes>
+ struct task_shared_state<F, void(ArgTypes...)>:
+ task_base_shared_state<void(ArgTypes...)>
+#else
template<typename F>
- struct task_object<void,F>:
- task_base<void>
+ struct task_shared_state<F, void()>:
+ task_base_shared_state<void()>
+#endif
+#else
+ template<typename F>
+ struct task_shared_state<F,void>:
+ task_base_shared_state<void>
+#endif
{
private:
- task_object(task_object&);
+ task_shared_state(task_shared_state&);
public:
F f;
- task_object(F const& f_):
+ task_shared_state(F const& f_):
f(f_)
{}
-#ifndef BOOST_NO_RVALUE_REFERENCES
- task_object(BOOST_THREAD_RV_REF(F) f_):
- f(boost::forward<F>(f_))
- {}
-#else
- task_object(BOOST_THREAD_RV_REF(F) f_):
+ task_shared_state(BOOST_THREAD_RV_REF(F) f_):
f(boost::move(f_))
{}
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ f(boost::move(args)...);
+#else
+ void do_apply()
+ {
+ try
+ {
+ f();
#endif
+ this->set_value_at_thread_exit();
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->set_interrupted_at_thread_exit();
+ }
+#endif
+ catch(...)
+ {
+ this->set_exception_at_thread_exit(current_exception());
+ }
+ }
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ f(boost::move(args)...);
+#else
void do_run()
{
try
{
f();
+#endif
this->mark_finished_with_result();
}
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
{
this->mark_interrupted_finish();
}
+#endif
catch(...)
{
this->mark_exceptional_finish();
@@ -1487,14 +2993,109 @@ namespace boost
}
};
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template<typename ...ArgTypes>
+ struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>:
+ task_base_shared_state<void(ArgTypes...)>
+#else
+ template<>
+ struct task_shared_state<void (*)(), void()>:
+ task_base_shared_state<void()>
+#endif
+#else
+ template<>
+ struct task_shared_state<void (*)(),void>:
+ task_base_shared_state<void>
+#endif
+ {
+ private:
+ task_shared_state(task_shared_state&);
+ public:
+ void (*f)();
+ task_shared_state(void (*f_)()):
+ f(f_)
+ {}
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ f(boost::move(args)...);
+#else
+ void do_apply()
+ {
+ try
+ {
+ f();
+#endif
+ this->set_value_at_thread_exit();
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->set_interrupted_at_thread_exit();
+ }
+#endif
+ catch(...)
+ {
+ this->set_exception_at_thread_exit(current_exception());
+ }
+ }
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ f(boost::move(args)...);
+#else
+ void do_run()
+ {
+ try
+ {
+ f();
+#endif
+ this->mark_finished_with_result();
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->mark_interrupted_finish();
+ }
+#endif
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+ };
}
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template<typename R, typename ...ArgTypes>
+ class packaged_task<R(ArgTypes...)>
+ {
+ typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr;
+ boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task;
+ #else
+ template<typename R>
+ class packaged_task<R()>
+ {
+ typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr;
+ boost::shared_ptr<detail::task_base_shared_state<R()> > task;
+ #endif
+#else
template<typename R>
class packaged_task
{
- typedef boost::shared_ptr<detail::task_base<R> > task_ptr;
- boost::shared_ptr<detail::task_base<R> > task;
+ typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr;
+ boost::shared_ptr<detail::task_base_shared_state<R> > task;
+#endif
bool future_obtained;
+ struct dummy;
public:
typedef R result_type;
@@ -1505,198 +3106,2078 @@ namespace boost
{}
// construction and destruction
+#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
- explicit packaged_task(R(*f)()):
- task(new detail::task_object<R,R(*)()>(f)),future_obtained(false)
- {}
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args)
+ {
+ typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...);
+ typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
+ task= task_ptr(new task_shared_state_type(f, boost::move(args)...));
+ future_obtained=false;
+ }
+ #else
+ explicit packaged_task(R(*f)())
+ {
+ typedef R(*FR)();
+ typedef detail::task_shared_state<FR,R()> task_shared_state_type;
+ task= task_ptr(new task_shared_state_type(f));
+ future_obtained=false;
+ }
+ #endif
+#else
+ explicit packaged_task(R(*f)())
+ {
+ typedef R(*FR)();
+ typedef detail::task_shared_state<FR,R> task_shared_state_type;
+ task= task_ptr(new task_shared_state_type(f));
+ future_obtained=false;
+ }
+#endif
+#endif
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class F>
- explicit packaged_task(BOOST_THREAD_RV_REF(F) f):
- task(new detail::task_object<R,
- typename remove_cv<typename remove_reference<F>::type>::type
- >(boost::forward<F>(f))),future_obtained(false)
- {}
+ explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
+ , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
+ )
+ {
+ typedef typename decay<F>::type FR;
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
+ #else
+ typedef detail::task_shared_state<FR,R()> task_shared_state_type;
+ #endif
+#else
+ typedef detail::task_shared_state<FR,R> task_shared_state_type;
+#endif
+ task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
+ future_obtained = false;
+
+ }
+
#else
template <class F>
- explicit packaged_task(F const& f):
- task(new detail::task_object<R,F>(f)),future_obtained(false)
- {}
+ explicit packaged_task(F const& f
+ , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
+ )
+ {
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
+ #else
+ typedef detail::task_shared_state<F,R()> task_shared_state_type;
+ #endif
+#else
+ typedef detail::task_shared_state<F,R> task_shared_state_type;
+#endif
+ task = task_ptr(new task_shared_state_type(f));
+ future_obtained=false;
+ }
template <class F>
- explicit packaged_task(BOOST_THREAD_RV_REF(F) f):
- task(new detail::task_object<R,F>(boost::move(f))),future_obtained(false)
- {}
+ explicit packaged_task(BOOST_THREAD_RV_REF(F) f)
+ {
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
+ task = task_ptr(new task_shared_state_type(boost::move(f)));
+#else
+ typedef detail::task_shared_state<F,R()> task_shared_state_type;
+ task = task_ptr(new task_shared_state_type(boost::move(f)));
+#endif
+#else
+ typedef detail::task_shared_state<F,R> task_shared_state_type;
+ task = task_ptr(new task_shared_state_type(boost::move(f)));
+#endif
+ future_obtained=false;
+
+ }
#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
template <class Allocator>
packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
{
typedef R(*FR)();
- typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2;
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
+ #else
+ typedef detail::task_shared_state<FR,R()> task_shared_state_type;
+ #endif
+#else
+ typedef detail::task_shared_state<FR,R> task_shared_state_type;
+#endif
+ typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
A2 a2(a);
typedef thread_detail::allocator_destructor<A2> D;
- task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(f), D(a2, 1) );
+ task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
future_obtained = false;
}
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
template <class F, class Allocator>
- packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
+ packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
{
- typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
- typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2;
+ typedef typename decay<F>::type FR;
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
+ #else
+ typedef detail::task_shared_state<FR,R()> task_shared_state_type;
+ #endif
+#else
+ typedef detail::task_shared_state<FR,R> task_shared_state_type;
+#endif
+ typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
A2 a2(a);
typedef thread_detail::allocator_destructor<A2> D;
- task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(boost::forward<F>(f)), D(a2, 1) );
+ task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
future_obtained = false;
}
-#else
+#else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
template <class F, class Allocator>
packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
{
- typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2;
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
+ #else
+ typedef detail::task_shared_state<F,R()> task_shared_state_type;
+ #endif
+#else
+ typedef detail::task_shared_state<F,R> task_shared_state_type;
+#endif
+ typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
A2 a2(a);
typedef thread_detail::allocator_destructor<A2> D;
- task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(f), D(a2, 1) );
+ task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
future_obtained = false;
}
template <class F, class Allocator>
packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
{
- typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2;
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
+ #else
+ typedef detail::task_shared_state<F,R()> task_shared_state_type;
+ #endif
+#else
+ typedef detail::task_shared_state<F,R> task_shared_state_type;
+#endif
+ typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
A2 a2(a);
typedef thread_detail::allocator_destructor<A2> D;
- task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(boost::move(f)), D(a2, 1) );
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) );
+#else
+ task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) );
+#endif
future_obtained = false;
}
-#endif //BOOST_NO_RVALUE_REFERENCES
+
+#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
#endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
- ~packaged_task()
- {
- if(task)
- {
+ ~packaged_task() {
+ if(task) {
task->owner_destroyed();
}
}
// assignment
- packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT :
- future_obtained(BOOST_THREAD_RV(other).future_obtained)
- {
+ packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
+ : future_obtained(BOOST_THREAD_RV(other).future_obtained) {
task.swap(BOOST_THREAD_RV(other).task);
BOOST_THREAD_RV(other).future_obtained=false;
}
- packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
- {
+ packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT {
+
+#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ packaged_task temp(boost::move(other));
+#else
packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other));
+#endif
swap(temp);
return *this;
}
- void reset()
- {
+ void reset() {
if (!valid())
throw future_error(system::make_error_code(future_errc::no_state));
task->reset();
future_obtained=false;
}
- void swap(packaged_task& other) BOOST_NOEXCEPT
- {
+ void swap(packaged_task& other) BOOST_NOEXCEPT {
task.swap(other.task);
std::swap(future_obtained,other.future_obtained);
}
- bool valid() const BOOST_NOEXCEPT
- {
+ bool valid() const BOOST_NOEXCEPT {
return task.get()!=0;
}
// result retrieval
- BOOST_THREAD_FUTURE<R> get_future()
- {
- if(!task)
- {
+ BOOST_THREAD_FUTURE<R> get_future() {
+ if(!task) {
boost::throw_exception(task_moved());
- }
- else if(!future_obtained)
- {
+ } else if(!future_obtained) {
future_obtained=true;
return BOOST_THREAD_FUTURE<R>(task);
- }
- else
- {
+ } else {
boost::throw_exception(future_already_retrieved());
}
- return BOOST_THREAD_FUTURE<R>();
-
}
-
// execution
- void operator()()
- {
- if(!task)
- {
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args) {
+ if(!task) {
+ boost::throw_exception(task_moved());
+ }
+ task->run(boost::move(args)...);
+ }
+ void make_ready_at_thread_exit(ArgTypes... args) {
+ if(!task) {
+ boost::throw_exception(task_moved());
+ }
+ if (task->has_value()) {
+ boost::throw_exception(promise_already_satisfied());
+ }
+ task->apply(boost::move(args)...);
+ }
+#else
+ void operator()() {
+ if(!task) {
boost::throw_exception(task_moved());
}
task->run();
}
-
+ void make_ready_at_thread_exit() {
+ if(!task) {
+ boost::throw_exception(task_moved());
+ }
+ if (task->has_value()) boost::throw_exception(promise_already_satisfied());
+ task->apply();
+ }
+#endif
template<typename F>
- void set_wait_callback(F f)
- {
+ void set_wait_callback(F f) {
task->set_wait_callback(f,this);
}
+ };
+}
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+namespace boost { namespace container {
+ template <class R, class Alloc>
+ struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
+ {};
+}}
+#if ! defined BOOST_NO_CXX11_ALLOCATOR
+namespace std {
+ template <class R, class Alloc>
+ struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
+ {};
+}
+#endif
+#endif
+
+namespace boost
+{
+ BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
+
+namespace detail
+{
+ ////////////////////////////////
+ // make_future_deferred_shared_state
+ ////////////////////////////////
+ template <class Rp, class Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
+ shared_ptr<future_deferred_shared_state<Rp, Fp> >
+ h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+
+ ////////////////////////////////
+ // make_future_async_shared_state
+ ////////////////////////////////
+ template <class Rp, class Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
+ shared_ptr<future_async_shared_state<Rp, Fp> >
+ h(new future_async_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+}
+
+ ////////////////////////////////
+ // template <class F, class... ArgTypes>
+ // future<R> async(launch policy, F&&, ArgTypes&&...);
+ ////////////////////////////////
+
+#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template <class R, class... ArgTypes>
+ BOOST_THREAD_FUTURE<R>
+ async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
+ typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
+ typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
+ typedef typename BF::result_type Rp;
+
+ if (underlying_cast<int>(policy) & int(launch::async)) {
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
+ BF(
+ f
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ )
+ ));
+ } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
+ BF(
+ f
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ )
+ ));
+ } else {
+ std::terminate();
+ BOOST_THREAD_FUTURE<R> ret;
+ return ::boost::move(ret);
+ }
+ }
+
+#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+
+ template <class R>
+ BOOST_THREAD_FUTURE<R>
+ async(launch policy, R(*f)()) {
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ typedef packaged_task<R()> packaged_task_type;
+ #else
+ typedef packaged_task<R> packaged_task_type;
+ #endif
+
+ if (underlying_cast<int>(policy) & int(launch::async)) {
+ packaged_task_type pt( f );
+ BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
+ ret.set_async();
+ boost::thread( boost::move(pt) ).detach();
+ return ::boost::move(ret);
+ } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
+ std::terminate();
+ BOOST_THREAD_FUTURE<R> ret;
+ return ::boost::move(ret);
+ } else {
+ std::terminate();
+ BOOST_THREAD_FUTURE<R> ret;
+ return ::boost::move(ret);
+ }
+ }
+#endif
+#endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
+
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+
+ template <class F, class ...ArgTypes>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
+ typename decay<ArgTypes>::type...
+ )>::type>
+ async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
+ typedef typename boost::result_of<typename decay<F>::type(
+ typename decay<ArgTypes>::type...
+ )>::type R;
+ typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
+ typedef typename BF::result_type Rp;
+
+ if (underlying_cast<int>(policy) & int(launch::async)) {
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ )
+ ));
+ } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ )
+ ));
+ } else {
+ std::terminate();
+ BOOST_THREAD_FUTURE<R> ret;
+ return ::boost::move(ret);
+ }
+ }
+
+#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+
+ template <class F>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
+ async(launch policy, BOOST_THREAD_FWD_REF(F) f) {
+ typedef typename boost::result_of<typename decay<F>::type()>::type R;
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ typedef packaged_task<R()> packaged_task_type;
+#else // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+ typedef packaged_task<R> packaged_task_type;
+#endif // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
+
+ if (underlying_cast<int>(policy) & int(launch::async)) {
+ packaged_task_type pt( boost::forward<F>(f) );
+ BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+ ret.set_async();
+ boost::thread( boost::move(pt) ).detach();
+ return ::boost::move(ret);
+ } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
+ std::terminate();
+ BOOST_THREAD_FUTURE<R> ret;
+ return ::boost::move(ret);
+ // return boost::detail::make_future_deferred_shared_state<Rp>(
+ // BF(
+ // thread_detail::decay_copy(boost::forward<F>(f))
+ // )
+ // );
+ } else {
+ std::terminate();
+ BOOST_THREAD_FUTURE<R> ret;
+ return ::boost::move(ret);
+ }
+ }
+#endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+namespace detail {
+ /////////////////////////
+ /// shared_state_nullary_task
+ /////////////////////////
+ template<typename Rp, typename Fp>
+ struct shared_state_nullary_task
+ {
+ shared_state<Rp>* that;
+ Fp f_;
+ public:
+ shared_state_nullary_task(shared_state<Rp>* st, BOOST_THREAD_FWD_REF(Fp) f)
+ : that(st), f_(boost::move(f))
+ {};
+#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
+ shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
+ : that(x.that), f_(x.f_)
+ {}
+ shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
+ {
+ if (this != &x) {
+ that=x.that;
+ f_=x.f_;
+ }
+ return *this;
+ }
+ // move
+ shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
+ : that(x.that), f_(boost::move(x.f_))
+ {
+ x.that=0;
+ }
+ shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
+ {
+ if (this != &x) {
+ that=x.that;
+ f_=boost::move(x.f_);
+ x.that=0;
+ }
+ return *this;
+ }
+#endif
+ void operator()() {
+ try {
+ that->mark_finished_with_result(f_());
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
};
-#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
- namespace container
+ template<typename Fp>
+ struct shared_state_nullary_task<void, Fp>
+ {
+ shared_state<void>* that;
+ Fp f_;
+ public:
+ shared_state_nullary_task(shared_state<void>* st, BOOST_THREAD_FWD_REF(Fp) f)
+ : that(st), f_(boost::move(f))
+ {};
+#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
+ shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
+ : that(x.that), f_(x.f_)
+ {}
+ shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
+ {
+ if (this != &x) {
+ that=x.that;
+ f_=x.f_;
+ }
+ return *this;
+ }
+ // move
+ shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT
+ : that(x.that), f_(boost::move(x.f_))
+ {
+ x.that=0;
+ }
+ shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT {
+ if (this != &x) {
+ that=x.that;
+ f_=boost::move(x.f_);
+ x.that=0;
+ }
+ return *this;
+ }
+#endif
+ void operator()() {
+ try {
+ f_();
+ that->mark_finished_with_result();
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+ };
+
+ template<typename Rp, typename Fp>
+ struct shared_state_nullary_task<Rp&, Fp>
{
- template <class R, class Alloc>
- struct uses_allocator<packaged_task<R>, Alloc>
- : public true_type {};
+ shared_state<Rp&>* that;
+ Fp f_;
+ public:
+ shared_state_nullary_task(shared_state<Rp&>* st, BOOST_THREAD_FWD_REF(Fp) f)
+ : that(st), f_(boost::move(f))
+ {}
+#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
+ shared_state_nullary_task(shared_state_nullary_task const& x) BOOST_NOEXCEPT
+ : that(x.that), f_(x.f_) {}
+
+ shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT {
+ if (this != &x){
+ that=x.that;
+ f_=x.f_;
+ }
+ return *this;
+ }
+ // move
+ shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT
+ : that(x.that), f_(boost::move(x.f_))
+ {
+ x.that=0;
+ }
+ shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT {
+ if (this != &x) {
+ that=x.that;
+ f_=boost::move(x.f_);
+ x.that=0;
+ }
+ return *this;
+ }
+#endif
+ void operator()() {
+ try {
+ that->mark_finished_with_result(f_());
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+ };
+
+ /////////////////////////
+ /// future_executor_shared_state_base
+ /////////////////////////
+ template<typename Rp, typename Executor>
+ struct future_executor_shared_state: shared_state<Rp>
+ {
+ typedef shared_state<Rp> base_type;
+ protected:
+ public:
+ template<typename Fp>
+ future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) {
+ this->set_executor();
+ shared_state_nullary_task<Rp,Fp> t(this, boost::forward<Fp>(f));
+ ex.submit(boost::move(t));
+ }
+
+ ~future_executor_shared_state() {
+ this->wait(false);
+ }
+ };
+
+ ////////////////////////////////
+ // make_future_executor_shared_state
+ ////////////////////////////////
+ template <class Rp, class Fp, class Executor>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) {
+ shared_ptr<future_executor_shared_state<Rp, Executor> >
+ h(new future_executor_shared_state<Rp, Executor>(ex, boost::forward<Fp>(f)));
+ return BOOST_THREAD_FUTURE<Rp>(h);
}
+
+} // detail
+
+ ////////////////////////////////
+ // template <class Executor, class F, class... ArgTypes>
+ // future<R> async(Executor& ex, F&&, ArgTypes&&...);
+ ////////////////////////////////
+
+//#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
+
+#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+
+ template <class Executor, class R, class... ArgTypes>
+ BOOST_THREAD_FUTURE<R>
+ async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
+ typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
+ typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
+ typedef typename BF::result_type Rp;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ f
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ )
+ ));
+ }
+#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+
+ template <class Executor, class F, class ...ArgTypes>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
+ typename decay<ArgTypes>::type...
+ )>::type>
+ async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
+ typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
+ typedef typename BF::result_type Rp;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ )
+ ));
+ }
+
+#else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+
+ template <class Executor, class R>
+ BOOST_THREAD_FUTURE<R>
+ async(Executor& ex, R(*f)()) {
+ typedef R(*F)();
+ typedef detail::invoker<F> BF;
+ typedef typename BF::result_type Rp;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ f
+ )
+ ));
+ }
+
+ template <class Executor, class R, class A1>
+ BOOST_THREAD_FUTURE<R>
+ async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1) {
+ typedef R(*F)(BOOST_THREAD_FWD_REF(A1));
+ typedef detail::invoker<F, typename decay<A1>::type> BF;
+ typedef typename BF::result_type Rp;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ f
+ , thread_detail::decay_copy(boost::forward<A1>(a1))
+ )
+ ));
+ }
+#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+
+ template <class Executor, class F>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
+ async(Executor& ex, BOOST_THREAD_FWD_REF(F) f) {
+ typedef detail::invoker<typename decay<F>::type> BF;
+ typedef typename BF::result_type Rp;
+
+ return boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ )
+ );
+ }
+
+ template <class Executor, class F, class A1>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
+ typename decay<A1>::type
+ )>::type>
+ async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) {
+ typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type> BF;
+ typedef typename BF::result_type Rp;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ , thread_detail::decay_copy(boost::forward<A1>(a1))
+ )
+ ));
+ }
+
+ template <class Executor, class F, class A1, class A2>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
+ typename decay<A1>::type, typename decay<A2>::type
+ )>::type>
+ async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) {
+ typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type, typename decay<A2>::type> BF;
+ typedef typename BF::result_type Rp;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ , thread_detail::decay_copy(boost::forward<A1>(a1))
+ , thread_detail::decay_copy(boost::forward<A2>(a2))
+ )
+ ));
+ }
+
+#endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#endif
- BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
+ ////////////////////////////////
+ // template <class F, class... ArgTypes>
+ // future<R> async(F&&, ArgTypes&&...);
+ ////////////////////////////////
+
+#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+ #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template <class R, class... ArgTypes>
+ BOOST_THREAD_FUTURE<R>
+ async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
+ }
+ #else
+ template <class R>
+ BOOST_THREAD_FUTURE<R>
+ async(R(*f)()) {
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
+ }
+ #endif
+#endif
-// template <class F>
-// BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
-// async(launch policy, F f)
-// {
-// typedef typename boost::result_of<F()>::type R;
-// typedef BOOST_THREAD_FUTURE<R> future;
-// if (int(policy) & int(launch::async))
-// {
-// packaged_task<R> pt( f );
-//
-// BOOST_THREAD_FUTURE ret = pt.get_future();
-// boost::thread( boost::move(pt) ).detach();
-// return ::boost::move(ret);
-// }
-// else if (int(policy) & int(launch::deferred))
-// {
-// packaged_task<R> pt( f );
-//
-// BOOST_THREAD_FUTURE ret = pt.get_future();
-// return ::boost::move(ret);
-// }
-// }
-//
-// template <class F>
-// BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
-// async(F f)
-// {
-// return async(launch::any, f);
-// }
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template <class F, class ...ArgTypes>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
+ typename decay<ArgTypes>::type...
+ )>::type>
+ async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
+ }
+#else
+ template <class F>
+ BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
+ async(BOOST_THREAD_FWD_REF(F) f) {
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
+ }
+#endif
+
+ ////////////////////////////////
+ // make_future deprecated
+ ////////////////////////////////
+ template <typename T>
+ BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value) {
+ typedef typename decay<T>::type future_value_type;
+ promise<future_value_type> p;
+ p.set_value(boost::forward<future_value_type>(value));
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ }
+
+#if defined BOOST_THREAD_USES_MOVE
+ inline BOOST_THREAD_FUTURE<void> make_future() {
+ promise<void> p;
+ p.set_value();
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ }
+#endif
+
+ ////////////////////////////////
+ // make_ready_future
+ ////////////////////////////////
+ template <typename T>
+ BOOST_THREAD_FUTURE<typename decay<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) {
+ typedef typename decay<T>::type future_value_type;
+ promise<future_value_type> p;
+ p.set_value(boost::forward<future_value_type>(value));
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ }
+
+ template <typename T, typename T1>
+ BOOST_THREAD_FUTURE<T> make_ready_no_decay_future(T1 value) {
+ typedef T future_value_type;
+ promise<future_value_type> p;
+ p.set_value(value);
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ }
+
+#if defined BOOST_THREAD_USES_MOVE
+ inline BOOST_THREAD_FUTURE<void> make_ready_future() {
+ promise<void> p;
+ p.set_value();
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ }
+#endif
+
+ template <typename T>
+ BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) {
+ promise<T> p;
+ p.set_exception(ex);
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ }
+
+ template <typename T>
+ BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex) {
+ promise<T> p;
+ p.set_exception(ex);
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ }
+
+ template <typename T, typename E>
+ BOOST_THREAD_FUTURE<T> make_exceptional_future(E ex) {
+ promise<T> p;
+ p.set_exception(boost::copy_exception(ex));
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ }
+
+ template <typename T>
+ BOOST_THREAD_FUTURE<T> make_exceptional_future() {
+ promise<T> p;
+ p.set_exception(boost::current_exception());
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ }
+
+ template <typename T>
+ BOOST_THREAD_FUTURE<T> make_exceptional_future_if_invalid(BOOST_THREAD_FWD_REF(BOOST_THREAD_FUTURE<T>) fut) {
+ fut.set_exceptional_if_invalid();
+ return boost::move(fut);
+ }
+ template <typename T>
+ shared_future<T> make_exceptional_future_if_invalid(shared_future<T> fut) {
+ fut.set_exceptional_if_invalid();
+ return fut;
+ }
+
+#if 0
+ template<typename CLOSURE>
+ make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> {
+ typedef decltype(closure()) T;
+ promise<T> p;
+ try {
+ p.set_value(closure());
+ } catch(...) {
+ p.set_exception(std::current_exception());
+ }
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ }
+#endif
+
+ ////////////////////////////////
+ // make_shared_future deprecated
+ ////////////////////////////////
+ template <typename T>
+ shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) {
+ typedef typename decay<T>::type future_type;
+ promise<future_type> p;
+ p.set_value(boost::forward<T>(value));
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
+ }
+
+ inline shared_future<void> make_shared_future() {
+ promise<void> p;
+ return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
+ }
+
+ ////////////////////////////////
+ // detail::future_async_continuation_shared_state
+ ////////////////////////////////
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+namespace detail
+{
+
+ /////////////////////////
+ /// future_async_continuation_shared_state
+ /////////////////////////
+
+ template<typename F, typename Rp, typename Fp>
+ struct future_async_continuation_shared_state: future_async_shared_state_base<Rp>
+ {
+ F parent;
+ Fp continuation;
+
+ public:
+ future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
+ : parent(boost::move(f)),
+ continuation(boost::move(c)) {
+ }
+
+ void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ this->thr_ = thread(&future_async_continuation_shared_state::run, this);
+ }
+
+ static void run(future_async_continuation_shared_state* that) {
+ try {
+ that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+
+ ~future_async_continuation_shared_state() {
+ this->join();
+ }
+ };
+
+ template<typename F, typename Fp>
+ struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void>
+ {
+ F parent;
+ Fp continuation;
+
+ public:
+ future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
+ : parent(boost::move(f)),
+ continuation(boost::move(c)) {
+ }
+
+ void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ this->thr_ = thread(&future_async_continuation_shared_state::run, this);
+ }
+
+ static void run(future_async_continuation_shared_state* that) {
+ try {
+ that->continuation(boost::move(that->parent));
+ that->mark_finished_with_result();
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+
+ ~future_async_continuation_shared_state() {
+ this->join();
+ }
+ };
+
+ /////////////////////////
+ /// future_executor_continuation_shared_state
+ /////////////////////////
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+
+ template <typename Ex>
+ struct run_it {
+ Ex* that;
+
+ run_it(Ex* that) : that (that) {}
+ void operator()() { that->run(that); }
+ };
+
+ template<typename Ex, typename F, typename Rp, typename Fp>
+ struct future_executor_continuation_shared_state: shared_state<Rp>
+ {
+ Ex* ex;
+ F parent;
+ Fp continuation;
+
+ public:
+ future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
+ : ex(&ex), parent(boost::move(f)),
+ continuation(boost::move(c)) {
+ this->set_executor();
+ }
+
+ void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ run_it<future_executor_continuation_shared_state> fct(this);
+ ex->submit(fct);
+ }
+
+ static void run(future_executor_continuation_shared_state* that) {
+ try {
+ that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+
+ ~future_executor_continuation_shared_state() {
+ this->wait(false);
+ }
+ };
+
+ template<typename Ex, typename F, typename Fp>
+ struct future_executor_continuation_shared_state<Ex, F, void, Fp>: public shared_state<void>
+ {
+ Ex* ex;
+ F parent;
+ Fp continuation;
+
+ public:
+ future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
+ : ex(&ex), parent(boost::move(f)),
+ continuation(boost::move(c)) {
+ this->set_executor();
+ }
+
+ void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ run_it<future_executor_continuation_shared_state> fct(this);
+ ex->submit(fct);
+ }
+
+ static void run(future_executor_continuation_shared_state* that) {
+ try {
+ that->continuation(boost::move(that->parent));
+ that->mark_finished_with_result();
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+
+ ~future_executor_continuation_shared_state() {
+ this->wait(false);
+ }
+ };
+#endif
+
+ /////////////////////////
+ /// shared_future_async_continuation_shared_state
+ /////////////////////////
+
+ template<typename F, typename Rp, typename Fp>
+ struct shared_future_async_continuation_shared_state: future_async_shared_state_base<Rp>
+ {
+ F parent;
+ Fp continuation;
+
+ public:
+ shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
+ : parent(f),
+ continuation(boost::move(c)) {
+ }
+
+ void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ this->thr_ = thread(&shared_future_async_continuation_shared_state::run, this);
+ }
+
+ static void run(shared_future_async_continuation_shared_state* that) {
+ try {
+ that->mark_finished_with_result(that->continuation(that->parent));
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+
+ ~shared_future_async_continuation_shared_state() {
+ this->join();
+ }
+ };
+
+ template<typename F, typename Fp>
+ struct shared_future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void>
+ {
+ F parent;
+ Fp continuation;
+
+ public:
+ shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
+ : parent(f),
+ continuation(boost::move(c)) {
+ }
+
+ void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ this->thr_ = thread(&shared_future_async_continuation_shared_state::run, this);
+ }
+
+ static void run(shared_future_async_continuation_shared_state* that) {
+ try {
+ that->continuation(that->parent);
+ that->mark_finished_with_result();
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+
+ ~shared_future_async_continuation_shared_state() {
+ this->join();
+ }
+ };
+
+ /////////////////////////
+ /// shared_future_executor_continuation_shared_state
+ /////////////////////////
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+
+ template<typename Ex, typename F, typename Rp, typename Fp>
+ struct shared_future_executor_continuation_shared_state: shared_state<Rp>
+ {
+ Ex* ex;
+ F parent;
+ Fp continuation;
+
+ public:
+ shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c)
+ : ex(&ex), parent(f),
+ continuation(boost::move(c)) {
+ this->set_executor();
+ }
+
+ void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ run_it<shared_future_executor_continuation_shared_state> fct(this);
+ ex->submit(fct);
+ }
+
+ static void run(shared_future_executor_continuation_shared_state* that) {
+ try {
+ that->mark_finished_with_result(that->continuation(that->parent));
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+
+ ~shared_future_executor_continuation_shared_state() {
+ this->wait(false);
+ }
+ };
+
+ template<typename Ex, typename F, typename Fp>
+ struct shared_future_executor_continuation_shared_state<Ex, F, void, Fp>: public shared_state<void>
+ {
+ Ex* ex;
+ F parent;
+ Fp continuation;
+
+ public:
+ shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c)
+ : ex(&ex), parent(f),
+ continuation(boost::move(c)) {
+ }
+
+ void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ run_it<shared_future_executor_continuation_shared_state> fct(this);
+ ex->submit(fct);
+ }
+
+ static void run(shared_future_executor_continuation_shared_state* that) {
+ try {
+ that->continuation(that->parent);
+ that->mark_finished_with_result();
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+
+ ~shared_future_executor_continuation_shared_state() {
+ this->wait(false);
+ }
+ };
+#endif
+ //////////////////////////
+ /// future_deferred_continuation_shared_state
+ //////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ struct future_deferred_continuation_shared_state: shared_state<Rp>
+ {
+ F parent;
+ Fp continuation;
+
+ public:
+ future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
+ : parent(boost::move(f)),
+ continuation(boost::move(c)) {
+ this->set_deferred();
+ }
+
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ }
+
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
+ try {
+ Fp local_fuct=boost::move(continuation);
+ F ftmp = boost::move(parent);
+ relocker relock(lck);
+ Rp res = local_fuct(boost::move(ftmp));
+ relock.lock();
+ this->mark_finished_with_result_internal(boost::move(res), lck);
+ } catch (...) {
+ this->mark_exceptional_finish_internal(current_exception(), lck);
+ }
+ }
+ };
+
+ template<typename F, typename Fp>
+ struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void>
+ {
+ F parent;
+ Fp continuation;
+
+ public:
+ future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
+ : parent(boost::move(f)),
+ continuation(boost::move(c)) {
+ this->set_deferred();
+ }
+
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ }
+
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
+ try {
+ Fp local_fuct=boost::move(continuation);
+ F ftmp = boost::move(parent);
+ relocker relock(lck);
+ local_fuct(boost::move(ftmp));
+ relock.lock();
+ this->mark_finished_with_result_internal(lck);
+ } catch (...) {
+ this->mark_exceptional_finish_internal(current_exception(), lck);
+ }
+ }
+ };
+
+ //////////////////////////
+ /// shared_future_deferred_continuation_shared_state
+ //////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ struct shared_future_deferred_continuation_shared_state: shared_state<Rp>
+ {
+ F parent;
+ Fp continuation;
+
+ public:
+ shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
+ : parent(f),
+ continuation(boost::move(c)) {
+ this->set_deferred();
+ }
+
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ }
+
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
+ try {
+ Fp local_fuct=boost::move(continuation);
+ F ftmp = parent;
+ relocker relock(lck);
+ Rp res = local_fuct(ftmp);
+ relock.lock();
+ this->mark_finished_with_result_internal(boost::move(res), lck);
+ } catch (...) {
+ this->mark_exceptional_finish_internal(current_exception(), lck);
+ }
+ }
+ };
+
+ template<typename F, typename Fp>
+ struct shared_future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void>
+ {
+ F parent;
+ Fp continuation;
+
+ public:
+ shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
+ : parent(f),
+ continuation(boost::move(c)) {
+ this->set_deferred();
+ }
+
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ }
+
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
+ try {
+ Fp local_fuct=boost::move(continuation);
+ F ftmp = parent;
+ relocker relock(lck);
+ local_fuct(ftmp);
+ relock.lock();
+ this->mark_finished_with_result_internal(lck);
+ } catch (...) {
+ this->mark_exceptional_finish_internal(current_exception(), lck);
+ }
+ }
+ };
+
+ ////////////////////////////////
+ // make_future_deferred_continuation_shared_state
+ ////////////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_deferred_continuation_shared_state(
+ boost::unique_lock<boost::mutex> &lock,
+ BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) {
+ shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> >
+ h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
+ h->parent.future_->set_continuation_ptr(h, lock);
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+
+ ////////////////////////////////
+ // make_future_async_continuation_shared_state
+ ////////////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_async_continuation_shared_state(
+ boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
+ BOOST_THREAD_FWD_REF(Fp) c) {
+ shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> >
+ h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
+ h->parent.future_->set_continuation_ptr(h, lock);
+
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+
+ ////////////////////////////////
+ // make_future_executor_continuation_shared_state
+ ////////////////////////////////
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+
+ template<typename Ex, typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_executor_continuation_shared_state(Ex& ex,
+ boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
+ BOOST_THREAD_FWD_REF(Fp) c) {
+ shared_ptr<future_executor_continuation_shared_state<Ex,F,Rp, Fp> >
+ h(new future_executor_continuation_shared_state<Ex, F,Rp, Fp>(ex, boost::move(f), boost::forward<Fp>(c)));
+ h->parent.future_->set_continuation_ptr(h, lock);
+
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+#endif
+
+ ////////////////////////////////
+ // make_shared_future_deferred_continuation_shared_state
+ ////////////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_shared_future_deferred_continuation_shared_state(
+ boost::unique_lock<boost::mutex> &lock,
+ F f, BOOST_THREAD_FWD_REF(Fp) c) {
+ shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Fp> >
+ h(new shared_future_deferred_continuation_shared_state<F, Rp, Fp>(f, boost::forward<Fp>(c)));
+ h->parent.future_->set_continuation_ptr(h, lock);
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+ ////////////////////////////////
+ // make_shared_future_async_continuation_shared_state
+ ////////////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_shared_future_async_continuation_shared_state(
+ boost::unique_lock<boost::mutex> &lock, F f,
+ BOOST_THREAD_FWD_REF(Fp) c) {
+ shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Fp> >
+ h(new shared_future_async_continuation_shared_state<F,Rp, Fp>(f, boost::forward<Fp>(c)));
+ h->parent.future_->set_continuation_ptr(h, lock);
+
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+ ////////////////////////////////
+ // make_shared_future_executor_continuation_shared_state
+ ////////////////////////////////
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ template<typename Ex, typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_shared_future_executor_continuation_shared_state(Ex& ex,
+ boost::unique_lock<boost::mutex> &lock, F f,
+ BOOST_THREAD_FWD_REF(Fp) c) {
+ shared_ptr<shared_future_executor_continuation_shared_state<Ex, F, Rp, Fp> >
+ h(new shared_future_executor_continuation_shared_state<Ex, F, Rp, Fp>(ex, f, boost::forward<Fp>(c)));
+ h->parent.future_->set_continuation_ptr(h, lock);
+
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+#endif
+}
+
+ ////////////////////////////////
+ // template<typename F>
+ // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
+ ////////////////////////////////
+
+ template <typename R>
+ template <typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
+ BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
+ typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ if (underlying_cast<int>(policy) & int(launch::async)) {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ )));
+ } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ )));
+ } else {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ )));
+ }
+ }
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ template <typename R>
+ template <typename Ex, typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
+ BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
+ typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type, F>(ex,
+ lock, boost::move(*this), boost::forward<F>(func)
+ )));
+ }
+#endif
+ template <typename R>
+ template <typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
+ BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) {
+ typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) {
+ return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ );
+ } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) {
+ this->future_->wait_internal(lock);
+ return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ );
+ } else {
+ return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ );
+ }
+ }
+
+ template <typename R>
+ template <typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
+ shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const
+ {
+ typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+
+ if (underlying_cast<int>(policy) & int(launch::async)) {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
+ lock, *this, boost::forward<F>(func)
+ )));
+ } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
+ lock, *this, boost::forward<F>(func)
+ )));
+ } else {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
+ lock, *this, boost::forward<F>(func)
+ )));
+ }
+ }
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ template <typename R>
+ template <typename Ex, typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
+ shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const
+ {
+ typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type, F>(ex,
+ lock, *this, boost::forward<F>(func)
+ )));
+ }
+#endif
+
+ template <typename R>
+ template <typename F>
+ inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
+ shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const {
+ typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
+
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) {
+ return boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
+ lock, *this, boost::forward<F>(func));
+ } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) {
+ this->future_->wait_internal(lock);
+ return boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
+ lock, *this, boost::forward<F>(func));
+ } else {
+ return boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
+ lock, *this, boost::forward<F>(func));
+ }
+ }
+
+namespace detail
+{
+ template <typename T>
+ struct mfallbacker_to
+ {
+ T value_;
+ typedef T result_type;
+ mfallbacker_to(BOOST_THREAD_RV_REF(T) v)
+ : value_(boost::move(v))
+ {}
+
+ T operator()(BOOST_THREAD_FUTURE<T> fut) {
+ return fut.get_or(boost::move(value_));
+ }
+ };
+ template <typename T>
+ struct cfallbacker_to
+ {
+ T value_;
+ typedef T result_type;
+ cfallbacker_to(T const& v)
+ : value_(v)
+ {}
+
+ T operator()(BOOST_THREAD_FUTURE<T> fut) {
+ return fut.get_or(value_);
+
+ }
+ };
+}
+ ////////////////////////////////
+ // future<R> future<R>::fallback_to(R&& v);
+ ////////////////////////////////
+
+ template <typename R>
+ template <typename R2>
+ inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
+ BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v) {
+ return then(detail::mfallbacker_to<R>(boost::move(v)));
+ }
+
+ template <typename R>
+ template <typename R2>
+ inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
+ BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v) {
+ return then(detail::cfallbacker_to<R>(v));
+ }
+
+#endif
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+namespace detail
+{
+ /////////////////////////
+ /// future_unwrap_shared_state
+ /////////////////////////
+
+ template<typename F, typename Rp>
+ struct future_unwrap_shared_state: shared_state<Rp>
+ {
+ F parent;
+ public:
+ explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f)
+ : parent(boost::move(f)) {}
+
+ typename F::value_type parent_value(boost::unique_lock<boost::mutex>& ) {
+ typename F::value_type r = parent.get();
+ r.set_exceptional_if_invalid();
+ return boost::move(r);
+ }
+ virtual void wait(bool ) { // todo see if rethrow must be used
+ boost::unique_lock<boost::mutex> lk(this->mutex);
+ parent_value(lk).wait();
+ }
+ virtual Rp get() {
+ boost::unique_lock<boost::mutex> lk(this->mutex);
+ return parent_value(lk).get();
+ }
+ };
+
+ template <class F, class Rp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) {
+ shared_ptr<future_unwrap_shared_state<F, Rp> >
+ h(new future_unwrap_shared_state<F, Rp>(boost::move(f)));
+ h->parent.future_->set_continuation_ptr(h, lock);
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+}
+ template <typename R>
+ inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other)
+ : base_type(other.unwrap()) {}
+ template <typename R2>
+ BOOST_THREAD_FUTURE<R2>
+ BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
+ {
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
+ }
+#endif
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
+namespace detail
+{
+ struct input_iterator_tag {};
+ struct vector_tag {};
+ struct values_tag {};
+ template <typename T>
+ struct alias_t { typedef T type; };
+
+ BOOST_CONSTEXPR_OR_CONST input_iterator_tag input_iterator_tag_value = {};
+ BOOST_CONSTEXPR_OR_CONST vector_tag vector_tag_value = {};
+ BOOST_CONSTEXPR_OR_CONST values_tag values_tag_value = {};
+ ////////////////////////////////
+ // detail::future_async_when_all_shared_state
+ ////////////////////////////////
+ template<typename F>
+ struct future_when_all_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
+ {
+ typedef csbl::vector<F> vector_type;
+ typedef typename F::value_type value_type;
+ vector_type vec_;
+
+ static void run(future_when_all_vector_shared_state* that) {
+ try {
+ boost::wait_for_all(that->vec_.begin(), that->vec_.end());
+ that->mark_finished_with_result(boost::move(that->vec_));
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+ bool run_deferred() {
+
+ bool res = false;
+ for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
+ if (! it->run_if_is_deferred())
+ {
+ res = true;
+ }
+ }
+ return res;
+ }
+ void init() {
+ if (! run_deferred())
+ {
+ future_when_all_vector_shared_state::run(this);
+ return;
+ }
+ this->thr_ = thread(&future_when_all_vector_shared_state::run, this);
+ }
+
+ public:
+ template< typename InputIterator>
+ future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
+ : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
+ {
+ init();
+ }
+
+ future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
+ : vec_(boost::move(v))
+ {
+ init();
+ }
+
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template< typename T0, typename ...T>
+ future_when_all_vector_shared_state(values_tag, BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
+ vec_.push_back(boost::forward<T0>(f));
+ typename alias_t<char[]>::type{
+ ( //first part of magic unpacker
+ vec_.push_back(boost::forward<T>(futures)),'0'
+ )..., '0'
+ }; //second part of magic unpacker
+ init();
+ }
+#endif
+ ~future_when_all_vector_shared_state() {
+ this->join();
+ }
+ };
+
+ ////////////////////////////////
+ // detail::future_async_when_any_shared_state
+ ////////////////////////////////
+ template<typename F>
+ struct future_when_any_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
+ {
+ typedef csbl::vector<F> vector_type;
+ typedef typename F::value_type value_type;
+ vector_type vec_;
+
+ static void run(future_when_any_vector_shared_state* that)
+ {
+ try {
+ boost::wait_for_any(that->vec_.begin(), that->vec_.end());
+ that->mark_finished_with_result(boost::move(that->vec_));
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+ bool run_deferred() {
+
+ for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
+ if (it->run_if_is_deferred_or_ready())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ void init() {
+ if (run_deferred())
+ {
+ future_when_any_vector_shared_state::run(this);
+ return;
+ }
+
+ this->thr_ = thread(&future_when_any_vector_shared_state::run, this);
+ }
+
+ public:
+ template< typename InputIterator>
+ future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
+ : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
+ {
+ init();
+ }
+
+ future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
+ : vec_(boost::move(v))
+ {
+ init();
+ }
+
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template< typename T0, typename ...T>
+ future_when_any_vector_shared_state(values_tag,
+ BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures
+ ) {
+ vec_.push_back(boost::forward<T0>(f));
+ typename alias_t<char[]>::type{
+ ( //first part of magic unpacker
+ vec_.push_back(boost::forward<T>(futures))
+ ,'0'
+ )...,
+ '0'
+ }; //second part of magic unpacker
+ init();
+ }
+#endif
+
+ ~future_when_any_vector_shared_state() {
+ this->join();
+ }
+ };
+
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ struct wait_for_all_fctr {
+ template <class ...T>
+ void operator()(T&&... v) {
+ boost::wait_for_all(boost::forward<T>(v)...);
+ }
+ };
+
+ struct wait_for_any_fctr {
+ template <class ...T>
+ void operator()(T&&... v) {
+ boost::wait_for_any(boost::forward<T>(v)...);
+ }
+ };
+
+
+ template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
+ struct accumulate_run_if_is_deferred {
+ bool operator ()(Tuple& t)
+ {
+ return (! csbl::get<i-1>(t).run_if_is_deferred()) || accumulate_run_if_is_deferred<Tuple,i-1>()(t);
+ }
+ };
+ template <class Tuple>
+ struct accumulate_run_if_is_deferred<Tuple, 0> {
+ bool operator ()(Tuple& )
+ {
+ return false;
+ }
+ };
+
+
+ template< typename Tuple, typename T0, typename ...T>
+ struct future_when_all_tuple_shared_state: future_async_shared_state_base<Tuple>
+ {
+ Tuple tup_;
+ typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
+
+ static void run(future_when_all_tuple_shared_state* that) {
+ try {
+ // TODO make use of apply(that->tup_, boost::detail::wait_for_all_fctor());
+ that->wait_for_all(Index());
+
+ that->mark_finished_with_result(boost::move(that->tup_));
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+
+ template <size_t ...Indices>
+ void wait_for_all(tuple_indices<Indices...>) {
+#if defined BOOST_THREAD_PROVIDES_INVOKE
+ return invoke<void>(wait_for_all_fctr(), csbl::get<Indices>(tup_)...);
+#else
+ return wait_for_all_fctr()(csbl::get<Indices>(tup_)...);
+#endif
+ }
+
+ bool run_deferred() {
+
+ return accumulate_run_if_is_deferred<Tuple>()(tup_);
+ }
+ void init() {
+ if (! run_deferred())
+ {
+ future_when_all_tuple_shared_state::run(this);
+ return;
+ }
+
+ this->thr_ = thread(&future_when_all_tuple_shared_state::run, this);
+ }
+ public:
+ template< typename F, typename ...Fs>
+ future_when_all_tuple_shared_state(values_tag, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures) :
+ tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
+ {
+ init();
+ }
+ ~future_when_all_tuple_shared_state() {
+ this->join();
+ }
+
+ };
+
+
+ template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
+ struct apply_any_run_if_is_deferred_or_ready {
+ bool operator ()(Tuple& t)
+ {
+ if (csbl::get<i-1>(t).run_if_is_deferred_or_ready()) return true;
+ return apply_any_run_if_is_deferred_or_ready<Tuple,i-1>()(t);
+ }
+ };
+ template <class Tuple>
+ struct apply_any_run_if_is_deferred_or_ready<Tuple, 0> {
+ bool operator ()(Tuple& )
+ {
+ return false;
+ }
+ };
+
+ template< typename Tuple, typename T0, typename ...T >
+ struct future_when_any_tuple_shared_state: future_async_shared_state_base<Tuple>
+ {
+ Tuple tup_;
+ typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
+
+ static void run(future_when_any_tuple_shared_state* that)
+ {
+ try {
+ // TODO make use of apply(that->tup_, wait_for_any_fctr);
+ that->wait_for_any(Index());
+
+ that->mark_finished_with_result(boost::move(that->tup_));
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ } catch(thread_interrupted& ) {
+ that->mark_interrupted_finish();
+#endif
+ } catch(...) {
+ that->mark_exceptional_finish();
+ }
+ }
+ template <size_t ...Indices>
+ void wait_for_any(tuple_indices<Indices...>) {
+#if defined BOOST_THREAD_PROVIDES_INVOKE
+ return invoke<void>(wait_for_any_fctr(), csbl::get<Indices>(tup_)...);
+#else
+ return wait_for_any_fctr()(csbl::get<Indices>(tup_)...);
+#endif
+ }
+ bool run_deferred() {
+ return apply_any_run_if_is_deferred_or_ready<Tuple>()(tup_);
+ }
+ void init() {
+ if (run_deferred())
+ {
+ future_when_any_tuple_shared_state::run(this);
+ return;
+ }
+
+ this->thr_ = thread(&future_when_any_tuple_shared_state::run, this);
+ }
+
+ public:
+ template< typename F, typename ...Fs>
+ future_when_any_tuple_shared_state(values_tag,
+ BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures
+ ) :
+ tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
+ {
+ init();
+ }
+
+ ~future_when_any_tuple_shared_state() {
+ this->join();
+ }
+ };
+#endif
+
+}
+
+ template< typename InputIterator>
+ typename boost::disable_if<is_future_type<InputIterator>,
+ BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
+ >::type
+ when_all(InputIterator first, InputIterator last) {
+ typedef typename InputIterator::value_type value_type;
+ typedef csbl::vector<value_type> container_type;
+ typedef detail::future_when_all_vector_shared_state<value_type> factory_type;
+
+ if (first==last) return make_ready_future(container_type());
+ shared_ptr<factory_type >
+ h(new factory_type(detail::input_iterator_tag_value, first,last));
+ return BOOST_THREAD_FUTURE<container_type>(h);
+ }
+
+ inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all() {
+ return make_ready_future(csbl::tuple<>());
+ }
+
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template< typename T0, typename ...T>
+ BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
+ when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
+ typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
+ typedef detail::future_when_all_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
+
+ shared_ptr<factory_type>
+ h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
+ return BOOST_THREAD_FUTURE<container_type>(h);
+ }
+#endif
+
+ template< typename InputIterator>
+ typename boost::disable_if<is_future_type<InputIterator>,
+ BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
+ >::type
+ when_any(InputIterator first, InputIterator last) {
+ typedef typename InputIterator::value_type value_type;
+ typedef csbl::vector<value_type> container_type;
+ typedef detail::future_when_any_vector_shared_state<value_type> factory_type;
+
+ if (first==last) return make_ready_future(container_type());
+ shared_ptr<factory_type >
+ h(new factory_type(detail::input_iterator_tag_value, first,last));
+ return BOOST_THREAD_FUTURE<container_type>(h);
+ }
+
+ inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any() {
+ return make_ready_future(csbl::tuple<>());
+ }
+
+#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template< typename T0, typename ...T>
+ BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
+ when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
+ typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
+ typedef detail::future_when_any_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
+
+ shared_ptr<factory_type>
+ h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
+ return BOOST_THREAD_FUTURE<container_type>(h);
+ }
+#endif
+#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
}
#endif // BOOST_NO_EXCEPTION
diff --git a/boost/thread/future_error_code.hpp b/boost/thread/future_error_code.hpp
new file mode 100644
index 0000000000..6fe95541b7
--- /dev/null
+++ b/boost/thread/future_error_code.hpp
@@ -0,0 +1,61 @@
+// (C) Copyright 2008-10 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+//
+// 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)
+
+#ifndef BOOST_THREAD_FUTURE_ERROR_CODE_HPP
+#define BOOST_THREAD_FUTURE_ERROR_CODE_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/core/scoped_enum.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost
+{
+
+ //enum class future_errc
+ BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc)
+ {
+ broken_promise = 1,
+ future_already_retrieved,
+ promise_already_satisfied,
+ no_state
+ }
+ BOOST_SCOPED_ENUM_DECLARE_END(future_errc)
+
+ namespace system
+ {
+ template <>
+ struct BOOST_SYMBOL_VISIBLE is_error_code_enum< ::boost::future_errc> : public true_type {};
+
+ #ifdef BOOST_NO_CXX11_SCOPED_ENUMS
+ template <>
+ struct BOOST_SYMBOL_VISIBLE is_error_code_enum< ::boost::future_errc::enum_type> : public true_type { };
+ #endif
+ } // system
+
+ BOOST_THREAD_DECL
+ const system::error_category& future_category() BOOST_NOEXCEPT;
+
+ namespace system
+ {
+ inline
+ error_code
+ make_error_code(future_errc e) BOOST_NOEXCEPT
+ {
+ return error_code(underlying_cast<int>(e), boost::future_category());
+ }
+
+ inline
+ error_condition
+ make_error_condition(future_errc e) BOOST_NOEXCEPT
+ {
+ return error_condition(underlying_cast<int>(e), boost::future_category());
+ }
+ } // system
+} // boost
+
+#endif // header
diff --git a/boost/thread/is_locked_by_this_thread.hpp b/boost/thread/is_locked_by_this_thread.hpp
new file mode 100644
index 0000000000..6344c0ff6d
--- /dev/null
+++ b/boost/thread/is_locked_by_this_thread.hpp
@@ -0,0 +1,39 @@
+// (C) Copyright 2012 Vicente J. Botet Escriba
+// 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)
+
+
+#ifndef BOOST_THREAD_IS_LOCKED_BY_THIS_THREAD_HPP
+#define BOOST_THREAD_IS_LOCKED_BY_THIS_THREAD_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ template <typename Lockable>
+ class testable_mutex;
+
+ /**
+ * Overloaded function used to check if the mutex is locked when it is testable and do nothing otherwise.
+ *
+ * This function is used usually to assert the pre-condition when the function can only be called when the mutex
+ * must be locked by the current thread.
+ */
+ template <typename Lockable>
+ bool is_locked_by_this_thread(testable_mutex<Lockable> const& mtx)
+ {
+ return mtx.is_locked_by_this_thread();
+ }
+ template <typename Lockable>
+ bool is_locked_by_this_thread(Lockable const&)
+ {
+ return true;
+ }
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // header
diff --git a/boost/thread/latch.hpp b/boost/thread/latch.hpp
new file mode 100644
index 0000000000..6caf521910
--- /dev/null
+++ b/boost/thread/latch.hpp
@@ -0,0 +1,167 @@
+// 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)
+// (C) Copyright 2013 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_LATCH_HPP
+#define BOOST_THREAD_LATCH_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/counter.hpp>
+
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/lock_types.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/chrono/duration.hpp>
+#include <boost/chrono/time_point.hpp>
+#include <boost/assert.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ class latch
+ {
+ /// @Requires: count_ must be greater than 0
+ /// Effect: Decrement the count. Unlocks the lock and notify anyone waiting if we reached zero.
+ /// Returns: true if count_ reached the value 0.
+ /// @ThreadSafe ensured by the @c lk parameter
+ bool count_down(unique_lock<mutex> &lk)
+ /// pre_condition (count_ > 0)
+ {
+ BOOST_ASSERT(count_ > 0);
+ if (--count_ == 0)
+ {
+ ++generation_;
+ //lk.unlock();
+ cond_.notify_all();
+ return true;
+ }
+ return false;
+ }
+ /// Effect: Decrement the count is > 0. Unlocks the lock notify anyone waiting if we reached zero.
+ /// Returns: true if count_ is 0.
+ /// @ThreadSafe ensured by the @c lk parameter
+ bool try_count_down(unique_lock<mutex> &lk)
+ {
+ if (count_ > 0)
+ {
+ return count_down(lk);
+ }
+ return true;
+ }
+ public:
+ BOOST_THREAD_NO_COPYABLE( latch)
+
+ /// Constructs a latch with a given count.
+ latch(std::size_t count) :
+ count_(count), generation_(0)
+ {
+ }
+
+ /// Destructor
+ /// Precondition: No threads are waiting or invoking count_down on @c *this.
+
+ ~latch()
+ {
+
+ }
+
+ /// Blocks until the latch has counted down to zero.
+ void wait()
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ std::size_t generation(generation_);
+ cond_.wait(lk, detail::not_equal(generation, generation_));
+ }
+
+ /// @return true if the internal counter is already 0, false otherwise
+ bool try_wait()
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ return (count_ == 0);
+ }
+
+ /// try to wait for a specified amount of time is elapsed.
+ /// @return whether there is a timeout or not.
+ template <class Rep, class Period>
+ cv_status wait_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ std::size_t generation(generation_);
+ return cond_.wait_for(lk, rel_time, detail::not_equal(generation, generation_))
+ ? cv_status::no_timeout
+ : cv_status::timeout;
+ }
+
+ /// try to wait until the specified time_point is reached
+ /// @return whether there were a timeout or not.
+ template <class Clock, class Duration>
+ cv_status wait_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ std::size_t generation(generation_);
+ return cond_.wait_until(lk, abs_time, detail::not_equal(generation, generation_))
+ ? cv_status::no_timeout
+ : cv_status::timeout;
+ }
+
+ /// Decrement the count and notify anyone waiting if we reach zero.
+ /// @Requires count must be greater than 0
+ void count_down()
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ count_down(lk);
+ }
+ /// Effect: Decrement the count if it is > 0 and notify anyone waiting if we reached zero.
+ /// Returns: true if count_ was 0 or reached 0.
+ bool try_count_down()
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ return try_count_down(lk);
+ }
+ void signal()
+ {
+ count_down();
+ }
+
+ /// Decrement the count and notify anyone waiting if we reach zero.
+ /// Blocks until the latch has counted down to zero.
+ /// @Requires count must be greater than 0
+ void count_down_and_wait()
+ {
+ boost::unique_lock<boost::mutex> lk(mutex_);
+ std::size_t generation(generation_);
+ if (count_down(lk))
+ {
+ return;
+ }
+ cond_.wait(lk, detail::not_equal(generation, generation_));
+ }
+ void sync()
+ {
+ count_down_and_wait();
+ }
+
+ /// Reset the counter
+ /// #Requires This method may only be invoked when there are no other threads currently inside the count_down_and_wait() method.
+ void reset(std::size_t count)
+ {
+ boost::lock_guard<boost::mutex> lk(mutex_);
+ //BOOST_ASSERT(count_ == 0);
+ count_ = count;
+ }
+
+ private:
+ mutex mutex_;
+ condition_variable cond_;
+ std::size_t count_;
+ std::size_t generation_;
+ };
+
+} // namespace boost
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/lock_algorithms.hpp b/boost/thread/lock_algorithms.hpp
new file mode 100644
index 0000000000..7a55f92a28
--- /dev/null
+++ b/boost/thread/lock_algorithms.hpp
@@ -0,0 +1,468 @@
+// 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)
+// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_LOCK_ALGORITHMS_HPP
+#define BOOST_THREAD_LOCK_ALGORITHMS_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/lock_types.hpp>
+#include <boost/thread/lockable_traits.hpp>
+
+#include <algorithm>
+#include <iterator>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ namespace detail
+ {
+ template <typename MutexType1, typename MutexType2>
+ unsigned try_lock_internal(MutexType1& m1, MutexType2& m2)
+ {
+ boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock);
+ if (!l1)
+ {
+ return 1;
+ }
+ if (!m2.try_lock())
+ {
+ return 2;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3>
+ unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3)
+ {
+ boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock);
+ if (!l1)
+ {
+ return 1;
+ }
+ if (unsigned const failed_lock=try_lock_internal(m2,m3))
+ {
+ return failed_lock + 1;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
+ unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
+ {
+ boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock);
+ if (!l1)
+ {
+ return 1;
+ }
+ if (unsigned const failed_lock=try_lock_internal(m2,m3,m4))
+ {
+ return failed_lock + 1;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
+ unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
+ {
+ boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock);
+ if (!l1)
+ {
+ return 1;
+ }
+ if (unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
+ {
+ return failed_lock + 1;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template <typename MutexType1, typename MutexType2>
+ unsigned lock_helper(MutexType1& m1, MutexType2& m2)
+ {
+ boost::unique_lock<MutexType1> l1(m1);
+ if (!m2.try_lock())
+ {
+ return 1;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3>
+ unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3)
+ {
+ boost::unique_lock<MutexType1> l1(m1);
+ if (unsigned const failed_lock=try_lock_internal(m2,m3))
+ {
+ return failed_lock;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
+ unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
+ {
+ boost::unique_lock<MutexType1> l1(m1);
+ if (unsigned const failed_lock=try_lock_internal(m2,m3,m4))
+ {
+ return failed_lock;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
+ unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
+ {
+ boost::unique_lock<MutexType1> l1(m1);
+ if (unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
+ {
+ return failed_lock;
+ }
+ l1.release();
+ return 0;
+ }
+ }
+
+ namespace detail
+ {
+ template <bool x>
+ struct is_mutex_type_wrapper
+ {
+ };
+
+ template <typename MutexType1, typename MutexType2>
+ void lock_impl(MutexType1& m1, MutexType2& m2, is_mutex_type_wrapper<true> )
+ {
+ unsigned const lock_count = 2;
+ unsigned lock_first = 0;
+ for (;;)
+ {
+ switch (lock_first)
+ {
+ case 0:
+ lock_first = detail::lock_helper(m1, m2);
+ if (!lock_first) return;
+ break;
+ case 1:
+ lock_first = detail::lock_helper(m2, m1);
+ if (!lock_first) return;
+ lock_first = (lock_first + 1) % lock_count;
+ break;
+ }
+ }
+ }
+
+ template <typename Iterator>
+ void lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> );
+ }
+
+ template <typename MutexType1, typename MutexType2>
+ void lock(MutexType1& m1, MutexType2& m2)
+ {
+ detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
+ }
+
+ template <typename MutexType1, typename MutexType2>
+ void lock(const MutexType1& m1, MutexType2& m2)
+ {
+ detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
+ }
+
+ template <typename MutexType1, typename MutexType2>
+ void lock(MutexType1& m1, const MutexType2& m2)
+ {
+ detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
+ }
+
+ template <typename MutexType1, typename MutexType2>
+ void lock(const MutexType1& m1, const MutexType2& m2)
+ {
+ detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3>
+ void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3)
+ {
+ unsigned const lock_count = 3;
+ unsigned lock_first = 0;
+ for (;;)
+ {
+ switch (lock_first)
+ {
+ case 0:
+ lock_first = detail::lock_helper(m1, m2, m3);
+ if (!lock_first) return;
+ break;
+ case 1:
+ lock_first = detail::lock_helper(m2, m3, m1);
+ if (!lock_first) return;
+ lock_first = (lock_first + 1) % lock_count;
+ break;
+ case 2:
+ lock_first = detail::lock_helper(m3, m1, m2);
+ if (!lock_first) return;
+ lock_first = (lock_first + 2) % lock_count;
+ break;
+ }
+ }
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
+ void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
+ {
+ unsigned const lock_count = 4;
+ unsigned lock_first = 0;
+ for (;;)
+ {
+ switch (lock_first)
+ {
+ case 0:
+ lock_first = detail::lock_helper(m1, m2, m3, m4);
+ if (!lock_first) return;
+ break;
+ case 1:
+ lock_first = detail::lock_helper(m2, m3, m4, m1);
+ if (!lock_first) return;
+ lock_first = (lock_first + 1) % lock_count;
+ break;
+ case 2:
+ lock_first = detail::lock_helper(m3, m4, m1, m2);
+ if (!lock_first) return;
+ lock_first = (lock_first + 2) % lock_count;
+ break;
+ case 3:
+ lock_first = detail::lock_helper(m4, m1, m2, m3);
+ if (!lock_first) return;
+ lock_first = (lock_first + 3) % lock_count;
+ break;
+ }
+ }
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
+ void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
+ {
+ unsigned const lock_count = 5;
+ unsigned lock_first = 0;
+ for (;;)
+ {
+ switch (lock_first)
+ {
+ case 0:
+ lock_first = detail::lock_helper(m1, m2, m3, m4, m5);
+ if (!lock_first) return;
+ break;
+ case 1:
+ lock_first = detail::lock_helper(m2, m3, m4, m5, m1);
+ if (!lock_first) return;
+ lock_first = (lock_first + 1) % lock_count;
+ break;
+ case 2:
+ lock_first = detail::lock_helper(m3, m4, m5, m1, m2);
+ if (!lock_first) return;
+ lock_first = (lock_first + 2) % lock_count;
+ break;
+ case 3:
+ lock_first = detail::lock_helper(m4, m5, m1, m2, m3);
+ if (!lock_first) return;
+ lock_first = (lock_first + 3) % lock_count;
+ break;
+ case 4:
+ lock_first = detail::lock_helper(m5, m1, m2, m3, m4);
+ if (!lock_first) return;
+ lock_first = (lock_first + 4) % lock_count;
+ break;
+ }
+ }
+ }
+
+ namespace detail
+ {
+ template <typename Mutex, bool x = is_mutex_type<Mutex>::value>
+ struct try_lock_impl_return
+ {
+ typedef int type;
+ };
+
+ template <typename Iterator>
+ struct try_lock_impl_return<Iterator, false>
+ {
+ typedef Iterator type;
+ };
+
+ template <typename MutexType1, typename MutexType2>
+ int try_lock_impl(MutexType1& m1, MutexType2& m2, is_mutex_type_wrapper<true> )
+ {
+ return ((int) detail::try_lock_internal(m1, m2)) - 1;
+ }
+
+ template <typename Iterator>
+ Iterator try_lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> );
+ }
+
+ template <typename MutexType1, typename MutexType2>
+ typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1, MutexType2& m2)
+ {
+ return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
+ }
+
+ template <typename MutexType1, typename MutexType2>
+ typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1, MutexType2& m2)
+ {
+ return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
+ }
+
+ template <typename MutexType1, typename MutexType2>
+ typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1, const MutexType2& m2)
+ {
+ return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
+ }
+
+ template <typename MutexType1, typename MutexType2>
+ typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1, const MutexType2& m2)
+ {
+ return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3>
+ int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3)
+ {
+ return ((int) detail::try_lock_internal(m1, m2, m3)) - 1;
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
+ int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
+ {
+ return ((int) detail::try_lock_internal(m1, m2, m3, m4)) - 1;
+ }
+
+ template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
+ int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
+ {
+ return ((int) detail::try_lock_internal(m1, m2, m3, m4, m5)) - 1;
+ }
+
+ namespace detail
+ {
+ template <typename Iterator>
+ struct range_lock_guard
+ {
+ Iterator begin;
+ Iterator end;
+
+ range_lock_guard(Iterator begin_, Iterator end_) :
+ begin(begin_), end(end_)
+ {
+ boost::lock(begin, end);
+ }
+
+ void release()
+ {
+ begin = end;
+ }
+
+ ~range_lock_guard()
+ {
+ for (; begin != end; ++begin)
+ {
+ begin->unlock();
+ }
+ }
+ };
+
+ template <typename Iterator>
+ Iterator try_lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> )
+
+ {
+ if (begin == end)
+ {
+ return end;
+ }
+ typedef typename std::iterator_traits<Iterator>::value_type lock_type;
+ unique_lock<lock_type> guard(*begin, try_to_lock);
+
+ if (!guard.owns_lock())
+ {
+ return begin;
+ }
+ Iterator const failed = boost::try_lock(++begin, end);
+ if (failed == end)
+ {
+ guard.release();
+ }
+
+ return failed;
+ }
+ }
+
+ namespace detail
+ {
+ template <typename Iterator>
+ void lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> )
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type lock_type;
+
+ if (begin == end)
+ {
+ return;
+ }
+ bool start_with_begin = true;
+ Iterator second = begin;
+ ++second;
+ Iterator next = second;
+
+ for (;;)
+ {
+ unique_lock<lock_type> begin_lock(*begin, defer_lock);
+ if (start_with_begin)
+ {
+ begin_lock.lock();
+ Iterator const failed_lock = boost::try_lock(next, end);
+ if (failed_lock == end)
+ {
+ begin_lock.release();
+ return;
+ }
+ start_with_begin = false;
+ next = failed_lock;
+ }
+ else
+ {
+ detail::range_lock_guard<Iterator> guard(next, end);
+ if (begin_lock.try_lock())
+ {
+ Iterator const failed_lock = boost::try_lock(second, next);
+ if (failed_lock == next)
+ {
+ begin_lock.release();
+ guard.release();
+ return;
+ }
+ start_with_begin = false;
+ next = failed_lock;
+ }
+ else
+ {
+ start_with_begin = true;
+ next = second;
+ }
+ }
+ }
+ }
+
+ }
+
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/lock_concepts.hpp b/boost/thread/lock_concepts.hpp
new file mode 100644
index 0000000000..d96c3dc1b9
--- /dev/null
+++ b/boost/thread/lock_concepts.hpp
@@ -0,0 +1,197 @@
+// (C) Copyright 2012 Vicente Botet
+//
+// 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)
+
+#ifndef BOOST_THREAD_LOCK_CONCEPTS_HPP
+#define BOOST_THREAD_LOCK_CONCEPTS_HPP
+
+#include <boost/thread/lock_traits.hpp>
+#include <boost/thread/lock_options.hpp>
+#include <boost/thread/lockable_concepts.hpp>
+#include <boost/thread/exceptions.hpp>
+#include <boost/thread/detail/move.hpp>
+
+#include <boost/chrono/chrono.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/static_assert.hpp>
+
+namespace boost
+{
+
+ /**
+ * BasicLock object supports the basic features
+ * required to delimit a critical region
+ * Supports the basic lock, unlock and try_lock functions and
+ * defines the lock traits
+ */
+
+ template <typename Lk>
+ struct BasicLock
+ {
+ typedef typename Lk::mutex_type mutex_type;
+ void cvt_mutex_ptr(mutex_type*) {}
+ BOOST_CONCEPT_ASSERT(( BasicLockable<mutex_type> ));
+
+ BOOST_CONCEPT_USAGE(BasicLock)
+ {
+ const Lk l1(mtx);
+ Lk l2(mtx, defer_lock);
+ Lk l3(mtx, adopt_lock);
+ Lk l4(( Lk()));
+ Lk l5(( boost::move(l2)));
+ cvt_mutex_ptr(l1.mutex());
+ if (l1.owns_lock()) return;
+ if (l1) return;
+ if (!l1) return;
+
+ l2.lock();
+ l2.unlock();
+ l2.release();
+
+ }
+ BasicLock() :
+ mtx(*static_cast<mutex_type*>(0))
+ {}
+ private:
+ BasicLock operator=(BasicLock const&);
+ mutex_type& mtx;
+ }
+ ;
+
+ template <typename Lk>
+ struct Lock
+ {
+ BOOST_CONCEPT_ASSERT(( BasicLock<Lk> ));
+ typedef typename Lk::mutex_type mutex_type;
+ BOOST_CONCEPT_ASSERT(( Lockable<mutex_type> ));
+
+ BOOST_CONCEPT_USAGE(Lock)
+ {
+ Lk l1(mtx, try_to_lock);
+ if (l1.try_lock()) return;
+ }
+ Lock() :
+ mtx(*static_cast<mutex_type*>(0))
+ {}
+ private:
+ Lock operator=(Lock const&);
+ mutex_type& mtx;
+ };
+
+ template <typename Lk>
+ struct TimedLock
+ {
+ BOOST_CONCEPT_ASSERT(( Lock<Lk> ));
+ typedef typename Lk::mutex_type mutex_type;
+ BOOST_CONCEPT_ASSERT(( TimedLockable<mutex_type> ));
+
+ BOOST_CONCEPT_USAGE(TimedLock)
+ {
+ const Lk l1(mtx, t);
+ Lk l2(mtx, d);
+ if (l1.try_lock_until(t)) return;
+ if (l1.try_lock_for(d)) return;
+ }
+ TimedLock() :
+ mtx(*static_cast<mutex_type*>(0))
+ {}
+ private:
+ TimedLock operator=(TimedLock const&);
+ mutex_type& mtx;
+ boost::chrono::system_clock::time_point t;
+ boost::chrono::system_clock::duration d;
+ };
+
+ template <typename Lk>
+ struct UniqueLock
+ {
+ BOOST_CONCEPT_ASSERT(( TimedLock<Lk> ));
+ typedef typename Lk::mutex_type mutex_type;
+
+ BOOST_CONCEPT_USAGE(UniqueLock)
+ {
+
+ }
+ UniqueLock() :
+ mtx(*static_cast<mutex_type*>(0))
+ {}
+ private:
+ UniqueLock operator=(UniqueLock const&);
+ mutex_type& mtx;
+ };
+
+ template <typename Lk>
+ struct SharedLock
+ {
+ BOOST_CONCEPT_ASSERT(( TimedLock<Lk> ));
+ typedef typename Lk::mutex_type mutex_type;
+
+ BOOST_CONCEPT_USAGE(SharedLock)
+ {
+ }
+ SharedLock() :
+ mtx(*static_cast<mutex_type*>(0))
+ {}
+ private:
+ SharedLock operator=(SharedLock const&);
+ mutex_type& mtx;
+
+ };
+
+ template <typename Lk>
+ struct UpgradeLock
+ {
+ BOOST_CONCEPT_ASSERT(( SharedLock<Lk> ));
+ typedef typename Lk::mutex_type mutex_type;
+
+ BOOST_CONCEPT_USAGE(UpgradeLock)
+ {
+ }
+ UpgradeLock() :
+ mtx(*static_cast<mutex_type*>(0))
+ {}
+ private:
+ UpgradeLock operator=(UpgradeLock const&);
+ mutex_type& mtx;
+ };
+
+ /**
+ * An StrictLock is a scoped lock guard ensuring the mutex is locked on the
+ * scope of the lock, by locking the mutex on construction and unlocking it on
+ * destruction.
+ *
+ * Essentially, a StrictLock's role is only to live on the stack as an
+ * automatic variable. strict_lock must adhere to a non-copy and non-alias
+ * policy. StrictLock disables copying by making the copy constructor and the
+ * assignment operator private. While we're at it, let's disable operator new
+ * and operator delete; strict locks are not intended to be allocated on the
+ * heap. StrictLock avoids aliasing by using a slightly less orthodox and
+ * less well-known technique: disable address taking.
+ */
+
+ template <typename Lk>
+ struct StrictLock
+ {
+ typedef typename Lk::mutex_type mutex_type;
+ BOOST_CONCEPT_ASSERT(( BasicLockable<mutex_type> ));
+ BOOST_STATIC_ASSERT(( is_strict_lock<Lk>::value ));
+
+ BOOST_CONCEPT_USAGE( StrictLock)
+ {
+ if (l1.owns_lock(&mtx)) return;
+ }
+ StrictLock() :
+ l1(*static_cast<Lk*>(0)),
+ mtx(*static_cast<mutex_type*>(0))
+ {}
+ private:
+ StrictLock operator=(StrictLock const&);
+
+ Lk const& l1;
+ mutex_type const& mtx;
+
+ };
+
+}
+#endif
diff --git a/boost/thread/lock_factories.hpp b/boost/thread/lock_factories.hpp
new file mode 100644
index 0000000000..523b90a5ea
--- /dev/null
+++ b/boost/thread/lock_factories.hpp
@@ -0,0 +1,78 @@
+// 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)
+// (C) Copyright 2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_LOCK_FACTORIES_HPP
+#define BOOST_THREAD_LOCK_FACTORIES_HPP
+
+#include <boost/thread/lock_types.hpp>
+#include <boost/thread/lock_algorithms.hpp>
+#if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS)
+#include <tuple> // todo change to <boost/tuple.hpp> once Boost.Tuple or Boost.Fusion provides Move semantics.
+#endif
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ template <typename Lockable>
+ unique_lock<Lockable> make_unique_lock(Lockable& mtx)
+ {
+ return unique_lock<Lockable> (mtx);
+ }
+
+ template <typename Lockable>
+ unique_lock<Lockable> make_unique_lock(Lockable& mtx, adopt_lock_t)
+ {
+ return unique_lock<Lockable> (mtx, adopt_lock);
+ }
+
+ template <typename Lockable>
+ unique_lock<Lockable> make_unique_lock(Lockable& mtx, defer_lock_t)
+ {
+ return unique_lock<Lockable> (mtx, defer_lock);
+ }
+
+ template <typename Lockable>
+ unique_lock<Lockable> make_unique_lock(Lockable& mtx, try_to_lock_t)
+ {
+ return unique_lock<Lockable> (mtx, try_to_lock);
+ }
+#if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS)
+
+#if ! defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ template <typename ...Lockable>
+ std::tuple<unique_lock<Lockable> ...> make_unique_locks(Lockable& ...mtx)
+ {
+ boost::lock(mtx...);
+ return std::tuple<unique_lock<Lockable> ...>(unique_lock<Lockable>(mtx, adopt_lock)...);
+ }
+#else
+ template <typename L1, typename L2>
+ std::tuple<unique_lock<L1>, unique_lock<L2> > make_unique_locks(L1& m1, L2& m2)
+ {
+ boost::lock(m1, m2);
+ return std::tuple<unique_lock<L1>,unique_lock<L2> >(
+ unique_lock<L1>(m1, adopt_lock),
+ unique_lock<L2>(m2, adopt_lock)
+ );
+ }
+ template <typename L1, typename L2, typename L3>
+ std::tuple<unique_lock<L1>, unique_lock<L2>, unique_lock<L3> > make_unique_locks(L1& m1, L2& m2, L3& m3)
+ {
+ boost::lock(m1, m2, m3);
+ return std::tuple<unique_lock<L1>,unique_lock<L2>,unique_lock<L3> >(
+ unique_lock<L1>(m1, adopt_lock),
+ unique_lock<L2>(m2, adopt_lock),
+ unique_lock<L3>(m3, adopt_lock)
+ );
+ }
+
+#endif
+#endif
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+#endif
diff --git a/boost/thread/lock_guard.hpp b/boost/thread/lock_guard.hpp
new file mode 100644
index 0000000000..4c2908af43
--- /dev/null
+++ b/boost/thread/lock_guard.hpp
@@ -0,0 +1,88 @@
+// 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)
+// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_LOCK_GUARD_HPP
+#define BOOST_THREAD_LOCK_GUARD_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/detail/lockable_wrapper.hpp>
+#include <boost/thread/lock_options.hpp>
+#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+#include <boost/thread/is_locked_by_this_thread.hpp>
+#include <boost/assert.hpp>
+#endif
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ template <typename Mutex>
+ class lock_guard
+ {
+ private:
+ Mutex& m;
+
+ public:
+ typedef Mutex mutex_type;
+ BOOST_THREAD_NO_COPYABLE( lock_guard )
+
+ explicit lock_guard(Mutex& m_) :
+ m(m_)
+ {
+ m.lock();
+ }
+
+ lock_guard(Mutex& m_, adopt_lock_t) :
+ m(m_)
+ {
+#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+ BOOST_ASSERT(is_locked_by_this_thread(m));
+#endif
+ }
+
+#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST
+ lock_guard(std::initializer_list<thread_detail::lockable_wrapper<Mutex> > l_) :
+ m(*(const_cast<thread_detail::lockable_wrapper<Mutex>*>(l_.begin())->m))
+ {
+ m.lock();
+ }
+
+ lock_guard(std::initializer_list<thread_detail::lockable_adopt_wrapper<Mutex> > l_) :
+ m(*(const_cast<thread_detail::lockable_adopt_wrapper<Mutex>*>(l_.begin())->m))
+ {
+#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+ BOOST_ASSERT(is_locked_by_this_thread(m));
+#endif
+ }
+
+#endif
+ ~lock_guard()
+ {
+ m.unlock();
+ }
+ };
+
+
+#if ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD
+ template <typename Lockable>
+ lock_guard<Lockable> make_lock_guard(Lockable& mtx)
+ {
+ return { thread_detail::lockable_wrapper<Lockable>(mtx) };
+ }
+ template <typename Lockable>
+ lock_guard<Lockable> make_lock_guard(Lockable& mtx, adopt_lock_t)
+ {
+ return { thread_detail::lockable_adopt_wrapper<Lockable>(mtx) };
+ }
+#endif
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/lock_options.hpp b/boost/thread/lock_options.hpp
new file mode 100644
index 0000000000..68899ca89f
--- /dev/null
+++ b/boost/thread/lock_options.hpp
@@ -0,0 +1,31 @@
+// 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)
+// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_LOCK_OPTIONS_HPP
+#define BOOST_THREAD_LOCK_OPTIONS_HPP
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ struct defer_lock_t
+ {
+ };
+ struct try_to_lock_t
+ {
+ };
+ struct adopt_lock_t
+ {
+ };
+
+ BOOST_CONSTEXPR_OR_CONST defer_lock_t defer_lock = {};
+ BOOST_CONSTEXPR_OR_CONST try_to_lock_t try_to_lock = {};
+ BOOST_CONSTEXPR_OR_CONST adopt_lock_t adopt_lock = {};
+
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/lock_traits.hpp b/boost/thread/lock_traits.hpp
new file mode 100644
index 0000000000..e45d822983
--- /dev/null
+++ b/boost/thread/lock_traits.hpp
@@ -0,0 +1,45 @@
+// 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)
+// (C) Copyright 2009-2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_LOCK_TRAITS_HPP
+#define BOOST_THREAD_LOCK_TRAITS_HPP
+
+#include <boost/thread/detail/config.hpp>
+//#include <boost/thread/detail/move.hpp>
+//#include <boost/thread/exceptions.hpp>
+//
+//#ifdef BOOST_THREAD_USES_CHRONO
+//#include <boost/chrono/time_point.hpp>
+//#include <boost/chrono/duration.hpp>
+//#endif
+
+#include <boost/type_traits/integral_constant.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+/**
+ * An strict lock is a lock ensuring the mutex is locked on the scope of the lock
+ * There is no single way to define a strict lock as the strict_lock and
+ * nesteed_strict_lock shows. So we need a metafunction that states if a
+ * lock is a strict lock "sur parole".
+ */
+
+template <typename Lock>
+struct is_strict_lock_sur_parolle : false_type {};
+
+
+template <typename Lock>
+struct is_strict_lock_sur_parole : is_strict_lock_sur_parolle<Lock> {};
+
+template <typename Lock>
+struct is_strict_lock : is_strict_lock_sur_parole<Lock> {};
+
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/lock_types.hpp b/boost/thread/lock_types.hpp
new file mode 100644
index 0000000000..2b73edfb02
--- /dev/null
+++ b/boost/thread/lock_types.hpp
@@ -0,0 +1,1230 @@
+// 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)
+// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_LOCK_TYPES_HPP
+#define BOOST_THREAD_LOCK_TYPES_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/exceptions.hpp>
+#include <boost/thread/lock_options.hpp>
+#include <boost/thread/lockable_traits.hpp>
+#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+#include <boost/thread/is_locked_by_this_thread.hpp>
+#endif
+#include <boost/thread/thread_time.hpp>
+
+#include <boost/assert.hpp>
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/time_point.hpp>
+#include <boost/chrono/duration.hpp>
+#endif
+#include <boost/detail/workaround.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ struct xtime;
+
+ template <typename Mutex>
+ class shared_lock;
+
+ template <typename Mutex>
+ class upgrade_lock;
+
+ template <typename Mutex>
+ class unique_lock;
+
+ namespace detail
+ {
+ template <typename Mutex>
+ class try_lock_wrapper;
+ }
+
+#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
+ namespace sync
+ {
+ template<typename T>
+ struct is_basic_lockable<unique_lock<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<typename T>
+ struct is_lockable<unique_lock<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+
+ template<typename T>
+ struct is_basic_lockable<shared_lock<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<typename T>
+ struct is_lockable<shared_lock<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+
+ template<typename T>
+ struct is_basic_lockable<upgrade_lock<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<typename T>
+ struct is_lockable<upgrade_lock<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+
+ template<typename T>
+ struct is_basic_lockable<detail::try_lock_wrapper<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<typename T>
+ struct is_lockable<detail::try_lock_wrapper<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ }
+#endif
+
+
+ template <typename Mutex>
+ class unique_lock
+ {
+ private:
+ Mutex* m;
+ bool is_locked;
+
+ private:
+ explicit unique_lock(upgrade_lock<Mutex>&);
+ unique_lock& operator=(upgrade_lock<Mutex>& other);
+ public:
+ typedef Mutex mutex_type;
+ BOOST_THREAD_MOVABLE_ONLY( unique_lock)
+
+#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
+#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
+ unique_lock(const volatile unique_lock&);
+#endif
+#endif
+ unique_lock()BOOST_NOEXCEPT :
+ m(0),is_locked(false)
+ {}
+
+ explicit unique_lock(Mutex& m_) :
+ m(&m_), is_locked(false)
+ {
+ lock();
+ }
+ unique_lock(Mutex& m_, adopt_lock_t) :
+ m(&m_), is_locked(true)
+ {
+#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+ BOOST_ASSERT(is_locked_by_this_thread(m));
+#endif
+ }
+ unique_lock(Mutex& m_, defer_lock_t)BOOST_NOEXCEPT:
+ m(&m_),is_locked(false)
+ {}
+ unique_lock(Mutex& m_, try_to_lock_t) :
+ m(&m_), is_locked(false)
+ {
+ try_lock();
+ }
+#if defined BOOST_THREAD_USES_DATETIME
+ template<typename TimeDuration>
+ unique_lock(Mutex& m_,TimeDuration const& target_time):
+ m(&m_),is_locked(false)
+ {
+ timed_lock(target_time);
+ }
+ unique_lock(Mutex& m_,system_time const& target_time):
+ m(&m_),is_locked(false)
+ {
+ timed_lock(target_time);
+ }
+#endif
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Clock, class Duration>
+ unique_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
+ : m(&mtx), is_locked(mtx.try_lock_until(t))
+ {
+ }
+ template <class Rep, class Period>
+ unique_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
+ : m(&mtx), is_locked(mtx.try_lock_for(d))
+ {
+ }
+#endif
+
+ unique_lock(BOOST_THREAD_RV_REF(unique_lock) other) BOOST_NOEXCEPT:
+ m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
+ {
+ BOOST_THREAD_RV(other).is_locked=false;
+ BOOST_THREAD_RV(other).m=0;
+ }
+
+ BOOST_THREAD_EXPLICIT_LOCK_CONVERSION unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other);
+
+#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
+ //std-2104 unique_lock move-assignment should not be noexcept
+ unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
+ {
+ unique_lock temp(::boost::move(other));
+ swap(temp);
+ return *this;
+ }
+#endif
+
+ //std-2104 unique_lock move-assignment should not be noexcept
+ unique_lock& operator=(BOOST_THREAD_RV_REF(unique_lock) other) //BOOST_NOEXCEPT
+ {
+ unique_lock temp(::boost::move(other));
+ swap(temp);
+ return *this;
+ }
+#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
+#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
+ unique_lock& operator=(unique_lock<Mutex> other)
+ {
+ swap(other);
+ return *this;
+ }
+#endif // BOOST_WORKAROUND
+#endif
+
+ // Conversion from upgrade locking
+ unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul, try_to_lock_t)
+ : m(0),is_locked(false)
+ {
+ if (BOOST_THREAD_RV(ul).owns_lock())
+ {
+ if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock())
+ {
+ m = BOOST_THREAD_RV(ul).release();
+ is_locked = true;
+ }
+ }
+ else
+ {
+ m = BOOST_THREAD_RV(ul).release();
+ }
+ }
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Clock, class Duration>
+ unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul,
+ const chrono::time_point<Clock, Duration>& abs_time)
+ : m(0),is_locked(false)
+ {
+ if (BOOST_THREAD_RV(ul).owns_lock())
+ {
+ if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_until(abs_time))
+ {
+ m = BOOST_THREAD_RV(ul).release();
+ is_locked = true;
+ }
+ }
+ else
+ {
+ m = BOOST_THREAD_RV(ul).release();
+ }
+ }
+
+ template <class Rep, class Period>
+ unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul,
+ const chrono::duration<Rep, Period>& rel_time)
+ : m(0),is_locked(false)
+ {
+ if (BOOST_THREAD_RV(ul).owns_lock())
+ {
+ if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_for(rel_time))
+ {
+ m = BOOST_THREAD_RV(ul).release();
+ is_locked = true;
+ }
+ }
+ else
+ {
+ m = BOOST_THREAD_RV(ul).release();
+ }
+ }
+#endif
+
+#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ // Conversion from shared locking
+ unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, try_to_lock_t)
+ : m(0),is_locked(false)
+ {
+ if (BOOST_THREAD_RV(sl).owns_lock())
+ {
+ if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock())
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ is_locked = true;
+ }
+ }
+ else
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ }
+ }
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Clock, class Duration>
+ unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
+ const chrono::time_point<Clock, Duration>& abs_time)
+ : m(0),is_locked(false)
+ {
+ if (BOOST_THREAD_RV(sl).owns_lock())
+ {
+ if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_until(abs_time))
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ is_locked = true;
+ }
+ }
+ else
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ }
+ }
+
+ template <class Rep, class Period>
+ unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
+ const chrono::duration<Rep, Period>& rel_time)
+ : m(0),is_locked(false)
+ {
+ if (BOOST_THREAD_RV(sl).owns_lock())
+ {
+ if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_for(rel_time))
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ is_locked = true;
+ }
+ }
+ else
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ }
+ }
+#endif // BOOST_THREAD_USES_CHRONO
+#endif // BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+
+ void swap(unique_lock& other)BOOST_NOEXCEPT
+ {
+ std::swap(m,other.m);
+ std::swap(is_locked,other.is_locked);
+ }
+
+ ~unique_lock()
+ {
+ if (owns_lock())
+ {
+ m->unlock();
+ }
+ }
+ void lock()
+ {
+ if (m == 0)
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
+ }
+ if (owns_lock())
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
+ }
+ m->lock();
+ is_locked = true;
+ }
+ bool try_lock()
+ {
+ if (m == 0)
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
+ }
+ if (owns_lock())
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
+ }
+ is_locked = m->try_lock();
+ return is_locked;
+ }
+#if defined BOOST_THREAD_USES_DATETIME
+ template<typename TimeDuration>
+ bool timed_lock(TimeDuration const& relative_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
+ }
+ is_locked=m->timed_lock(relative_time);
+ return is_locked;
+ }
+
+ bool timed_lock(::boost::system_time const& absolute_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
+ }
+ is_locked=m->timed_lock(absolute_time);
+ return is_locked;
+ }
+ bool timed_lock(::boost::xtime const& absolute_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
+ }
+ is_locked=m->timed_lock(absolute_time);
+ return is_locked;
+ }
+#endif
+#ifdef BOOST_THREAD_USES_CHRONO
+
+ template <class Rep, class Period>
+ bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
+ }
+ is_locked=m->try_lock_for(rel_time);
+ return is_locked;
+ }
+ template <class Clock, class Duration>
+ bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
+ }
+ is_locked=m->try_lock_until(abs_time);
+ return is_locked;
+ }
+#endif
+
+ void unlock()
+ {
+ if (m == 0)
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
+ }
+ if (!owns_lock())
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock doesn't own the mutex"));
+ }
+ m->unlock();
+ is_locked = false;
+ }
+
+#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+ typedef void (unique_lock::*bool_type)();
+ operator bool_type() const BOOST_NOEXCEPT
+ {
+ return is_locked?&unique_lock::lock:0;
+ }
+ bool operator!() const BOOST_NOEXCEPT
+ {
+ return !owns_lock();
+ }
+#else
+ explicit operator bool() const BOOST_NOEXCEPT
+ {
+ return owns_lock();
+ }
+#endif
+ bool owns_lock() const BOOST_NOEXCEPT
+ {
+ return is_locked;
+ }
+
+ Mutex* mutex() const BOOST_NOEXCEPT
+ {
+ return m;
+ }
+
+ Mutex* release()BOOST_NOEXCEPT
+ {
+ Mutex* const res=m;
+ m=0;
+ is_locked=false;
+ return res;
+ }
+
+ friend class shared_lock<Mutex> ;
+ friend class upgrade_lock<Mutex> ;
+ };
+
+ template<typename Mutex>
+ void swap(unique_lock<Mutex>& lhs, unique_lock<Mutex>& rhs)
+ BOOST_NOEXCEPT
+ {
+ lhs.swap(rhs);
+ }
+
+ BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
+
+ template<typename Mutex>
+ class shared_lock
+ {
+ protected:
+ Mutex* m;
+ bool is_locked;
+
+ public:
+ typedef Mutex mutex_type;
+ BOOST_THREAD_MOVABLE_ONLY(shared_lock)
+
+ shared_lock() BOOST_NOEXCEPT:
+ m(0),is_locked(false)
+ {}
+
+ explicit shared_lock(Mutex& m_):
+ m(&m_),is_locked(false)
+ {
+ lock();
+ }
+ shared_lock(Mutex& m_,adopt_lock_t):
+ m(&m_),is_locked(true)
+ {
+#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+ BOOST_ASSERT(is_locked_by_this_thread(m));
+#endif
+ }
+ shared_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT:
+ m(&m_),is_locked(false)
+ {}
+ shared_lock(Mutex& m_,try_to_lock_t):
+ m(&m_),is_locked(false)
+ {
+ try_lock();
+ }
+#if defined BOOST_THREAD_USES_DATETIME
+ shared_lock(Mutex& m_,system_time const& target_time):
+ m(&m_),is_locked(false)
+ {
+ timed_lock(target_time);
+ }
+#endif
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Clock, class Duration>
+ shared_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
+ : m(&mtx), is_locked(mtx.try_lock_shared_until(t))
+ {
+ }
+ template <class Rep, class Period>
+ shared_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
+ : m(&mtx), is_locked(mtx.try_lock_shared_for(d))
+ {
+ }
+#endif
+
+ shared_lock(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
+ m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
+ {
+ BOOST_THREAD_RV(other).is_locked=false;
+ BOOST_THREAD_RV(other).m=0;
+ }
+
+ BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other):
+ m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
+ {
+ if(is_locked)
+ {
+ m->unlock_and_lock_shared();
+ }
+ BOOST_THREAD_RV(other).is_locked=false;
+ BOOST_THREAD_RV(other).m=0;
+ }
+
+ BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other):
+ m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
+ {
+ if(is_locked)
+ {
+ m->unlock_upgrade_and_lock_shared();
+ }
+ BOOST_THREAD_RV(other).is_locked=false;
+ BOOST_THREAD_RV(other).m=0;
+ }
+
+ //std-2104 unique_lock move-assignment should not be noexcept
+ shared_lock& operator=(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
+ {
+ shared_lock temp(::boost::move(other));
+ swap(temp);
+ return *this;
+ }
+#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
+ shared_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other)
+ {
+ shared_lock temp(::boost::move(other));
+ swap(temp);
+ return *this;
+ }
+
+ shared_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other)
+ {
+ shared_lock temp(::boost::move(other));
+ swap(temp);
+ return *this;
+ }
+#endif
+
+ void swap(shared_lock& other) BOOST_NOEXCEPT
+ {
+ std::swap(m,other.m);
+ std::swap(is_locked,other.is_locked);
+ }
+
+ Mutex* mutex() const BOOST_NOEXCEPT
+ {
+ return m;
+ }
+
+ Mutex* release() BOOST_NOEXCEPT
+ {
+ Mutex* const res=m;
+ m=0;
+ is_locked=false;
+ return res;
+ }
+
+ ~shared_lock()
+ {
+ if(owns_lock())
+ {
+ m->unlock_shared();
+ }
+ }
+ void lock()
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
+ }
+ m->lock_shared();
+ is_locked=true;
+ }
+ bool try_lock()
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
+ }
+ is_locked=m->try_lock_shared();
+ return is_locked;
+ }
+#if defined BOOST_THREAD_USES_DATETIME
+ bool timed_lock(boost::system_time const& target_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
+ }
+ is_locked=m->timed_lock_shared(target_time);
+ return is_locked;
+ }
+ template<typename Duration>
+ bool timed_lock(Duration const& target_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
+ }
+ is_locked=m->timed_lock_shared(target_time);
+ return is_locked;
+ }
+#endif
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
+ }
+ is_locked=m->try_lock_shared_for(rel_time);
+ return is_locked;
+ }
+ template <class Clock, class Duration>
+ bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
+ }
+ is_locked=m->try_lock_shared_until(abs_time);
+ return is_locked;
+ }
+#endif
+ void unlock()
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if(!owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock doesn't own the mutex"));
+ }
+ m->unlock_shared();
+ is_locked=false;
+ }
+
+#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+ typedef void (shared_lock<Mutex>::*bool_type)();
+ operator bool_type() const BOOST_NOEXCEPT
+ {
+ return is_locked?&shared_lock::lock:0;
+ }
+ bool operator!() const BOOST_NOEXCEPT
+ {
+ return !owns_lock();
+ }
+#else
+ explicit operator bool() const BOOST_NOEXCEPT
+ {
+ return owns_lock();
+ }
+#endif
+ bool owns_lock() const BOOST_NOEXCEPT
+ {
+ return is_locked;
+ }
+
+ };
+
+ BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) shared_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
+
+ template<typename Mutex>
+ void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs) BOOST_NOEXCEPT
+ {
+ lhs.swap(rhs);
+ }
+
+ template <typename Mutex>
+ class upgrade_lock
+ {
+ protected:
+ Mutex* m;
+ bool is_locked;
+
+ public:
+ typedef Mutex mutex_type;
+ BOOST_THREAD_MOVABLE_ONLY( upgrade_lock)
+
+ upgrade_lock()BOOST_NOEXCEPT:
+ m(0),is_locked(false)
+ {}
+
+ explicit upgrade_lock(Mutex& m_) :
+ m(&m_), is_locked(false)
+ {
+ lock();
+ }
+ upgrade_lock(Mutex& m_, adopt_lock_t) :
+ m(&m_), is_locked(true)
+ {
+#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+ BOOST_ASSERT(is_locked_by_this_thread(m));
+#endif
+ }
+ upgrade_lock(Mutex& m_, defer_lock_t)BOOST_NOEXCEPT:
+ m(&m_),is_locked(false)
+ {}
+ upgrade_lock(Mutex& m_, try_to_lock_t) :
+ m(&m_), is_locked(false)
+ {
+ try_lock();
+ }
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Clock, class Duration>
+ upgrade_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
+ : m(&mtx), is_locked(mtx.try_lock_upgrade_until(t))
+ {
+ }
+ template <class Rep, class Period>
+ upgrade_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
+ : m(&mtx), is_locked(mtx.try_lock_upgrade_for(d))
+ {
+ }
+#endif
+
+ upgrade_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
+ m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
+ {
+ BOOST_THREAD_RV(other).is_locked=false;
+ BOOST_THREAD_RV(other).m=0;
+ }
+
+ BOOST_THREAD_EXPLICIT_LOCK_CONVERSION upgrade_lock(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other):
+ m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
+ {
+ if(is_locked)
+ {
+ m->unlock_and_lock_upgrade();
+ }
+ BOOST_THREAD_RV(other).is_locked=false;
+ BOOST_THREAD_RV(other).m=0;
+ }
+
+ //std-2104 unique_lock move-assignment should not be noexcept
+ upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
+ {
+ upgrade_lock temp(::boost::move(other));
+ swap(temp);
+ return *this;
+ }
+
+#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
+ upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other)
+ {
+ upgrade_lock temp(::boost::move(other));
+ swap(temp);
+ return *this;
+ }
+#endif
+
+#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ // Conversion from shared locking
+ upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, try_to_lock_t)
+ : m(0),is_locked(false)
+ {
+ if (BOOST_THREAD_RV(sl).owns_lock())
+ {
+ if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade())
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ is_locked = true;
+ }
+ }
+ else
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ }
+ }
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Clock, class Duration>
+ upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
+ const chrono::time_point<Clock, Duration>& abs_time)
+ : m(0),is_locked(false)
+ {
+ if (BOOST_THREAD_RV(sl).owns_lock())
+ {
+ if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_until(abs_time))
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ is_locked = true;
+ }
+ }
+ else
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ }
+ }
+
+ template <class Rep, class Period>
+ upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
+ const chrono::duration<Rep, Period>& rel_time)
+ : m(0),is_locked(false)
+ {
+ if (BOOST_THREAD_RV(sl).owns_lock())
+ {
+ if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_for(rel_time))
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ is_locked = true;
+ }
+ }
+ else
+ {
+ m = BOOST_THREAD_RV(sl).release();
+ }
+ }
+#endif // BOOST_THREAD_USES_CHRONO
+#endif // BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ void swap(upgrade_lock& other)BOOST_NOEXCEPT
+ {
+ std::swap(m,other.m);
+ std::swap(is_locked,other.is_locked);
+ }
+ Mutex* mutex() const BOOST_NOEXCEPT
+ {
+ return m;
+ }
+
+ Mutex* release()BOOST_NOEXCEPT
+ {
+ Mutex* const res=m;
+ m=0;
+ is_locked=false;
+ return res;
+ }
+ ~upgrade_lock()
+ {
+ if (owns_lock())
+ {
+ m->unlock_upgrade();
+ }
+ }
+ void lock()
+ {
+ if (m == 0)
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if (owns_lock())
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
+ }
+ m->lock_upgrade();
+ is_locked = true;
+ }
+ bool try_lock()
+ {
+ if (m == 0)
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if (owns_lock())
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
+ }
+ is_locked = m->try_lock_upgrade();
+ return is_locked;
+ }
+ void unlock()
+ {
+ if (m == 0)
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if (!owns_lock())
+ {
+ boost::throw_exception(
+ boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock doesn't own the mutex"));
+ }
+ m->unlock_upgrade();
+ is_locked = false;
+ }
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
+ }
+ is_locked=m->try_lock_upgrade_for(rel_time);
+ return is_locked;
+ }
+ template <class Clock, class Duration>
+ bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+ if(m==0)
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
+ }
+ if(owns_lock())
+ {
+ boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
+ }
+ is_locked=m->try_lock_upgrade_until(abs_time);
+ return is_locked;
+ }
+#endif
+#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+ typedef void (upgrade_lock::*bool_type)();
+ operator bool_type() const BOOST_NOEXCEPT
+ {
+ return is_locked?&upgrade_lock::lock:0;
+ }
+ bool operator!() const BOOST_NOEXCEPT
+ {
+ return !owns_lock();
+ }
+#else
+ explicit operator bool() const BOOST_NOEXCEPT
+ {
+ return owns_lock();
+ }
+#endif
+ bool owns_lock() const BOOST_NOEXCEPT
+ {
+ return is_locked;
+ }
+ friend class shared_lock<Mutex> ;
+ friend class unique_lock<Mutex> ;
+ };
+
+ template<typename Mutex>
+ void swap(upgrade_lock<Mutex>& lhs, upgrade_lock<Mutex>& rhs)
+ BOOST_NOEXCEPT
+ {
+ lhs.swap(rhs);
+ }
+
+ BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
+
+ template<typename Mutex>
+ unique_lock<Mutex>::unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other):
+ m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
+ {
+ if(is_locked)
+ {
+ m->unlock_upgrade_and_lock();
+ }
+ BOOST_THREAD_RV(other).release();
+ }
+
+ template <class Mutex>
+ class upgrade_to_unique_lock
+ {
+ private:
+ upgrade_lock<Mutex>* source;
+ unique_lock<Mutex> exclusive;
+
+ public:
+ typedef Mutex mutex_type;
+ BOOST_THREAD_MOVABLE_ONLY( upgrade_to_unique_lock)
+
+ explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_) :
+ source(&m_), exclusive(::boost::move(*source))
+ {
+ }
+ ~upgrade_to_unique_lock()
+ {
+ if (source)
+ {
+ *source = BOOST_THREAD_MAKE_RV_REF(upgrade_lock<Mutex> (::boost::move(exclusive)));
+ }
+ }
+
+ upgrade_to_unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
+ source(BOOST_THREAD_RV(other).source),exclusive(::boost::move(BOOST_THREAD_RV(other).exclusive))
+ {
+ BOOST_THREAD_RV(other).source=0;
+ }
+
+ //std-2104 unique_lock move-assignment should not be noexcept
+ upgrade_to_unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT
+ {
+ upgrade_to_unique_lock temp(other);
+ swap(temp);
+ return *this;
+ }
+
+ void swap(upgrade_to_unique_lock& other)BOOST_NOEXCEPT
+ {
+ std::swap(source,other.source);
+ exclusive.swap(other.exclusive);
+ }
+
+#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+ typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&);
+ operator bool_type() const BOOST_NOEXCEPT
+ {
+ return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0;
+ }
+ bool operator!() const BOOST_NOEXCEPT
+ {
+ return !owns_lock();
+ }
+#else
+ explicit operator bool() const BOOST_NOEXCEPT
+ {
+ return owns_lock();
+ }
+#endif
+
+ bool owns_lock() const BOOST_NOEXCEPT
+ {
+ return exclusive.owns_lock();
+ }
+ Mutex* mutex() const BOOST_NOEXCEPT
+ {
+ return exclusive.mutex();
+ }
+ };
+
+BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_to_unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
+
+namespace detail
+{
+ template<typename Mutex>
+ class try_lock_wrapper:
+private unique_lock<Mutex>
+ {
+ typedef unique_lock<Mutex> base;
+ public:
+ BOOST_THREAD_MOVABLE_ONLY(try_lock_wrapper)
+
+ try_lock_wrapper()
+ {}
+
+ explicit try_lock_wrapper(Mutex& m):
+ base(m,try_to_lock)
+ {}
+
+ try_lock_wrapper(Mutex& m_,adopt_lock_t):
+ base(m_,adopt_lock)
+ {
+#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+ BOOST_ASSERT(is_locked_by_this_thread(m_));
+#endif
+ }
+ try_lock_wrapper(Mutex& m_,defer_lock_t):
+ base(m_,defer_lock)
+ {}
+ try_lock_wrapper(Mutex& m_,try_to_lock_t):
+ base(m_,try_to_lock)
+ {}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
+ base(::boost::move(other))
+ {}
+
+#elif defined BOOST_THREAD_USES_MOVE
+ try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
+ base(::boost::move(static_cast<base&>(other)))
+ {}
+
+#else
+ try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
+ base(BOOST_THREAD_RV_REF(base)(*other))
+ {}
+#endif
+ try_lock_wrapper& operator=(BOOST_THREAD_RV_REF_BEG try_lock_wrapper<Mutex> BOOST_THREAD_RV_REF_END other)
+ {
+ try_lock_wrapper temp(other);
+ swap(temp);
+ return *this;
+ }
+ void swap(try_lock_wrapper& other)
+ {
+ base::swap(other);
+ }
+ void lock()
+ {
+ base::lock();
+ }
+ bool try_lock()
+ {
+ return base::try_lock();
+ }
+ void unlock()
+ {
+ base::unlock();
+ }
+ bool owns_lock() const
+ {
+ return base::owns_lock();
+ }
+ Mutex* mutex() const BOOST_NOEXCEPT
+ {
+ return base::mutex();
+ }
+ Mutex* release()
+ {
+ return base::release();
+ }
+
+#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+ typedef typename base::bool_type bool_type;
+ operator bool_type() const
+ {
+ return base::operator bool_type();
+ }
+ bool operator!() const
+ {
+ return !this->owns_lock();
+ }
+#else
+ explicit operator bool() const
+ {
+ return owns_lock();
+ }
+#endif
+ };
+
+ template<typename Mutex>
+ void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs)
+ {
+ lhs.swap(rhs);
+ }
+}
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/lockable_adapter.hpp b/boost/thread/lockable_adapter.hpp
new file mode 100644
index 0000000000..93d9ba5023
--- /dev/null
+++ b/boost/thread/lockable_adapter.hpp
@@ -0,0 +1,226 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_THREAD_LOCKABLE_ADAPTER_HPP
+#define BOOST_THREAD_LOCKABLE_ADAPTER_HPP
+
+#include <boost/thread/detail/delete.hpp>
+#include <boost/chrono/chrono.hpp>
+
+namespace boost
+{
+
+ //[basic_lockable_adapter
+ template <typename BasicLockable>
+ class basic_lockable_adapter
+ {
+ public:
+ typedef BasicLockable mutex_type;
+
+ protected:
+ mutex_type& lockable() const
+ {
+ return lockable_;
+ }
+ mutable mutex_type lockable_; /*< mutable so that it can be modified by const functions >*/
+ public:
+
+ BOOST_THREAD_NO_COPYABLE( basic_lockable_adapter) /*< no copyable >*/
+
+ basic_lockable_adapter()
+ {}
+
+ void lock() const
+ {
+ lockable().lock();
+ }
+ void unlock() const
+ {
+ lockable().unlock();
+ }
+
+ };
+ //]
+
+ //[lockable_adapter
+ template <typename Lockable>
+ class lockable_adapter : public basic_lockable_adapter<Lockable>
+ {
+ public:
+ typedef Lockable mutex_type;
+
+ bool try_lock() const
+ {
+ return this->lockable().try_lock();
+ }
+ };
+ //]
+
+ //[timed_lockable_adapter
+ template <typename TimedLock>
+ class timed_lockable_adapter: public lockable_adapter<TimedLock>
+ {
+ public:
+ typedef TimedLock mutex_type;
+
+ template <typename Clock, typename Duration>
+ bool try_lock_until(chrono::time_point<Clock, Duration> const & abs_time) const
+ {
+ return this->lockable().try_lock_until(abs_time);
+ }
+ template <typename Rep, typename Period>
+ bool try_lock_for(chrono::duration<Rep, Period> const & rel_time) const
+ {
+ return this->lockable().try_lock_for(rel_time);
+ }
+
+ };
+ //]
+
+ //[shared_lockable_adapter
+ template <typename SharableLock>
+ class shared_lockable_adapter: public timed_lockable_adapter<SharableLock>
+ {
+ public:
+ typedef SharableLock mutex_type;
+
+ void lock_shared() const
+ {
+ this->lockable().lock_shared();
+ }
+ bool try_lock_shared() const
+ {
+ return this->lockable().try_lock_shared();
+ }
+ void unlock_shared() const
+ {
+ this->lockable().unlock_shared();
+ }
+
+ template <typename Clock, typename Duration>
+ bool try_lock_shared_until(chrono::time_point<Clock, Duration> const & abs_time) const
+ {
+ return this->lockable().try_lock_shared_until(abs_time);
+ }
+ template <typename Rep, typename Period>
+ bool try_lock_shared_for(chrono::duration<Rep, Period> const & rel_time) const
+ {
+ return this->lockable().try_lock_shared_for(rel_time);
+ }
+
+ };
+
+ //]
+
+ //[upgrade_lockable_adapter
+ template <typename UpgradableLock>
+ class upgrade_lockable_adapter: public shared_lockable_adapter<UpgradableLock>
+ {
+ public:
+ typedef UpgradableLock mutex_type;
+
+ void lock_upgrade() const
+ {
+ this->lockable().lock_upgrade();
+ }
+
+ bool try_lock_upgrade() const
+ {
+ return this->lockable().try_lock_upgrade();
+ }
+
+ void unlock_upgrade() const
+ {
+ this->lockable().unlock_upgrade();
+ }
+
+ template <typename Clock, typename Duration>
+ bool try_lock_upgrade_until(chrono::time_point<Clock, Duration> const & abs_time) const
+ {
+ return this->lockable().try_lock_upgrade_until(abs_time);
+ }
+ template <typename Rep, typename Period>
+ bool try_lock_upgrade_for(chrono::duration<Rep, Period> const & rel_time) const
+ {
+ return this->lockable().try_lock_upgrade_for(rel_time);
+ }
+
+ bool try_unlock_shared_and_lock() const
+ {
+ return this->lockable().try_unlock_shared_and_lock();
+ }
+
+ template <typename Clock, typename Duration>
+ bool try_unlock_shared_and_lock_until(chrono::time_point<Clock, Duration> const & abs_time) const
+ {
+ return this->lockable().try_unlock_shared_and_lock_until(abs_time);
+ }
+ template <typename Rep, typename Period>
+ bool try_unlock_shared_and_lock_for(chrono::duration<Rep, Period> const & rel_time) const
+ {
+ return this->lockable().try_unlock_shared_and_lock_for(rel_time);
+ }
+
+ void unlock_and_lock_shared() const
+ {
+ this->lockable().unlock_and_lock_shared();
+ }
+
+ bool try_unlock_shared_and_lock_upgrade() const
+ {
+ return this->lockable().try_unlock_shared_and_lock_upgrade();
+ }
+
+ template <typename Clock, typename Duration>
+ bool try_unlock_shared_and_lock_upgrade_until(chrono::time_point<Clock, Duration> const & abs_time) const
+ {
+ return this->lockable().try_unlock_shared_and_lock_upgrade_until(abs_time);
+ }
+ template <typename Rep, typename Period>
+ bool try_unlock_shared_and_lock_upgrade_for(chrono::duration<Rep, Period> const & rel_time) const
+ {
+ return this->lockable().try_unlock_shared_and_lock_upgrade_for(rel_time);
+ }
+
+ void unlock_and_lock_upgrade() const
+ {
+ this->lockable().unlock_and_lock_upgrade();
+ }
+
+ void unlock_upgrade_and_lock() const
+ {
+ this->lockable().unlock_upgrade_and_lock();
+ }
+
+ bool try_unlock_upgrade_and_lock() const
+ {
+ return this->lockable().try_unlock_upgrade_and_lock();
+ }
+ template <typename Clock, typename Duration>
+ bool try_unlock_upgrade_and_lock_until(chrono::time_point<Clock, Duration> const & abs_time) const
+ {
+ return this->lockable().try_unlock_upgrade_and_lock_until(abs_time);
+ }
+ template <typename Rep, typename Period>
+ bool try_unlock_upgrade_and_lock_for(chrono::duration<Rep, Period> const & rel_time) const
+ {
+ return this->lockable().try_unlock_upgrade_and_lock_for(rel_time);
+ }
+
+ void unlock_upgrade_and_lock_shared() const
+ {
+ this->lockable().unlock_upgrade_and_lock_shared();
+ }
+
+ };
+//]
+
+}
+#endif
diff --git a/boost/thread/lockable_concepts.hpp b/boost/thread/lockable_concepts.hpp
new file mode 100644
index 0000000000..bedd962e3b
--- /dev/null
+++ b/boost/thread/lockable_concepts.hpp
@@ -0,0 +1,157 @@
+// (C) Copyright 2012 Vicente Botet
+//
+// 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)
+
+#ifndef BOOST_THREAD_LOCKABLE_CONCEPTS_HPP
+#define BOOST_THREAD_LOCKABLE_CONCEPTS_HPP
+
+#include <boost/chrono/chrono.hpp>
+#include <boost/concept_check.hpp>
+
+namespace boost
+{
+
+ /**
+ * BasicLockable object supports the basic features
+ * required to delimit a critical region
+ * Supports the basic lock and unlock functions.
+ */
+
+ //[BasicLockable
+ template <typename Mutex>
+ struct BasicLockable
+ {
+
+ BOOST_CONCEPT_USAGE(BasicLockable)
+ {
+ l.lock();
+ l.unlock();
+ }
+ BasicLockable() : l(*static_cast<Mutex*>(0)) {}
+ private:
+ BasicLockable operator=(BasicLockable const&);
+
+ Mutex& l;
+ }
+ ;
+ //]
+ /**
+ * Lockable extends BasicLockable
+ * with try_lock functions.
+ */
+
+ //[Lockable
+ template <typename Mutex>
+ struct Lockable
+ {
+ BOOST_CONCEPT_ASSERT(( BasicLockable<Mutex> ));
+
+ BOOST_CONCEPT_USAGE(Lockable)
+ {
+ if (l.try_lock()) return;
+ }
+ Lockable() : l(*static_cast<Mutex*>(0)) {}
+ private:
+ Lockable operator=(Lockable const&);
+ Mutex& l;
+ };
+ //]
+
+ /**
+ * TimedLockable object extends Lockable
+ * with timed lock functions: try_lock_until and try_lock_for and the exception based lock_until and lock_for
+ */
+
+ //[TimedLockable
+ template <typename Mutex>
+ struct TimedLockable
+ {
+ BOOST_CONCEPT_ASSERT(( Lockable<Mutex> ));
+
+ BOOST_CONCEPT_USAGE(TimedLockable)
+ {
+ if (l.try_lock_until(t)) return;
+ if (l.try_lock_for(d)) return;
+ }
+ TimedLockable() : l(*static_cast<Mutex*>(0)) {}
+ private:
+ TimedLockable operator=(TimedLockable const&);
+ Mutex& l;
+ chrono::system_clock::time_point t;
+ chrono::system_clock::duration d;
+ };
+ //]
+
+ /**
+ * SharedLockable object extends TimedLockable
+ * with the lock_shared, lock_shared_until, lock_shared_for, try_lock_shared_until, try_lock_shared
+ * and unlock_shared functions
+ */
+ //[SharedLockable
+ template <typename Mutex>
+ struct SharedLockable
+ {
+ BOOST_CONCEPT_ASSERT(( TimedLockable<Mutex> ));
+
+ BOOST_CONCEPT_USAGE(SharedLockable)
+ {
+ l.lock_shared();
+ l.unlock_shared();
+ if (l.try_lock_shared()) return;
+ if (l.try_lock_shared_until(t)) return;
+ if (l.try_lock_shared_for(d)) return;
+ }
+ SharedLockable() : l(*static_cast<Mutex*>(0)) {}
+ private:
+ SharedLockable operator=(SharedLockable const&);
+ Mutex& l;
+ chrono::system_clock::time_point t;
+ chrono::system_clock::duration d;
+ };
+ //]
+
+ /**
+ * UpgradeLockable object extends SharedLockable
+ * with the lock_upgrade, lock_upgrade_until, unlock_upgrade_and_lock,
+ * unlock_and_lock_shared and unlock_upgrade_and_lock_shared functions
+ */
+
+ //[UpgradeLockable
+ template <typename Mutex>
+ struct UpgradeLockable
+ {
+ BOOST_CONCEPT_ASSERT(( SharedLockable<Mutex> ));
+
+ BOOST_CONCEPT_USAGE(UpgradeLockable)
+ {
+ l.lock_upgrade();
+ l.unlock_upgrade();
+ if (l.try_lock_upgrade()) return;
+ if (l.try_lock_upgrade_until(t)) return;
+ if (l.try_lock_upgrade_for(d)) return;
+ if (l.try_unlock_shared_and_lock()) return;
+ if (l.try_unlock_shared_and_lock_until(t)) return;
+ if (l.try_unlock_shared_and_lock_for(d)) return;
+ l.unlock_and_lock_shared();
+ if (l.try_unlock_shared_and_lock_upgrade()) return;
+ if (l.try_unlock_shared_and_lock_upgrade_until(t)) return;
+ if (l.try_unlock_shared_and_lock_upgrade_for(d)) return;
+ l.unlock_and_lock_upgrade();
+ l.unlock_upgrade_and_lock();
+ if (l.try_unlock_upgrade_and_lock()) return;
+ if (l.try_unlock_upgrade_and_lock_until(t)) return;
+ if (l.try_unlock_upgrade_and_lock_for(d)) return;
+ l.unlock_upgrade_and_lock_shared();
+ }
+ UpgradeLockable() : l(*static_cast<Mutex*>(0)) {}
+ private:
+ UpgradeLockable operator=(UpgradeLockable const&);
+ Mutex& l;
+ chrono::system_clock::time_point t;
+ chrono::system_clock::duration d;
+ };
+ //]
+
+}
+#endif
diff --git a/boost/thread/lockable_traits.hpp b/boost/thread/lockable_traits.hpp
new file mode 100644
index 0000000000..8a17ae72d3
--- /dev/null
+++ b/boost/thread/lockable_traits.hpp
@@ -0,0 +1,207 @@
+// 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)
+// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_LOCKABLE_TRAITS_HPP
+#define BOOST_THREAD_LOCKABLE_TRAITS_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#include <boost/assert.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/type_traits/is_class.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+// todo make use of integral_constant, true_type and false_type
+
+namespace boost
+{
+ namespace sync
+ {
+
+#if defined(BOOST_NO_SFINAE) || \
+ BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \
+ BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
+#if ! defined BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
+#define BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
+#endif
+#endif
+
+#ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
+ namespace detail
+ {
+#define BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(member_name) \
+ template<typename T, bool=boost::is_class<T>::value> \
+ struct has_member_called_##member_name \
+ { \
+ BOOST_STATIC_CONSTANT(bool, value=false); \
+ }; \
+ \
+ template<typename T> \
+ struct has_member_called_##member_name<T,true> \
+ { \
+ typedef char true_type; \
+ struct false_type \
+ { \
+ true_type dummy[2]; \
+ }; \
+ \
+ struct fallback { int member_name; }; \
+ struct derived: \
+ T, fallback \
+ { \
+ derived(); \
+ }; \
+ \
+ template<int fallback::*> struct tester; \
+ \
+ template<typename U> \
+ static false_type has_member(tester<&U::member_name>*); \
+ template<typename U> \
+ static true_type has_member(...); \
+ \
+ BOOST_STATIC_CONSTANT( \
+ bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \
+ }
+
+ BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(lock)
+; BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(unlock);
+ BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(try_lock);
+
+ template<typename T,bool=has_member_called_lock<T>::value >
+ struct has_member_lock
+ {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct has_member_lock<T,true>
+ {
+ typedef char true_type;
+ struct false_type
+ {
+ true_type dummy[2];
+ };
+
+ template<typename U,typename V>
+ static true_type has_member(V (U::*)());
+ template<typename U>
+ static false_type has_member(U);
+
+ BOOST_STATIC_CONSTANT(
+ bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type));
+ };
+
+ template<typename T,bool=has_member_called_unlock<T>::value >
+ struct has_member_unlock
+ {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct has_member_unlock<T,true>
+ {
+ typedef char true_type;
+ struct false_type
+ {
+ true_type dummy[2];
+ };
+
+ template<typename U,typename V>
+ static true_type has_member(V (U::*)());
+ template<typename U>
+ static false_type has_member(U);
+
+ BOOST_STATIC_CONSTANT(
+ bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type));
+ };
+
+ template<typename T,bool=has_member_called_try_lock<T>::value >
+ struct has_member_try_lock
+ {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct has_member_try_lock<T,true>
+ {
+ typedef char true_type;
+ struct false_type
+ {
+ true_type dummy[2];
+ };
+
+ template<typename U>
+ static true_type has_member(bool (U::*)());
+ template<typename U>
+ static false_type has_member(U);
+
+ BOOST_STATIC_CONSTANT(
+ bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
+ };
+
+ }
+
+ template<typename T>
+ struct is_basic_lockable
+ {
+ BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value &&
+ detail::has_member_unlock<T>::value);
+ };
+ template<typename T>
+ struct is_lockable
+ {
+ BOOST_STATIC_CONSTANT(bool, value =
+ is_basic_lockable<T>::value &&
+ detail::has_member_try_lock<T>::value);
+ };
+
+#else
+ template<typename T>
+ struct is_basic_lockable
+ {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
+ template<typename T>
+ struct is_lockable
+ {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
+#endif
+
+ template<typename T>
+ struct is_recursive_mutex_sur_parole
+ {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
+ template<typename T>
+ struct is_recursive_mutex_sur_parolle : is_recursive_mutex_sur_parole<T>
+ {
+ };
+
+ template<typename T>
+ struct is_recursive_basic_lockable
+ {
+ BOOST_STATIC_CONSTANT(bool, value = is_basic_lockable<T>::value &&
+ is_recursive_mutex_sur_parolle<T>::value);
+ };
+ template<typename T>
+ struct is_recursive_lockable
+ {
+ BOOST_STATIC_CONSTANT(bool, value = is_lockable<T>::value &&
+ is_recursive_mutex_sur_parolle<T>::value);
+ };
+ }
+ template<typename T>
+ struct is_mutex_type
+ {
+ BOOST_STATIC_CONSTANT(bool, value = sync::is_lockable<T>::value);
+ };
+
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/locks.hpp b/boost/thread/locks.hpp
index 5111d33e68..6749964cf5 100644
--- a/boost/thread/locks.hpp
+++ b/boost/thread/locks.hpp
@@ -6,1822 +6,11 @@
#ifndef BOOST_THREAD_LOCKS_HPP
#define BOOST_THREAD_LOCKS_HPP
-#include <boost/thread/detail/config.hpp>
-#include <boost/thread/exceptions.hpp>
-#include <boost/thread/detail/move.hpp>
-#include <algorithm>
-#include <iterator>
-#include <boost/thread/thread_time.hpp>
-#include <boost/detail/workaround.hpp>
-#include <boost/type_traits/is_class.hpp>
-#ifdef BOOST_THREAD_USES_CHRONO
-#include <boost/chrono/time_point.hpp>
-#include <boost/chrono/duration.hpp>
-#endif
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost
-{
- struct xtime;
-
-#if defined(BOOST_NO_SFINAE) || \
- BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \
- BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
-#define BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
-#endif
-
-#ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
- namespace detail
- {
-#define BOOST_DEFINE_HAS_MEMBER_CALLED(member_name) \
- template<typename T, bool=boost::is_class<T>::value> \
- struct has_member_called_##member_name \
- { \
- BOOST_STATIC_CONSTANT(bool, value=false); \
- }; \
- \
- template<typename T> \
- struct has_member_called_##member_name<T,true> \
- { \
- typedef char true_type; \
- struct false_type \
- { \
- true_type dummy[2]; \
- }; \
- \
- struct fallback { int member_name; }; \
- struct derived: \
- T, fallback \
- { \
- derived(); \
- }; \
- \
- template<int fallback::*> struct tester; \
- \
- template<typename U> \
- static false_type has_member(tester<&U::member_name>*); \
- template<typename U> \
- static true_type has_member(...); \
- \
- BOOST_STATIC_CONSTANT( \
- bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \
- }
-
- BOOST_DEFINE_HAS_MEMBER_CALLED(lock);
- BOOST_DEFINE_HAS_MEMBER_CALLED(unlock);
- BOOST_DEFINE_HAS_MEMBER_CALLED(try_lock);
-
- template<typename T,bool=has_member_called_lock<T>::value >
- struct has_member_lock
- {
- BOOST_STATIC_CONSTANT(bool, value=false);
- };
-
- template<typename T>
- struct has_member_lock<T,true>
- {
- typedef char true_type;
- struct false_type
- {
- true_type dummy[2];
- };
-
- template<typename U,typename V>
- static true_type has_member(V (U::*)());
- template<typename U>
- static false_type has_member(U);
-
- BOOST_STATIC_CONSTANT(
- bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type));
- };
-
- template<typename T,bool=has_member_called_unlock<T>::value >
- struct has_member_unlock
- {
- BOOST_STATIC_CONSTANT(bool, value=false);
- };
-
- template<typename T>
- struct has_member_unlock<T,true>
- {
- typedef char true_type;
- struct false_type
- {
- true_type dummy[2];
- };
-
- template<typename U,typename V>
- static true_type has_member(V (U::*)());
- template<typename U>
- static false_type has_member(U);
-
- BOOST_STATIC_CONSTANT(
- bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type));
- };
-
- template<typename T,bool=has_member_called_try_lock<T>::value >
- struct has_member_try_lock
- {
- BOOST_STATIC_CONSTANT(bool, value=false);
- };
-
- template<typename T>
- struct has_member_try_lock<T,true>
- {
- typedef char true_type;
- struct false_type
- {
- true_type dummy[2];
- };
-
- template<typename U>
- static true_type has_member(bool (U::*)());
- template<typename U>
- static false_type has_member(U);
-
- BOOST_STATIC_CONSTANT(
- bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
- };
-
- }
-
-
- template<typename T>
- struct is_mutex_type
- {
- BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value &&
- detail::has_member_unlock<T>::value &&
- detail::has_member_try_lock<T>::value);
-
- };
-#else
- template<typename T>
- struct is_mutex_type
- {
- BOOST_STATIC_CONSTANT(bool, value = false);
- };
-#endif
-
- struct defer_lock_t
- {};
- struct try_to_lock_t
- {};
- struct adopt_lock_t
- {};
-
- BOOST_CONSTEXPR_OR_CONST defer_lock_t defer_lock={};
- BOOST_CONSTEXPR_OR_CONST try_to_lock_t try_to_lock={};
- BOOST_CONSTEXPR_OR_CONST adopt_lock_t adopt_lock={};
-
- template<typename Mutex>
- class shared_lock;
-
- template<typename Mutex>
- class upgrade_lock;
-
- template<typename Mutex>
- class unique_lock;
-
- namespace detail
- {
- template<typename Mutex>
- class try_lock_wrapper;
- }
-
-#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
- template<typename T>
- struct is_mutex_type<unique_lock<T> >
- {
- BOOST_STATIC_CONSTANT(bool, value = true);
- };
-
- template<typename T>
- struct is_mutex_type<shared_lock<T> >
- {
- BOOST_STATIC_CONSTANT(bool, value = true);
- };
-
- template<typename T>
- struct is_mutex_type<upgrade_lock<T> >
- {
- BOOST_STATIC_CONSTANT(bool, value = true);
- };
-
- template<typename T>
- struct is_mutex_type<detail::try_lock_wrapper<T> >
- {
- BOOST_STATIC_CONSTANT(bool, value = true);
- };
-
- class mutex;
- class timed_mutex;
- class recursive_mutex;
- class recursive_timed_mutex;
- class shared_mutex;
-
- template<>
- struct is_mutex_type<mutex>
- {
- BOOST_STATIC_CONSTANT(bool, value = true);
- };
- template<>
- struct is_mutex_type<timed_mutex>
- {
- BOOST_STATIC_CONSTANT(bool, value = true);
- };
- template<>
- struct is_mutex_type<recursive_mutex>
- {
- BOOST_STATIC_CONSTANT(bool, value = true);
- };
- template<>
- struct is_mutex_type<recursive_timed_mutex>
- {
- BOOST_STATIC_CONSTANT(bool, value = true);
- };
- template<>
- struct is_mutex_type<shared_mutex>
- {
- BOOST_STATIC_CONSTANT(bool, value = true);
- };
-
-#endif
-
- template<typename Mutex>
- class lock_guard
- {
- private:
- Mutex& m;
-
- public:
- typedef Mutex mutex_type;
- BOOST_THREAD_NO_COPYABLE(lock_guard)
-
- explicit lock_guard(Mutex& m_):
- m(m_)
- {
- m.lock();
- }
- lock_guard(Mutex& m_,adopt_lock_t):
- m(m_)
- {}
- ~lock_guard()
- {
- m.unlock();
- }
- };
-
- template<typename Mutex>
- class unique_lock
- {
- private:
- Mutex* m;
- bool is_locked;
-
- private:
- explicit unique_lock(upgrade_lock<Mutex>&);
- unique_lock& operator=(upgrade_lock<Mutex>& other);
- public:
- typedef Mutex mutex_type;
- BOOST_THREAD_MOVABLE_ONLY(unique_lock)
-
-#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
-#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
- unique_lock(const volatile unique_lock&);
-#endif
-#endif
- unique_lock() BOOST_NOEXCEPT :
- m(0),is_locked(false)
- {}
-
- explicit unique_lock(Mutex& m_):
- m(&m_),is_locked(false)
- {
- lock();
- }
- unique_lock(Mutex& m_,adopt_lock_t):
- m(&m_),is_locked(true)
- {}
- unique_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT:
- m(&m_),is_locked(false)
- {}
- unique_lock(Mutex& m_,try_to_lock_t):
- m(&m_),is_locked(false)
- {
- try_lock();
- }
- template<typename TimeDuration>
- unique_lock(Mutex& m_,TimeDuration const& target_time):
- m(&m_),is_locked(false)
- {
- timed_lock(target_time);
- }
- unique_lock(Mutex& m_,system_time const& target_time):
- m(&m_),is_locked(false)
- {
- timed_lock(target_time);
- }
-
-#ifdef BOOST_THREAD_USES_CHRONO
- template <class Clock, class Duration>
- unique_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
- : m(&mtx), is_locked(mtx.try_lock_until(t))
- {
- }
- template <class Rep, class Period>
- unique_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
- : m(&mtx), is_locked(mtx.try_lock_for(d))
- {
- }
-#endif
-
- unique_lock(BOOST_THREAD_RV_REF(unique_lock) other) BOOST_NOEXCEPT:
- m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
- {
- BOOST_THREAD_RV(other).is_locked=false;
- BOOST_THREAD_RV(other).m=0;
- }
- BOOST_THREAD_EXPLICIT_LOCK_CONVERSION unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other);
-
-#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
- unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
- {
- unique_lock temp(::boost::move(other));
- swap(temp);
- return *this;
- }
-#endif
-
- unique_lock& operator=(BOOST_THREAD_RV_REF(unique_lock) other) BOOST_NOEXCEPT
- {
- unique_lock temp(::boost::move(other));
- swap(temp);
- return *this;
- }
-#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
-#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
- unique_lock& operator=(unique_lock<Mutex> other)
- {
- swap(other);
- return *this;
- }
-#endif // BOOST_WORKAROUND
-#endif
-
- // Conversion from upgrade locking
- unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul, try_to_lock_t)
- : m(0),is_locked(false)
- {
- if (BOOST_THREAD_RV(ul).owns_lock()) {
- if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock())
- {
- m = BOOST_THREAD_RV(ul).release();
- is_locked = true;
- }
- }
- else
- {
- m = BOOST_THREAD_RV(ul).release();
- }
- }
-
-#ifdef BOOST_THREAD_USES_CHRONO
- template <class Clock, class Duration>
- unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul,
- const chrono::time_point<Clock, Duration>& abs_time)
- : m(0),is_locked(false)
- {
- if (BOOST_THREAD_RV(ul).owns_lock()) {
- if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_until(abs_time))
- {
- m = BOOST_THREAD_RV(ul).release();
- is_locked = true;
- }
- }
- else
- {
- m = BOOST_THREAD_RV(ul).release();
- }
- }
-
- template <class Rep, class Period>
- unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul,
- const chrono::duration<Rep, Period>& rel_time)
- : m(0),is_locked(false)
- {
- if (BOOST_THREAD_RV(ul).owns_lock()) {
- if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_for(rel_time))
- {
- m = BOOST_THREAD_RV(ul).release();
- is_locked = true;
- }
- }
- else
- {
- m = BOOST_THREAD_RV(ul).release();
- }
- }
-#endif
-
-#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
- // Conversion from shared locking
- unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, try_to_lock_t)
- : m(0),is_locked(false)
- {
- if (BOOST_THREAD_RV(sl).owns_lock()) {
- if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock())
- {
- m = BOOST_THREAD_RV(sl).release();
- is_locked = true;
- }
- }
- else
- {
- m = BOOST_THREAD_RV(sl).release();
- }
- }
-
-#ifdef BOOST_THREAD_USES_CHRONO
- template <class Clock, class Duration>
- unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
- const chrono::time_point<Clock, Duration>& abs_time)
- : m(0),is_locked(false)
- {
- if (BOOST_THREAD_RV(sl).owns_lock()) {
- if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_until(abs_time))
- {
- m = BOOST_THREAD_RV(sl).release();
- is_locked = true;
- }
- }
- else
- {
- m = BOOST_THREAD_RV(sl).release();
- }
- }
-
- template <class Rep, class Period>
- unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
- const chrono::duration<Rep, Period>& rel_time)
- : m(0),is_locked(false)
- {
- if (BOOST_THREAD_RV(sl).owns_lock()) {
- if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_for(rel_time))
- {
- m = BOOST_THREAD_RV(sl).release();
- is_locked = true;
- }
- }
- else
- {
- m = BOOST_THREAD_RV(sl).release();
- }
- }
-#endif // BOOST_THREAD_USES_CHRONO
-#endif // BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
-
-
- void swap(unique_lock& other) BOOST_NOEXCEPT
- {
- std::swap(m,other.m);
- std::swap(is_locked,other.is_locked);
- }
-
- ~unique_lock()
- {
- if(owns_lock())
- {
- m->unlock();
- }
- }
- void lock()
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
- }
- m->lock();
- is_locked=true;
- }
- bool try_lock()
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
- }
- is_locked=m->try_lock();
- return is_locked;
- }
- template<typename TimeDuration>
- bool timed_lock(TimeDuration const& relative_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
- }
- is_locked=m->timed_lock(relative_time);
- return is_locked;
- }
-
- bool timed_lock(::boost::system_time const& absolute_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
- }
- is_locked=m->timed_lock(absolute_time);
- return is_locked;
- }
- bool timed_lock(::boost::xtime const& absolute_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
- }
- is_locked=m->timed_lock(absolute_time);
- return is_locked;
- }
-
-#ifdef BOOST_THREAD_USES_CHRONO
-
- template <class Rep, class Period>
- bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
- }
- is_locked=m->try_lock_for(rel_time);
- return is_locked;
- }
- template <class Clock, class Duration>
- bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex"));
- }
- is_locked=m->try_lock_until(abs_time);
- return is_locked;
- }
-#endif
-
- void unlock()
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex"));
- }
- if(!owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock doesn't own the mutex"));
- }
- m->unlock();
- is_locked=false;
- }
-
-#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
- typedef void (unique_lock::*bool_type)();
- operator bool_type() const BOOST_NOEXCEPT
- {
- return is_locked?&unique_lock::lock:0;
- }
- bool operator!() const BOOST_NOEXCEPT
- {
- return !owns_lock();
- }
-#else
- explicit operator bool() const BOOST_NOEXCEPT
- {
- return owns_lock();
- }
-#endif
- bool owns_lock() const BOOST_NOEXCEPT
- {
- return is_locked;
- }
-
- Mutex* mutex() const BOOST_NOEXCEPT
- {
- return m;
- }
-
- Mutex* release() BOOST_NOEXCEPT
- {
- Mutex* const res=m;
- m=0;
- is_locked=false;
- return res;
- }
-
- friend class shared_lock<Mutex>;
- friend class upgrade_lock<Mutex>;
- };
-
- template<typename Mutex>
- void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs) BOOST_NOEXCEPT
- {
- lhs.swap(rhs);
- }
-
- BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
-
- template<typename Mutex>
- class shared_lock
- {
- protected:
- Mutex* m;
- bool is_locked;
-
- public:
- typedef Mutex mutex_type;
- BOOST_THREAD_MOVABLE_ONLY(shared_lock)
-
- shared_lock() BOOST_NOEXCEPT:
- m(0),is_locked(false)
- {}
-
- explicit shared_lock(Mutex& m_):
- m(&m_),is_locked(false)
- {
- lock();
- }
- shared_lock(Mutex& m_,adopt_lock_t):
- m(&m_),is_locked(true)
- {}
- shared_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT:
- m(&m_),is_locked(false)
- {}
- shared_lock(Mutex& m_,try_to_lock_t):
- m(&m_),is_locked(false)
- {
- try_lock();
- }
- shared_lock(Mutex& m_,system_time const& target_time):
- m(&m_),is_locked(false)
- {
- timed_lock(target_time);
- }
-
-#ifdef BOOST_THREAD_USES_CHRONO
- template <class Clock, class Duration>
- shared_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
- : m(&mtx), is_locked(mtx.try_lock_shared_until(t))
- {
- }
- template <class Rep, class Period>
- shared_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
- : m(&mtx), is_locked(mtx.try_lock_shared_for(d))
- {
- }
-#endif
-
- shared_lock(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
- m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
- {
- BOOST_THREAD_RV(other).is_locked=false;
- BOOST_THREAD_RV(other).m=0;
- }
-
- BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other):
- m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
- {
- if(is_locked)
- {
- m->unlock_and_lock_shared();
- }
- BOOST_THREAD_RV(other).is_locked=false;
- BOOST_THREAD_RV(other).m=0;
- }
-
- BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other):
- m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
- {
- if(is_locked)
- {
- m->unlock_upgrade_and_lock_shared();
- }
- BOOST_THREAD_RV(other).is_locked=false;
- BOOST_THREAD_RV(other).m=0;
- }
-
-
- shared_lock& operator=(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
- {
- shared_lock temp(::boost::move(other));
- swap(temp);
- return *this;
- }
-#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
- shared_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other)
- {
- shared_lock temp(::boost::move(other));
- swap(temp);
- return *this;
- }
-
- shared_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other)
- {
- shared_lock temp(::boost::move(other));
- swap(temp);
- return *this;
- }
-#endif
-
- void swap(shared_lock& other) BOOST_NOEXCEPT
- {
- std::swap(m,other.m);
- std::swap(is_locked,other.is_locked);
- }
-
- Mutex* mutex() const BOOST_NOEXCEPT
- {
- return m;
- }
-
- Mutex* release() BOOST_NOEXCEPT
- {
- Mutex* const res=m;
- m=0;
- is_locked=false;
- return res;
- }
-
- ~shared_lock()
- {
- if(owns_lock())
- {
- m->unlock_shared();
- }
- }
- void lock()
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
- }
- m->lock_shared();
- is_locked=true;
- }
- bool try_lock()
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
- }
- is_locked=m->try_lock_shared();
- return is_locked;
- }
- bool timed_lock(boost::system_time const& target_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
- }
- is_locked=m->timed_lock_shared(target_time);
- return is_locked;
- }
- template<typename Duration>
- bool timed_lock(Duration const& target_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
- }
- is_locked=m->timed_lock_shared(target_time);
- return is_locked;
- }
-#ifdef BOOST_THREAD_USES_CHRONO
- template <class Rep, class Period>
- bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
- }
- is_locked=m->try_lock_shared_for(rel_time);
- return is_locked;
- }
- template <class Clock, class Duration>
- bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
- }
- is_locked=m->try_lock_shared_until(abs_time);
- return is_locked;
- }
-#endif
- void unlock()
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(!owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock doesn't own the mutex"));
- }
- m->unlock_shared();
- is_locked=false;
- }
-
-#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
- typedef void (shared_lock<Mutex>::*bool_type)();
- operator bool_type() const BOOST_NOEXCEPT
- {
- return is_locked?&shared_lock::lock:0;
- }
- bool operator!() const BOOST_NOEXCEPT
- {
- return !owns_lock();
- }
-#else
- explicit operator bool() const BOOST_NOEXCEPT
- {
- return owns_lock();
- }
-#endif
- bool owns_lock() const BOOST_NOEXCEPT
- {
- return is_locked;
- }
-
- };
-
- BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) shared_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
-
- template<typename Mutex>
- void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs) BOOST_NOEXCEPT
- {
- lhs.swap(rhs);
- }
-
- template<typename Mutex>
- class upgrade_lock
- {
- protected:
- Mutex* m;
- bool is_locked;
-
- public:
- typedef Mutex mutex_type;
- BOOST_THREAD_MOVABLE_ONLY(upgrade_lock)
-
- upgrade_lock() BOOST_NOEXCEPT:
- m(0),is_locked(false)
- {}
-
- explicit upgrade_lock(Mutex& m_):
- m(&m_),is_locked(false)
- {
- lock();
- }
- upgrade_lock(Mutex& m_,adopt_lock_t):
- m(&m_),is_locked(true)
- {}
- upgrade_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT:
- m(&m_),is_locked(false)
- {}
- upgrade_lock(Mutex& m_,try_to_lock_t):
- m(&m_),is_locked(false)
- {
- try_lock();
- }
-
-#ifdef BOOST_THREAD_USES_CHRONO
- template <class Clock, class Duration>
- upgrade_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
- : m(&mtx), is_locked(mtx.try_lock_upgrade_until(t))
- {
- }
- template <class Rep, class Period>
- upgrade_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
- : m(&mtx), is_locked(mtx.try_lock_upgrade_for(d))
- {
- }
-#endif
-
- upgrade_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
- m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
- {
- BOOST_THREAD_RV(other).is_locked=false;
- BOOST_THREAD_RV(other).m=0;
- }
-
- BOOST_THREAD_EXPLICIT_LOCK_CONVERSION upgrade_lock(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other):
- m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
- {
- if(is_locked)
- {
- m->unlock_and_lock_upgrade();
- }
- BOOST_THREAD_RV(other).is_locked=false;
- BOOST_THREAD_RV(other).m=0;
- }
-
- upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
- {
- upgrade_lock temp(::boost::move(other));
- swap(temp);
- return *this;
- }
-
-#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
- upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other)
- {
- upgrade_lock temp(::boost::move(other));
- swap(temp);
- return *this;
- }
-#endif
-
-#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
- // Conversion from shared locking
- upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, try_to_lock_t)
- : m(0),is_locked(false)
- {
- if (BOOST_THREAD_RV(sl).owns_lock()) {
- if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade())
- {
- m = BOOST_THREAD_RV(sl).release();
- is_locked = true;
- }
- }
- else
- {
- m = BOOST_THREAD_RV(sl).release();
- }
- }
-
-#ifdef BOOST_THREAD_USES_CHRONO
- template <class Clock, class Duration>
- upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
- const chrono::time_point<Clock, Duration>& abs_time)
- : m(0),is_locked(false)
- {
- if (BOOST_THREAD_RV(sl).owns_lock()) {
- if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_until(abs_time))
- {
- m = BOOST_THREAD_RV(sl).release();
- is_locked = true;
- }
- }
- else
- {
- m = BOOST_THREAD_RV(sl).release();
- }
- }
-
- template <class Rep, class Period>
- upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
- const chrono::duration<Rep, Period>& rel_time)
- : m(0),is_locked(false)
- {
- if (BOOST_THREAD_RV(sl).owns_lock()) {
- if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_for(rel_time))
- {
- m = BOOST_THREAD_RV(sl).release();
- is_locked = true;
- }
- }
- else
- {
- m = BOOST_THREAD_RV(sl).release();
- }
- }
-#endif // BOOST_THREAD_USES_CHRONO
-#endif // BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
-
- void swap(upgrade_lock& other) BOOST_NOEXCEPT
- {
- std::swap(m,other.m);
- std::swap(is_locked,other.is_locked);
- }
- Mutex* mutex() const BOOST_NOEXCEPT
- {
- return m;
- }
-
- Mutex* release() BOOST_NOEXCEPT
- {
- Mutex* const res=m;
- m=0;
- is_locked=false;
- return res;
- }
- ~upgrade_lock()
- {
- if(owns_lock())
- {
- m->unlock_upgrade();
- }
- }
- void lock()
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost upgrade_lock owns already the mutex"));
- }
- m->lock_upgrade();
- is_locked=true;
- }
- bool try_lock()
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost upgrade_lock owns already the mutex"));
- }
- is_locked=m->try_lock_upgrade();
- return is_locked;
- }
- void unlock()
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(!owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost upgrade_lock doesn't own the mutex"));
- }
- m->unlock_upgrade();
- is_locked=false;
- }
-#ifdef BOOST_THREAD_USES_CHRONO
- template <class Rep, class Period>
- bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
- }
- is_locked=m->try_lock_upgrade_for(rel_time);
- return is_locked;
- }
- template <class Clock, class Duration>
- bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
- {
- if(m==0)
- {
- boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex"));
- }
- if(owns_lock())
- {
- boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex"));
- }
- is_locked=m->try_lock_upgrade_until(abs_time);
- return is_locked;
- }
-#endif
-#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
- typedef void (upgrade_lock::*bool_type)();
- operator bool_type() const BOOST_NOEXCEPT
- {
- return is_locked?&upgrade_lock::lock:0;
- }
- bool operator!() const BOOST_NOEXCEPT
- {
- return !owns_lock();
- }
-#else
- explicit operator bool() const BOOST_NOEXCEPT
- {
- return owns_lock();
- }
-#endif
- bool owns_lock() const BOOST_NOEXCEPT
- {
- return is_locked;
- }
- friend class shared_lock<Mutex>;
- friend class unique_lock<Mutex>;
- };
-
- template<typename Mutex>
- void swap(upgrade_lock<Mutex>& lhs,upgrade_lock<Mutex>& rhs) BOOST_NOEXCEPT
- {
- lhs.swap(rhs);
- }
-
- BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
-
- template<typename Mutex>
- unique_lock<Mutex>::unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other):
- m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
- {
- if(is_locked)
- {
- m->unlock_upgrade_and_lock();
- }
- BOOST_THREAD_RV(other).release();
- }
-
- template <class Mutex>
- class upgrade_to_unique_lock
- {
- private:
- upgrade_lock<Mutex>* source;
- unique_lock<Mutex> exclusive;
-
- public:
- typedef Mutex mutex_type;
- BOOST_THREAD_MOVABLE_ONLY(upgrade_to_unique_lock)
-
- explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_):
- source(&m_),exclusive(::boost::move(*source))
- {}
- ~upgrade_to_unique_lock()
- {
- if(source)
- {
- *source=BOOST_THREAD_MAKE_RV_REF(upgrade_lock<Mutex>(::boost::move(exclusive)));
- }
- }
-
- upgrade_to_unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
- source(BOOST_THREAD_RV(other).source),exclusive(::boost::move(BOOST_THREAD_RV(other).exclusive))
- {
- BOOST_THREAD_RV(other).source=0;
- }
-
- upgrade_to_unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT
- {
- upgrade_to_unique_lock temp(other);
- swap(temp);
- return *this;
- }
-
- void swap(upgrade_to_unique_lock& other) BOOST_NOEXCEPT
- {
- std::swap(source,other.source);
- exclusive.swap(other.exclusive);
- }
-
-#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
- typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&);
- operator bool_type() const BOOST_NOEXCEPT
- {
- return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0;
- }
- bool operator!() const BOOST_NOEXCEPT
- {
- return !owns_lock();
- }
-#else
- explicit operator bool() const BOOST_NOEXCEPT
- {
- return owns_lock();
- }
-#endif
-
- bool owns_lock() const BOOST_NOEXCEPT
- {
- return exclusive.owns_lock();
- }
- };
-
- BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_to_unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
-
- namespace detail
- {
- template<typename Mutex>
- class try_lock_wrapper:
- private unique_lock<Mutex>
- {
- typedef unique_lock<Mutex> base;
- public:
- BOOST_THREAD_MOVABLE_ONLY(try_lock_wrapper)
-
- try_lock_wrapper()
- {}
-
- explicit try_lock_wrapper(Mutex& m):
- base(m,try_to_lock)
- {}
-
- try_lock_wrapper(Mutex& m_,adopt_lock_t):
- base(m_,adopt_lock)
- {}
- try_lock_wrapper(Mutex& m_,defer_lock_t):
- base(m_,defer_lock)
- {}
- try_lock_wrapper(Mutex& m_,try_to_lock_t):
- base(m_,try_to_lock)
- {}
-#ifndef BOOST_NO_RVALUE_REFERENCES
- try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
- base(::boost::move(other))
- {}
-
-#elif defined BOOST_THREAD_USES_MOVE
- try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
- base(::boost::move(static_cast<base&>(other)))
- {}
-
-#else
- try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
- base(BOOST_THREAD_RV_REF(base)(*other))
- {}
-#endif
- try_lock_wrapper& operator=(BOOST_THREAD_RV_REF_BEG try_lock_wrapper<Mutex> BOOST_THREAD_RV_REF_END other)
- {
- try_lock_wrapper temp(other);
- swap(temp);
- return *this;
- }
- void swap(try_lock_wrapper& other)
- {
- base::swap(other);
- }
- void lock()
- {
- base::lock();
- }
- bool try_lock()
- {
- return base::try_lock();
- }
- void unlock()
- {
- base::unlock();
- }
- bool owns_lock() const
- {
- return base::owns_lock();
- }
- Mutex* mutex() const
- {
- return base::mutex();
- }
- Mutex* release()
- {
- return base::release();
- }
-
-#if defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
- typedef typename base::bool_type bool_type;
- operator bool_type() const
- {
- return base::operator bool_type();
- }
- bool operator!() const
- {
- return !this->owns_lock();
- }
-#else
- explicit operator bool() const
- {
- return owns_lock();
- }
-#endif
- };
-
- template<typename Mutex>
- void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs)
- {
- lhs.swap(rhs);
- }
-
- template<typename MutexType1,typename MutexType2>
- unsigned try_lock_internal(MutexType1& m1,MutexType2& m2)
- {
- boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
- if(!l1)
- {
- return 1;
- }
- if(!m2.try_lock())
- {
- return 2;
- }
- l1.release();
- return 0;
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3>
- unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3)
- {
- boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
- if(!l1)
- {
- return 1;
- }
- if(unsigned const failed_lock=try_lock_internal(m2,m3))
- {
- return failed_lock+1;
- }
- l1.release();
- return 0;
- }
-
-
- template<typename MutexType1,typename MutexType2,typename MutexType3,
- typename MutexType4>
- unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3,
- MutexType4& m4)
- {
- boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
- if(!l1)
- {
- return 1;
- }
- if(unsigned const failed_lock=try_lock_internal(m2,m3,m4))
- {
- return failed_lock+1;
- }
- l1.release();
- return 0;
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3,
- typename MutexType4,typename MutexType5>
- unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3,
- MutexType4& m4,MutexType5& m5)
- {
- boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
- if(!l1)
- {
- return 1;
- }
- if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
- {
- return failed_lock+1;
- }
- l1.release();
- return 0;
- }
-
-
- template<typename MutexType1,typename MutexType2>
- unsigned lock_helper(MutexType1& m1,MutexType2& m2)
- {
- boost::unique_lock<MutexType1> l1(m1);
- if(!m2.try_lock())
- {
- return 1;
- }
- l1.release();
- return 0;
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3>
- unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3)
- {
- boost::unique_lock<MutexType1> l1(m1);
- if(unsigned const failed_lock=try_lock_internal(m2,m3))
- {
- return failed_lock;
- }
- l1.release();
- return 0;
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3,
- typename MutexType4>
- unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3,
- MutexType4& m4)
- {
- boost::unique_lock<MutexType1> l1(m1);
- if(unsigned const failed_lock=try_lock_internal(m2,m3,m4))
- {
- return failed_lock;
- }
- l1.release();
- return 0;
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3,
- typename MutexType4,typename MutexType5>
- unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3,
- MutexType4& m4,MutexType5& m5)
- {
- boost::unique_lock<MutexType1> l1(m1);
- if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
- {
- return failed_lock;
- }
- l1.release();
- return 0;
- }
- }
-
- namespace detail
- {
- template<bool x>
- struct is_mutex_type_wrapper
- {};
-
- template<typename MutexType1,typename MutexType2>
- void lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>)
- {
- unsigned const lock_count=2;
- unsigned lock_first=0;
- for(;;)
- {
- switch(lock_first)
- {
- case 0:
- lock_first=detail::lock_helper(m1,m2);
- if(!lock_first)
- return;
- break;
- case 1:
- lock_first=detail::lock_helper(m2,m1);
- if(!lock_first)
- return;
- lock_first=(lock_first+1)%lock_count;
- break;
- }
- }
- }
-
- template<typename Iterator>
- void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>);
- }
-
-
- template<typename MutexType1,typename MutexType2>
- void lock(MutexType1& m1,MutexType2& m2)
- {
- detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
- }
-
- template<typename MutexType1,typename MutexType2>
- void lock(const MutexType1& m1,MutexType2& m2)
- {
- detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
- }
-
- template<typename MutexType1,typename MutexType2>
- void lock(MutexType1& m1,const MutexType2& m2)
- {
- detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
- }
-
- template<typename MutexType1,typename MutexType2>
- void lock(const MutexType1& m1,const MutexType2& m2)
- {
- detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3>
- void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3)
- {
- unsigned const lock_count=3;
- unsigned lock_first=0;
- for(;;)
- {
- switch(lock_first)
- {
- case 0:
- lock_first=detail::lock_helper(m1,m2,m3);
- if(!lock_first)
- return;
- break;
- case 1:
- lock_first=detail::lock_helper(m2,m3,m1);
- if(!lock_first)
- return;
- lock_first=(lock_first+1)%lock_count;
- break;
- case 2:
- lock_first=detail::lock_helper(m3,m1,m2);
- if(!lock_first)
- return;
- lock_first=(lock_first+2)%lock_count;
- break;
- }
- }
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3,
- typename MutexType4>
- void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,
- MutexType4& m4)
- {
- unsigned const lock_count=4;
- unsigned lock_first=0;
- for(;;)
- {
- switch(lock_first)
- {
- case 0:
- lock_first=detail::lock_helper(m1,m2,m3,m4);
- if(!lock_first)
- return;
- break;
- case 1:
- lock_first=detail::lock_helper(m2,m3,m4,m1);
- if(!lock_first)
- return;
- lock_first=(lock_first+1)%lock_count;
- break;
- case 2:
- lock_first=detail::lock_helper(m3,m4,m1,m2);
- if(!lock_first)
- return;
- lock_first=(lock_first+2)%lock_count;
- break;
- case 3:
- lock_first=detail::lock_helper(m4,m1,m2,m3);
- if(!lock_first)
- return;
- lock_first=(lock_first+3)%lock_count;
- break;
- }
- }
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3,
- typename MutexType4,typename MutexType5>
- void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,
- MutexType4& m4,MutexType5& m5)
- {
- unsigned const lock_count=5;
- unsigned lock_first=0;
- for(;;)
- {
- switch(lock_first)
- {
- case 0:
- lock_first=detail::lock_helper(m1,m2,m3,m4,m5);
- if(!lock_first)
- return;
- break;
- case 1:
- lock_first=detail::lock_helper(m2,m3,m4,m5,m1);
- if(!lock_first)
- return;
- lock_first=(lock_first+1)%lock_count;
- break;
- case 2:
- lock_first=detail::lock_helper(m3,m4,m5,m1,m2);
- if(!lock_first)
- return;
- lock_first=(lock_first+2)%lock_count;
- break;
- case 3:
- lock_first=detail::lock_helper(m4,m5,m1,m2,m3);
- if(!lock_first)
- return;
- lock_first=(lock_first+3)%lock_count;
- break;
- case 4:
- lock_first=detail::lock_helper(m5,m1,m2,m3,m4);
- if(!lock_first)
- return;
- lock_first=(lock_first+4)%lock_count;
- break;
- }
- }
- }
-
- namespace detail
- {
- template<typename Mutex,bool x=is_mutex_type<Mutex>::value>
- struct try_lock_impl_return
- {
- typedef int type;
- };
-
- template<typename Iterator>
- struct try_lock_impl_return<Iterator,false>
- {
- typedef Iterator type;
- };
-
- template<typename MutexType1,typename MutexType2>
- int try_lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>)
- {
- return ((int)detail::try_lock_internal(m1,m2))-1;
- }
-
- template<typename Iterator>
- Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>);
- }
-
- template<typename MutexType1,typename MutexType2>
- typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,MutexType2& m2)
- {
- return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
- }
-
- template<typename MutexType1,typename MutexType2>
- typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1,MutexType2& m2)
- {
- return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
- }
-
- template<typename MutexType1,typename MutexType2>
- typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,const MutexType2& m2)
- {
- return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
- }
-
- template<typename MutexType1,typename MutexType2>
- typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1,const MutexType2& m2)
- {
- return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3>
- int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3)
- {
- return ((int)detail::try_lock_internal(m1,m2,m3))-1;
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4>
- int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4)
- {
- return ((int)detail::try_lock_internal(m1,m2,m3,m4))-1;
- }
-
- template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4,typename MutexType5>
- int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4,MutexType5& m5)
- {
- return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1;
- }
-
-
- namespace detail
- {
- template<typename Iterator>
- struct range_lock_guard
- {
- Iterator begin;
- Iterator end;
-
- range_lock_guard(Iterator begin_,Iterator end_):
- begin(begin_),end(end_)
- {
- boost::lock(begin,end);
- }
-
- void release()
- {
- begin=end;
- }
-
- ~range_lock_guard()
- {
- for(;begin!=end;++begin)
- {
- begin->unlock();
- }
- }
- };
-
- template<typename Iterator>
- Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>)
-
- {
- if(begin==end)
- {
- return end;
- }
- typedef typename std::iterator_traits<Iterator>::value_type lock_type;
- unique_lock<lock_type> guard(*begin,try_to_lock);
-
- if(!guard.owns_lock())
- {
- return begin;
- }
- Iterator const failed=boost::try_lock(++begin,end);
- if(failed==end)
- {
- guard.release();
- }
-
- return failed;
- }
- }
-
-
- namespace detail
- {
- template<typename Iterator>
- void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>)
- {
- typedef typename std::iterator_traits<Iterator>::value_type lock_type;
-
- if(begin==end)
- {
- return;
- }
- bool start_with_begin=true;
- Iterator second=begin;
- ++second;
- Iterator next=second;
-
- for(;;)
- {
- unique_lock<lock_type> begin_lock(*begin,defer_lock);
- if(start_with_begin)
- {
- begin_lock.lock();
- Iterator const failed_lock=boost::try_lock(next,end);
- if(failed_lock==end)
- {
- begin_lock.release();
- return;
- }
- start_with_begin=false;
- next=failed_lock;
- }
- else
- {
- detail::range_lock_guard<Iterator> guard(next,end);
- if(begin_lock.try_lock())
- {
- Iterator const failed_lock=boost::try_lock(second,next);
- if(failed_lock==next)
- {
- begin_lock.release();
- guard.release();
- return;
- }
- start_with_begin=false;
- next=failed_lock;
- }
- else
- {
- start_with_begin=true;
- next=second;
- }
- }
- }
- }
-
- }
-}
-#include <boost/config/abi_suffix.hpp>
+#include <boost/thread/lock_algorithms.hpp>
+#include <boost/thread/lock_types.hpp>
+#include <boost/thread/lock_guard.hpp>
+#include <boost/thread/lockable_traits.hpp>
+#include <boost/thread/lock_options.hpp>
#endif
diff --git a/boost/thread/mutex.hpp b/boost/thread/mutex.hpp
index 4669886c7f..05c60941c4 100644
--- a/boost/thread/mutex.hpp
+++ b/boost/thread/mutex.hpp
@@ -3,7 +3,7 @@
// mutex.hpp
//
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -18,4 +18,36 @@
#error "Boost threads unavailable on this platform"
#endif
+#include <boost/thread/lockable_traits.hpp>
+
+
+namespace boost
+{
+ namespace sync
+ {
+#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
+ template<>
+ struct is_basic_lockable<mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<>
+ struct is_lockable<mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<>
+ struct is_basic_lockable<timed_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<>
+ struct is_lockable<timed_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+#endif
+ }
+}
+
#endif
diff --git a/boost/thread/null_mutex.hpp b/boost/thread/null_mutex.hpp
new file mode 100644
index 0000000000..f439f9ffb2
--- /dev/null
+++ b/boost/thread/null_mutex.hpp
@@ -0,0 +1,243 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_THREAD_NULL_MUTEX_HPP
+#define BOOST_THREAD_NULL_MUTEX_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/chrono/chrono.hpp>
+
+/// \file
+/// Describes null_mutex class
+
+namespace boost
+{
+
+ /// Implements a mutex that simulates a mutex without doing any operation and
+ /// simulates a successful operation.
+ class null_mutex
+ {
+ public:
+
+ BOOST_THREAD_NO_COPYABLE( null_mutex) /*< no copyable >*/
+
+ null_mutex() {}
+
+ /// Simulates a mutex lock() operation. Empty function.
+ void lock()
+ {
+ }
+
+ /// Simulates a mutex try_lock() operation.
+ /// Equivalent to "return true;"
+ bool try_lock()
+ {
+ return true;
+ }
+
+ /// Simulates a mutex unlock() operation.
+ /// Empty function.
+ void unlock()
+ {
+ }
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ /// Simulates a mutex try_lock_until() operation.
+ /// Equivalent to "return true;"
+ template <typename Clock, typename Duration>
+ bool try_lock_until(chrono::time_point<Clock, Duration> const &)
+ {
+ return true;
+ }
+
+ /// Simulates a mutex try_lock_for() operation.
+ /// Equivalent to "return true;"
+ template <typename Rep, typename Period>
+ bool try_lock_for(chrono::duration<Rep, Period> const &)
+ {
+ return true;
+ }
+#endif
+
+ /// Simulates a mutex lock_shared() operation.
+ /// Empty function.
+ void lock_shared()
+ {
+ }
+
+ /// Simulates a mutex try_lock_shared() operation.
+ /// Equivalent to "return true;"
+ bool try_lock_shared()
+ {
+ return true;
+ }
+
+ /// Simulates a mutex unlock_shared() operation.
+ /// Empty function.
+ void unlock_shared()
+ {
+ }
+
+ /// Simulates a mutex try_lock_shared_until() operation.
+ /// Equivalent to "return true;"
+ template <typename Clock, typename Duration>
+ bool try_lock_shared_until(chrono::time_point<Clock, Duration> const &)
+ {
+ return true;
+ }
+ /// Simulates a mutex try_lock_shared_for() operation.
+ /// Equivalent to "return true;"
+ template <typename Rep, typename Period>
+ bool try_lock_shared_for(chrono::duration<Rep, Period> const &)
+ {
+ return true;
+ }
+
+ /// Simulates a mutex lock_upgrade() operation.
+ /// Empty function.
+ void lock_upgrade()
+ {
+ }
+
+ /// Simulates a mutex try_lock_upgrade() operation.
+ /// Equivalent to "return true;"
+ bool try_lock_upgrade()
+ {
+ return true;
+ }
+
+ /// Simulates a mutex unlock_upgrade() operation.
+ /// Empty function.
+ void unlock_upgrade()
+ {
+ }
+
+ /// Simulates a mutex try_lock_upgrade_until() operation.
+ /// Equivalent to "return true;"
+ template <typename Clock, typename Duration>
+ bool try_lock_upgrade_until(chrono::time_point<Clock, Duration> const &)
+ {
+ return true;
+ }
+
+ /// Simulates a mutex try_lock_upgrade_for() operation.
+ /// Equivalent to "return true;"
+ template <typename Rep, typename Period>
+ bool try_lock_upgrade_for(chrono::duration<Rep, Period> const &)
+ {
+ return true;
+ }
+
+ /// Simulates a mutex try_unlock_shared_and_lock() operation.
+ /// Equivalent to "return true;"
+ bool try_unlock_shared_and_lock()
+ {
+ return true;
+ }
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ /// Simulates a mutex try_unlock_shared_and_lock_until() operation.
+ /// Equivalent to "return true;"
+ template <typename Clock, typename Duration>
+ bool try_unlock_shared_and_lock_until(chrono::time_point<Clock, Duration> const &)
+ {
+ return true;
+ }
+
+ /// Simulates a mutex try_unlock_shared_and_lock_for() operation.
+ /// Equivalent to "return true;"
+ template <typename Rep, typename Period>
+ bool try_unlock_shared_and_lock_for(chrono::duration<Rep, Period> const &)
+ {
+ return true;
+ }
+#endif
+
+ /// Simulates unlock_and_lock_shared().
+ /// Empty function.
+ void unlock_and_lock_shared()
+ {
+ }
+
+ /// Simulates a mutex try_unlock_shared_and_lock_upgrade() operation.
+ /// Equivalent to "return true;"
+ bool try_unlock_shared_and_lock_upgrade()
+ {
+ return true;
+ }
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ /// Simulates a mutex try_unlock_shared_and_lock_upgrade_until() operation.
+ /// Equivalent to "return true;"
+ template <typename Clock, typename Duration>
+ bool try_unlock_shared_and_lock_upgrade_until(chrono::time_point<Clock, Duration> const &)
+ {
+ return true;
+ }
+
+ /// Simulates a mutex try_unlock_shared_and_lock_upgrade_for() operation.
+ /// Equivalent to "return true;"
+ template <typename Rep, typename Period>
+ bool try_unlock_shared_and_lock_upgrade_for(chrono::duration<Rep, Period> const &)
+ {
+ return true;
+ }
+#endif
+
+ /// Simulates unlock_and_lock_upgrade().
+ /// Empty function.
+ void unlock_and_lock_upgrade()
+ {
+ }
+
+ /// Simulates unlock_upgrade_and_lock().
+ /// Empty function.
+ void unlock_upgrade_and_lock()
+ {
+ }
+
+ /// Simulates a mutex try_unlock_upgrade_and_lock() operation.
+ /// Equivalent to "return true;"
+ bool try_unlock_upgrade_and_lock()
+ {
+ return true;
+ }
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ /// Simulates a mutex try_unlock_upgrade_and_lock_until() operation.
+ /// Equivalent to "return true;"
+ template <typename Clock, typename Duration>
+ bool try_unlock_upgrade_and_lock_until(chrono::time_point<Clock, Duration> const &)
+ {
+ return true;
+ }
+
+ /// Simulates a mutex try_unlock_upgrade_and_lock_for() operation.
+ /// Equivalent to "return true;"
+ template <typename Rep, typename Period>
+ bool try_unlock_upgrade_and_lock_for(chrono::duration<Rep, Period> const &)
+ {
+ return true;
+ }
+#endif
+
+ /// Simulates unlock_upgrade_and_lock_shared().
+ /// Empty function.
+ void unlock_upgrade_and_lock_shared()
+ {
+ }
+
+ };
+
+} //namespace boost {
+
+
+#endif
diff --git a/boost/thread/once.hpp b/boost/thread/once.hpp
index acd216edd6..9fcfb53339 100644
--- a/boost/thread/once.hpp
+++ b/boost/thread/once.hpp
@@ -9,11 +9,18 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
+#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/once.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
+#if defined BOOST_THREAD_ONCE_FAST_EPOCH
#include <boost/thread/pthread/once.hpp>
+#elif defined BOOST_THREAD_ONCE_ATOMIC
+#include <boost/thread/pthread/once_atomic.hpp>
+#else
+#error "Once Not Implemented"
+#endif
#else
#error "Boost threads unavailable on this platform"
#endif
@@ -24,7 +31,9 @@ namespace boost
{
// template<class Callable, class ...Args> void
// call_once(once_flag& flag, Callable&& func, Args&&... args);
- inline void call_once(void (*func)(),once_flag& flag)
+template<typename Function>
+inline void call_once(Function func,once_flag& flag)
+//inline void call_once(void (*func)(),once_flag& flag)
{
call_once(flag,func);
}
diff --git a/boost/thread/ostream_buffer.hpp b/boost/thread/ostream_buffer.hpp
new file mode 100644
index 0000000000..cc02a9c0ce
--- /dev/null
+++ b/boost/thread/ostream_buffer.hpp
@@ -0,0 +1,45 @@
+// (C) Copyright 2013 Vicente J. Botet Escriba
+// 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)
+
+
+#ifndef BOOST_THREAD_OSTREAM_BUFFER_HPP
+#define BOOST_THREAD_OSTREAM_BUFFER_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <sstream>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ template <typename OStream>
+ class ostream_buffer
+ {
+ public:
+ typedef std::basic_ostringstream<typename OStream::char_type, typename OStream::traits_type> stream_type;
+ ostream_buffer(OStream& os) :
+ os_(os)
+ {
+ }
+ ~ostream_buffer()
+ {
+ os_ << o_str_.str();
+ }
+ stream_type& stream()
+ {
+ return o_str_;
+ }
+ private:
+ OStream& os_;
+ stream_type o_str_;
+ };
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // header
diff --git a/boost/thread/poly_lockable.hpp b/boost/thread/poly_lockable.hpp
new file mode 100644
index 0000000000..7346188116
--- /dev/null
+++ b/boost/thread/poly_lockable.hpp
@@ -0,0 +1,68 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_THREAD_POLY_LOCKABLE_HPP
+#define BOOST_THREAD_POLY_LOCKABLE_HPP
+
+#include <boost/thread/detail/delete.hpp>
+#include <boost/chrono/chrono.hpp>
+
+namespace boost
+{
+
+ //[basic_poly_lockable
+ class basic_poly_lockable
+ {
+ public:
+
+ virtual ~basic_poly_lockable() = 0;
+
+ virtual void lock() = 0;
+ virtual void unlock() = 0;
+
+ };
+ //]
+
+ //[poly_lockable
+ class poly_lockable : public basic_poly_lockable<Lockable>
+ {
+ public:
+
+ virtual ~poly_lockable() = 0;
+ virtual bool try_lock() = 0;
+ };
+ //]
+
+ //[timed_poly_lockable
+ class timed_poly_lockable: public poly_lockable<TimedLock>
+ {
+ public:
+ virtual ~timed_poly_lockable()=0;
+
+ virtual bool try_lock_until(chrono::system_clock::time_point const & abs_time)=0;
+ virtual bool try_lock_until(chrono::steady_clock::time_point const & abs_time)=0;
+ template <typename Clock, typename Duration>
+ bool try_lock_until(chrono::time_point<Clock, Duration> const & abs_time)
+ {
+ return try_lock_until(time_point_cast<Clock::time_point>(abs_time));
+ }
+
+ virtual bool try_lock_for(chrono::nanoseconds const & relative_time)=0;
+ template <typename Rep, typename Period>
+ bool try_lock_for(chrono::duration<Rep, Period> const & rel_time)
+ {
+ return try_lock_for(duration_cast<Clock::duration>(rel_time));
+ }
+
+ };
+ //]
+
+}
+#endif
diff --git a/boost/thread/poly_lockable_adapter.hpp b/boost/thread/poly_lockable_adapter.hpp
new file mode 100644
index 0000000000..448789ecbc
--- /dev/null
+++ b/boost/thread/poly_lockable_adapter.hpp
@@ -0,0 +1,89 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_THREAD_POLY_LOCKABLE_ADAPTER_HPP
+#define BOOST_THREAD_POLY_LOCKABLE_ADAPTER_HPP
+
+#include <boost/thread/poly_lockable.hpp>
+
+namespace boost
+{
+
+ //[poly_basic_lockable_adapter
+ template <typename Mutex, typename Base=poly_basic_lockable>
+ class poly_basic_lockable_adapter : public Base
+ {
+ public:
+ typedef Mutex mutex_type;
+
+ protected:
+ mutex_type& mtx() const
+ {
+ return mtx_;
+ }
+ mutable mutex_type mtx_; /*< mutable so that it can be modified by const functions >*/
+ public:
+
+ BOOST_THREAD_NO_COPYABLE( poly_basic_lockable_adapter) /*< no copyable >*/
+
+ poly_basic_lockable_adapter()
+ {}
+
+ void lock()
+ {
+ mtx().lock();
+ }
+ void unlock()
+ {
+ mtx().unlock();
+ }
+
+ };
+ //]
+
+ //[poly_lockable_adapter
+ template <typename Mutex, typename Base=poly_lockable>
+ class poly_lockable_adapter : public poly_basic_lockable_adapter<Mutex, Base>
+ {
+ public:
+ typedef Mutex mutex_type;
+
+ bool try_lock()
+ {
+ return this->mtx().try_lock();
+ }
+ };
+ //]
+
+ //[poly_timed_lockable_adapter
+ template <typename Mutex, typename Base=poly_timed_lockable>
+ class poly_timed_lockable_adapter: public poly_lockable_adapter<Mutex, Base>
+ {
+ public:
+ typedef Mutex mutex_type;
+
+ bool try_lock_until(chrono::system_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_lock_until(abs_time);
+ }
+ bool try_lock_until(chrono::steady_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_lock_until(abs_time);
+ }
+ bool try_lock_for(chrono::nanoseconds const & rel_time)
+ {
+ return this->mtx().try_lock_for(rel_time);
+ }
+
+ };
+ //]
+
+}
+#endif
diff --git a/boost/thread/poly_shared_lockable.hpp b/boost/thread/poly_shared_lockable.hpp
new file mode 100644
index 0000000000..4348ed76c2
--- /dev/null
+++ b/boost/thread/poly_shared_lockable.hpp
@@ -0,0 +1,135 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_THREAD_POLY_SHARED_LOCKABLE_HPP
+#define BOOST_THREAD_POLY_SHARED_LOCKABLE_HPP
+
+#include <boost/thread/poly_lockable.hpp>
+#include <boost/chrono/chrono.hpp>
+
+namespace boost
+{
+
+
+ //[shared_poly_lockable
+ class shared_poly_lockable: public timed_poly_lockable
+ {
+ public:
+ virtual ~shared_poly_lockable() = 0;
+
+ virtual void lock_shared() = 0;
+ virtual bool try_lock_shared() = 0;
+ virtual void unlock_shared() = 0;
+
+ virtual bool try_lock_shared_until(chrono::system_clock::time_point const & abs_time)=0;
+ virtual bool try_lock_shared_until(chrono::steady_clock::time_point const & abs_time)=0;
+ template <typename Clock, typename Duration>
+ bool try_lock_shared_until(chrono::time_point<Clock, Duration> const & abs_time)
+ {
+ return try_lock_shared_until(time_point_cast<Clock::time_point>(abs_time));
+ }
+
+ virtual bool try_lock_shared_for(chrono::nanoseconds const & relative_time)=0;
+ template <typename Rep, typename Period>
+ bool try_lock_shared_for(chrono::duration<Rep, Period> const & rel_time)
+ {
+ return try_lock_shared_for(duration_cast<Clock::duration>(rel_time));
+ }
+
+ };
+
+ //]
+
+ //[upgrade_poly_lockable
+ class upgrade_poly_lockable: public shared_poly_lockable
+ {
+ public:
+ virtual ~upgrade_poly_lockable() = 0;
+
+ virtual void lock_upgrade() = 0;
+ virtual bool try_lock_upgrade() = 0;
+ virtual void unlock_upgrade() = 0;
+
+ virtual bool try_lock_upgrade_until(chrono::system_clock::time_point const & abs_time)=0;
+ virtual bool try_lock_upgrade_until(chrono::steady_clock::time_point const & abs_time)=0;
+ template <typename Clock, typename Duration>
+ bool try_lock_upgrade_until(chrono::time_point<Clock, Duration> const & abs_time)
+ {
+ return try_lock_upgrade_until(time_point_cast<Clock::time_point>(abs_time));
+ }
+
+ virtual bool try_lock_upgrade_for(chrono::nanoseconds const & relative_time)=0;
+ template <typename Rep, typename Period>
+ bool try_lock_upgrade_for(chrono::duration<Rep, Period> const & rel_time)
+ {
+ return try_lock_upgrade_for(duration_cast<Clock::duration>(rel_time));
+ }
+
+ virtual bool try_unlock_shared_and_lock() = 0;
+
+ virtual bool try_unlock_shared_and_lock_until(chrono::system_clock::time_point const & abs_time)=0;
+ virtual bool try_unlock_shared_and_lock_until(chrono::steady_clock::time_point const & abs_time)=0;
+ template <typename Clock, typename Duration>
+ bool try_unlock_shared_and_lock_until(chrono::time_point<Clock, Duration> const & abs_time)
+ {
+ return try_unlock_shared_and_lock_until(time_point_cast<Clock::time_point>(abs_time));
+ }
+
+ virtual bool try_unlock_shared_and_lock_for(chrono::nanoseconds const & relative_time)=0;
+ template <typename Rep, typename Period>
+ bool try_unlock_shared_and_lock_for(chrono::duration<Rep, Period> const & rel_time)
+ {
+ return try_unlock_shared_and_lock_for(duration_cast<Clock::duration>(rel_time));
+ }
+
+ virtual void unlock_and_lock_shared() = 0;
+ virtual bool try_unlock_shared_and_lock_upgrade() = 0;
+
+ virtual bool try_unlock_shared_and_lock_upgrade_until(chrono::system_clock::time_point const & abs_time)=0;
+ virtual bool try_unlock_shared_and_lock_upgrade_until(chrono::steady_clock::time_point const & abs_time)=0;
+ template <typename Clock, typename Duration>
+ bool try_unlock_shared_and_lock_upgrade_until(chrono::time_point<Clock, Duration> const & abs_time)
+ {
+ return try_unlock_shared_and_lock_upgrade_until(time_point_cast<Clock::time_point>(abs_time));
+ }
+
+ virtual bool try_unlock_shared_and_lock_upgrade_for(chrono::nanoseconds const & relative_time)=0;
+ template <typename Rep, typename Period>
+ bool try_unlock_shared_and_lock_upgrade_for(chrono::duration<Rep, Period> const & rel_time)
+ {
+ return try_unlock_shared_and_lock_upgrade_for(duration_cast<Clock::duration>(rel_time));
+ }
+
+ virtual void unlock_and_lock_upgrade() = 0;
+ virtual void unlock_upgrade_and_lock() = 0;
+ virtual bool try_unlock_upgrade_and_lock() = 0;
+
+ virtual bool try_unlock_upgrade_and_lock_until(chrono::system_clock::time_point const & abs_time)=0;
+ virtual bool try_unlock_upgrade_and_lock_until(chrono::steady_clock::time_point const & abs_time)=0;
+ template <typename Clock, typename Duration>
+ bool try_unlock_upgrade_and_lock_until(chrono::time_point<Clock, Duration> const & abs_time)
+ {
+ return try_unlock_upgrade_and_lock_until(time_point_cast<Clock::time_point>(abs_time));
+ }
+
+ virtual bool try_unlock_upgrade_and_lock_for(chrono::nanoseconds const & relative_time)=0;
+ template <typename Rep, typename Period>
+ bool try_unlock_upgrade_and_lock_for(chrono::duration<Rep, Period> const & rel_time)
+ {
+ return try_unlock_upgrade_and_lock_for(duration_cast<Clock::duration>(rel_time));
+ }
+
+ virtual void unlock_upgrade_and_lock_shared() = 0;
+
+ };
+//]
+
+}
+#endif
diff --git a/boost/thread/poly_shared_lockable_adapter.hpp b/boost/thread/poly_shared_lockable_adapter.hpp
new file mode 100644
index 0000000000..f136128907
--- /dev/null
+++ b/boost/thread/poly_shared_lockable_adapter.hpp
@@ -0,0 +1,170 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_THREAD_POLY_SHARED_LOCKABLE_ADAPTER_HPP
+#define BOOST_THREAD_POLY_SHARED_LOCKABLE_ADAPTER_HPP
+
+#include <boost/thread/poly_lockable_adapter.hpp>
+#include <boost/thread/poly_shared_lockable.hpp>
+
+namespace boost
+{
+
+ //[shared_lockable_adapter
+ template <typename Mutex, typename Base=poly_shared_lockable>
+ class poly_shared_lockable_adapter: public poly_timed_lockable_adapter<Mutex, Base>
+ {
+ public:
+ typedef Mutex mutex_type;
+
+ void lock_shared()
+ {
+ this->mtx().lock_shared();
+ }
+ bool try_lock_shared()
+ {
+ return this->mtx().try_lock_shared();
+ }
+ void unlock_shared()
+ {
+ this->mtx().unlock_shared();
+ }
+
+ bool try_lock_shared_until(chrono::system_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_lock_shared_until(abs_time);
+ }
+ bool try_lock_shared_until(chrono::steady_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_lock_shared_until(abs_time);
+ }
+ bool try_lock_shared_for(chrono::nanoseconds const & rel_time)
+ {
+ return this->mtx().try_lock_shared_for(rel_time);
+ }
+
+ };
+
+ //]
+
+ //[upgrade_lockable_adapter
+ template <typename Mutex, typename Base=poly_shared_lockable>
+ class upgrade_lockable_adapter: public shared_lockable_adapter<Mutex, Base>
+ {
+ public:
+ typedef Mutex mutex_type;
+
+ void lock_upgrade()
+ {
+ this->mtx().lock_upgrade();
+ }
+
+ bool try_lock_upgrade()
+ {
+ return this->mtx().try_lock_upgrade();
+ }
+
+ void unlock_upgrade()
+ {
+ this->mtx().unlock_upgrade();
+ }
+
+ bool try_lock_upgrade_until(chrono::system_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_lock_upgrade_until(abs_time);
+ }
+ bool try_lock_upgrade_until(chrono::steady_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_lock_upgrade_until(abs_time);
+ }
+ bool try_lock_upgrade_for(chrono::nanoseconds const & rel_time)
+ {
+ return this->mtx().try_lock_upgrade_for(rel_time);
+ }
+
+ bool try_unlock_shared_and_lock()
+ {
+ return this->mtx().try_unlock_shared_and_lock();
+ }
+
+ bool try_unlock_shared_and_lock_until(chrono::system_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_unlock_shared_and_lock_until(abs_time);
+ }
+ bool try_unlock_shared_and_lock_until(chrono::steady_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_unlock_shared_and_lock_until(abs_time);
+ }
+ template <typename Rep, typename Period>
+ bool try_unlock_shared_and_lock_for(chrono::nanoseconds const & rel_time)
+ {
+ return this->mtx().try_unlock_shared_and_lock_for(rel_time);
+ }
+
+ void unlock_and_lock_shared()
+ {
+ this->mtx().unlock_and_lock_shared();
+ }
+
+ bool try_unlock_shared_and_lock_upgrade()
+ {
+ return this->mtx().try_unlock_shared_and_lock_upgrade();
+ }
+
+ bool try_unlock_shared_and_lock_upgrade_until(chrono::system_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_unlock_shared_and_lock_upgrade_until(abs_time);
+ }
+ bool try_unlock_shared_and_lock_upgrade_until(chrono::steady_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_unlock_shared_and_lock_upgrade_until(abs_time);
+ }
+ bool try_unlock_shared_and_lock_upgrade_for(chrono::nanoseconds const & rel_time)
+ {
+ return this->mtx().try_unlock_shared_and_lock_upgrade_for(rel_time);
+ }
+
+ void unlock_and_lock_upgrade()
+ {
+ this->mtx().unlock_and_lock_upgrade();
+ }
+
+ void unlock_upgrade_and_lock()
+ {
+ this->mtx().unlock_upgrade_and_lock();
+ }
+
+ bool try_unlock_upgrade_and_lock()
+ {
+ return this->mtx().try_unlock_upgrade_and_lock();
+ }
+ bool try_unlock_upgrade_and_lock_until(chrono::system_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_unlock_upgrade_and_lock_until(abs_time);
+ }
+ bool try_unlock_upgrade_and_lock_until(chrono::steady_clock::time_point const & abs_time)
+ {
+ return this->mtx().try_unlock_upgrade_and_lock_until(abs_time);
+ }
+ bool try_unlock_upgrade_and_lock_for(chrono::nanoseconds const & rel_time)
+ {
+ return this->mtx().try_unlock_upgrade_and_lock_for(rel_time);
+ }
+
+ void unlock_upgrade_and_lock_shared()
+ {
+ this->mtx().unlock_upgrade_and_lock_shared();
+ }
+
+ };
+//]
+
+}
+#endif
diff --git a/boost/thread/pthread/condition_variable.hpp b/boost/thread/pthread/condition_variable.hpp
index aa7100766e..b30d37f9b0 100644
--- a/boost/thread/pthread/condition_variable.hpp
+++ b/boost/thread/pthread/condition_variable.hpp
@@ -4,11 +4,13 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-10 Anthony Williams
-// (C) Copyright 2011 Vicente J. Botet Escriba
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
#include <boost/thread/pthread/thread_data.hpp>
+#endif
#include <boost/thread/pthread/condition_variable_fwd.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
@@ -20,10 +22,12 @@
namespace boost
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
namespace this_thread
{
void BOOST_THREAD_DECL interruption_point();
}
+#endif
namespace thread_cv_detail
{
@@ -53,57 +57,88 @@ namespace boost
inline void condition_variable::wait(unique_lock<mutex>& m)
{
+#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+ if(! m.owns_lock())
+ {
+ boost::throw_exception(condition_error(-1, "boost::condition_variable::wait() failed precondition mutex not owned"));
+ }
+#endif
int res=0;
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
do {
res = pthread_cond_wait(&cond,&internal_mutex);
} while (res == EINTR);
+#else
+ //boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
+ pthread_mutex_t* the_mutex = m.mutex()->native_handle();
+ do {
+ res = pthread_cond_wait(&cond,the_mutex);
+ } while (res == EINTR);
+#endif
}
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
+#endif
if(res)
{
- boost::throw_exception(condition_error(res, "boost:: condition_variable constructor failed in pthread_cond_wait"));
+ boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait"));
}
}
- inline bool condition_variable::do_timed_wait(
+ inline bool condition_variable::do_wait_until(
unique_lock<mutex>& m,
struct timespec const &timeout)
{
+#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
if (!m.owns_lock())
- boost::throw_exception(condition_error(EPERM, "condition_variable do_timed_wait: mutex not locked"));
-
+ {
+ boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned"));
+ }
+#endif
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
int cond_res;
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
+#else
+ //boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
+ pthread_mutex_t* the_mutex = m.mutex()->native_handle();
+ cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
+#endif
}
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
+#endif
if(cond_res==ETIMEDOUT)
{
return false;
}
if(cond_res)
{
- boost::throw_exception(condition_error(cond_res, "condition_variable failed in pthread_cond_timedwait"));
+ boost::throw_exception(condition_error(cond_res, "boost::condition_variable::do_wait_until failed in pthread_cond_timedwait"));
}
return true;
}
inline void condition_variable::notify_one() BOOST_NOEXCEPT
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
+#endif
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
inline void condition_variable::notify_all() BOOST_NOEXCEPT
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
+#endif
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
@@ -119,13 +154,13 @@ namespace boost
int const res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
- boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_mutex_init"));
+ boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
- boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_cond_init"));
+ boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init"));
}
}
~condition_variable_any()
@@ -140,14 +175,20 @@ namespace boost
int res=0;
{
thread_cv_detail::lock_on_exit<lock_type> guard;
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
+#else
+ boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
+#endif
guard.activate(m);
res=pthread_cond_wait(&cond,&internal_mutex);
}
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
+#endif
if(res)
{
- boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_wait"));
+ boost::throw_exception(condition_error(res, "boost::condition_variable_any::wait() failed in pthread_cond_wait"));
}
}
@@ -157,16 +198,17 @@ namespace boost
while(!pred()) wait(m);
}
+#if defined BOOST_THREAD_USES_DATETIME
template<typename lock_type>
- bool timed_wait(lock_type& m,boost::system_time const& wait_until)
+ bool timed_wait(lock_type& m,boost::system_time const& abs_time)
{
- struct timespec const timeout=detail::get_timespec(wait_until);
- return do_timed_wait(m, timeout);
+ struct timespec const timeout=detail::to_timespec(abs_time);
+ return do_wait_until(m, timeout);
}
template<typename lock_type>
- bool timed_wait(lock_type& m,xtime const& wait_until)
+ bool timed_wait(lock_type& m,xtime const& abs_time)
{
- return timed_wait(m,system_time(wait_until));
+ return timed_wait(m,system_time(abs_time));
}
template<typename lock_type,typename duration_type>
@@ -176,20 +218,20 @@ namespace boost
}
template<typename lock_type,typename predicate_type>
- bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
+ bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred)
{
while (!pred())
{
- if(!timed_wait(m, wait_until))
+ if(!timed_wait(m, abs_time))
return pred();
}
return true;
}
template<typename lock_type,typename predicate_type>
- bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred)
+ bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred)
{
- return timed_wait(m,system_time(wait_until),pred);
+ return timed_wait(m,system_time(abs_time),pred);
}
template<typename lock_type,typename duration_type,typename predicate_type>
@@ -197,7 +239,7 @@ namespace boost
{
return timed_wait(m,get_system_time()+wait_duration,pred);
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type,class Duration>
cv_status
@@ -265,26 +307,26 @@ namespace boost
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
- while (!pred())
- {
- if (wait_for(lock, d) == cv_status::timeout)
- return pred();
- }
- return true;
+ return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
+
+// while (!pred())
+// {
+// if (wait_for(lock, d) == cv_status::timeout)
+// return pred();
+// }
+// return true;
}
template <class lock_type>
- inline void wait_until(
+ cv_status wait_until(
lock_type& lk,
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
- timespec ts;
- seconds s = duration_cast<seconds>(d);
- ts.tv_sec = static_cast<long>(s.count());
- ts.tv_nsec = static_cast<long>((d - s).count());
- do_timed_wait(lk, ts);
+ timespec ts = boost::detail::to_timespec(d);
+ if (do_wait_until(lk, ts)) return cv_status::no_timeout;
+ else return cv_status::timeout;
}
#endif
@@ -302,25 +344,31 @@ namespace boost
private: // used by boost::thread::try_join_until
template <class lock_type>
- inline bool do_timed_wait(
+ inline bool do_wait_until(
lock_type& m,
struct timespec const &timeout)
{
int res=0;
{
thread_cv_detail::lock_on_exit<lock_type> guard;
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
+#else
+ boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
+#endif
guard.activate(m);
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
}
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
+#endif
if(res==ETIMEDOUT)
{
return false;
}
if(res)
{
- boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_timedwait"));
+ boost::throw_exception(condition_error(res, "boost::condition_variable_any::do_wait_until() failed in pthread_cond_timedwait"));
}
return true;
}
diff --git a/boost/thread/pthread/condition_variable_fwd.hpp b/boost/thread/pthread/condition_variable_fwd.hpp
index 4f4bd881d9..e18030fd5f 100644
--- a/boost/thread/pthread/condition_variable_fwd.hpp
+++ b/boost/thread/pthread/condition_variable_fwd.hpp
@@ -4,22 +4,26 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
-// (C) Copyright 2011 Vicente J. Botet Escriba
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
#include <pthread.h>
#include <boost/thread/cv_status.hpp>
#include <boost/thread/mutex.hpp>
-#include <boost/thread/locks.hpp>
+#include <boost/thread/lock_types.hpp>
#include <boost/thread/thread_time.hpp>
+#include <boost/thread/pthread/timespec.hpp>
+#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>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/date_time/posix_time/posix_time_duration.hpp>
+
#include <boost/config/abi_prefix.hpp>
namespace boost
@@ -28,33 +32,58 @@ namespace boost
class condition_variable
{
private:
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
pthread_mutex_t internal_mutex;
+#endif
pthread_cond_t cond;
public:
+ //private: // used by boost::thread::try_join_until
+
+ inline bool do_wait_until(
+ unique_lock<mutex>& lock,
+ struct timespec const &timeout);
+
+ bool do_wait_for(
+ unique_lock<mutex>& lock,
+ struct timespec const &timeout)
+ {
+ return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now()));
+ }
+
+ public:
BOOST_THREAD_NO_COPYABLE(condition_variable)
condition_variable()
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
int const res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
- boost::throw_exception(thread_resource_error(res, "boost:: condition_variable constructor failed in pthread_mutex_init"));
+ boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
}
+#endif
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
- boost::throw_exception(thread_resource_error(res2, "boost:: condition_variable constructor failed in pthread_cond_init"));
+#endif
+ boost::throw_exception(thread_resource_error(res2, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init"));
}
}
~condition_variable()
{
- BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
int ret;
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ do {
+ ret = pthread_mutex_destroy(&internal_mutex);
+ } while (ret == EINTR);
+ BOOST_ASSERT(!ret);
+#endif
do {
ret = pthread_cond_destroy(&cond);
} while (ret == EINTR);
- BOOST_VERIFY(!ret);
+ BOOST_ASSERT(!ret);
}
void wait(unique_lock<mutex>& m);
@@ -66,23 +95,24 @@ namespace boost
}
+#if defined BOOST_THREAD_USES_DATETIME
inline bool timed_wait(
unique_lock<mutex>& m,
- boost::system_time const& wait_until)
+ boost::system_time const& abs_time)
{
#if defined BOOST_THREAD_WAIT_BUG
- struct timespec const timeout=detail::get_timespec(wait_until + BOOST_THREAD_WAIT_BUG);
- return do_timed_wait(m, timeout);
+ struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG);
+ return do_wait_until(m, timeout);
#else
- struct timespec const timeout=detail::get_timespec(wait_until);
- return do_timed_wait(m, timeout);
+ struct timespec const timeout=detail::to_timespec(abs_time);
+ return do_wait_until(m, timeout);
#endif
}
bool timed_wait(
unique_lock<mutex>& m,
- xtime const& wait_until)
+ xtime const& abs_time)
{
- return timed_wait(m,system_time(wait_until));
+ return timed_wait(m,system_time(abs_time));
}
template<typename duration_type>
@@ -96,11 +126,11 @@ namespace boost
template<typename predicate_type>
bool timed_wait(
unique_lock<mutex>& m,
- boost::system_time const& wait_until,predicate_type pred)
+ boost::system_time const& abs_time,predicate_type pred)
{
while (!pred())
{
- if(!timed_wait(m, wait_until))
+ if(!timed_wait(m, abs_time))
return pred();
}
return true;
@@ -109,9 +139,9 @@ namespace boost
template<typename predicate_type>
bool timed_wait(
unique_lock<mutex>& m,
- xtime const& wait_until,predicate_type pred)
+ xtime const& abs_time,predicate_type pred)
{
- return timed_wait(m,system_time(wait_until),pred);
+ return timed_wait(m,system_time(abs_time),pred);
}
template<typename duration_type,typename predicate_type>
@@ -121,6 +151,7 @@ namespace boost
{
return timed_wait(m,get_system_time()+wait_duration,pred);
}
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
@@ -190,12 +221,14 @@ namespace boost
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
- while (!pred())
- {
- if (wait_for(lock, d) == cv_status::timeout)
- return pred();
- }
- return true;
+ return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
+
+// while (!pred())
+// {
+// if (wait_for(lock, d) == cv_status::timeout)
+// return pred();
+// }
+// return true;
}
#endif
@@ -210,27 +243,24 @@ namespace boost
void notify_all() BOOST_NOEXCEPT;
#ifdef BOOST_THREAD_USES_CHRONO
- inline void wait_until(
+ inline cv_status wait_until(
unique_lock<mutex>& lk,
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
- timespec ts;
- seconds s = duration_cast<seconds>(d);
- ts.tv_sec = static_cast<long>(s.count());
- ts.tv_nsec = static_cast<long>((d - s).count());
- do_timed_wait(lk, ts);
+ timespec ts = boost::detail::to_timespec(d);
+ if (do_wait_until(lk, ts)) return cv_status::no_timeout;
+ else return cv_status::timeout;
}
#endif
- //private: // used by boost::thread::try_join_until
-
- inline bool do_timed_wait(
- unique_lock<mutex>& lock,
- struct timespec const &timeout);
};
+
+ BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
+
}
+
#include <boost/config/abi_suffix.hpp>
#endif
diff --git a/boost/thread/pthread/mutex.hpp b/boost/thread/pthread/mutex.hpp
index 2c5af92b8a..3e9af2a833 100644
--- a/boost/thread/pthread/mutex.hpp
+++ b/boost/thread/pthread/mutex.hpp
@@ -6,10 +6,14 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
+#include <boost/thread/detail/config.hpp>
#include <pthread.h>
#include <boost/throw_exception.hpp>
+#include <boost/core/ignore_unused.hpp>
#include <boost/thread/exceptions.hpp>
-#include <boost/thread/locks.hpp>
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+#include <boost/thread/lock_types.hpp>
+#endif
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/assert.hpp>
@@ -23,15 +27,68 @@
#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
-#if _POSIX_TIMEOUTS >= 0 && _POSIX_C_SOURCE>=200112L
+#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
+#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
+#endif
+
#include <boost/config/abi_prefix.hpp>
+#ifndef BOOST_THREAD_HAS_NO_EINTR_BUG
+#define BOOST_THREAD_HAS_EINTR_BUG
+#endif
+
namespace boost
{
+ namespace posix {
+#ifdef BOOST_THREAD_HAS_EINTR_BUG
+ BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m)
+ {
+ int ret;
+ do
+ {
+ ret = ::pthread_mutex_destroy(m);
+ } while (ret == EINTR);
+ return ret;
+ }
+ BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m)
+ {
+ int ret;
+ do
+ {
+ ret = ::pthread_mutex_lock(m);
+ } while (ret == EINTR);
+ return ret;
+ }
+ BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m)
+ {
+ int ret;
+ do
+ {
+ ret = ::pthread_mutex_unlock(m);
+ } while (ret == EINTR);
+ return ret;
+ }
+#else
+ BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m)
+ {
+ return ::pthread_mutex_destroy(m);
+ }
+ BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m)
+ {
+ return ::pthread_mutex_lock(m);
+ }
+ BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m)
+ {
+ return ::pthread_mutex_unlock(m);
+ }
+
+#endif
+
+ }
class mutex
{
private:
@@ -49,20 +106,14 @@ namespace boost
}
~mutex()
{
- int ret;
- do
- {
- ret = pthread_mutex_destroy(&m);
- } while (ret == EINTR);
+ int const res = posix::pthread_mutex_destroy(&m);
+ boost::ignore_unused(res);
+ BOOST_ASSERT(!res);
}
void lock()
{
- int res;
- do
- {
- res = pthread_mutex_lock(&m);
- } while (res == EINTR);
+ int res = posix::pthread_mutex_lock(&m);
if (res)
{
boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
@@ -71,12 +122,11 @@ namespace boost
void unlock()
{
- int ret;
- do
+ int res = posix::pthread_mutex_unlock(&m);
+ if (res)
{
- ret = pthread_mutex_unlock(&m);
- } while (ret == EINTR);
- BOOST_VERIFY(!ret);
+ boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
+ }
}
bool try_lock()
@@ -86,12 +136,8 @@ namespace boost
{
res = pthread_mutex_trylock(&m);
} while (res == EINTR);
- if(res && (res!=EBUSY))
+ if (res==EBUSY)
{
- // The following throw_exception has been replaced by an assertion and just return false,
- // as this is an internal error and the user can do nothing with the exception.
- //boost::throw_exception(lock_error(res,"boost: mutex try_lock failed in pthread_mutex_trylock"));
- BOOST_ASSERT_MSG(false ,"boost: mutex try_lock failed in pthread_mutex_trylock");
return false;
}
@@ -105,8 +151,10 @@ namespace boost
return &m;
}
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
typedef unique_lock<mutex> scoped_lock;
typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
+#endif
};
typedef mutex try_mutex;
@@ -132,7 +180,8 @@ namespace boost
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
- BOOST_VERIFY(!pthread_mutex_destroy(&m));
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
+ //BOOST_VERIFY(!pthread_mutex_destroy(&m));
boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
}
is_locked=false;
@@ -140,12 +189,13 @@ namespace boost
}
~timed_mutex()
{
- BOOST_VERIFY(!pthread_mutex_destroy(&m));
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
+#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
@@ -155,23 +205,39 @@ namespace boost
{
return timed_lock(system_time(absolute_time));
}
-
+#endif
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
void lock()
{
- BOOST_VERIFY(!pthread_mutex_lock(&m));
+ int res = posix::pthread_mutex_lock(&m);
+ if (res)
+ {
+ boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
+ }
}
void unlock()
{
- BOOST_VERIFY(!pthread_mutex_unlock(&m));
+ int res = posix::pthread_mutex_unlock(&m);
+ if (res)
+ {
+ boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
+ }
}
bool try_lock()
{
- int const res=pthread_mutex_trylock(&m);
- BOOST_ASSERT(!res || res==EBUSY);
- return !res;
+ int res;
+ do
+ {
+ res = pthread_mutex_trylock(&m);
+ } while (res == EINTR);
+ if (res==EBUSY)
+ {
+ return false;
+ }
+
+ return !res;
}
@@ -232,12 +298,13 @@ namespace boost
public:
#endif
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(system_time const & abs_time)
{
- struct timespec const ts=detail::get_timespec(abs_time);
+ struct timespec const ts=boost::detail::to_timespec(abs_time);
return do_try_lock_until(ts);
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
@@ -261,12 +328,9 @@ namespace boost
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
- using namespace chrono;
- nanoseconds d = tp.time_since_epoch();
- timespec ts;
- seconds s = duration_cast<seconds>(d);
- ts.tv_sec = static_cast<long>(s.count());
- ts.tv_nsec = static_cast<long>((d - s).count());
+ //using namespace chrono;
+ chrono::nanoseconds d = tp.time_since_epoch();
+ timespec ts = boost::detail::to_timespec(d);
return do_try_lock_until(ts);
}
#endif
@@ -278,9 +342,11 @@ namespace boost
return &m;
}
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
+#endif
};
}
diff --git a/boost/thread/pthread/once.hpp b/boost/thread/pthread/once.hpp
index 80aa09ee12..0bef0387de 100644
--- a/boost/thread/pthread/once.hpp
+++ b/boost/thread/pthread/once.hpp
@@ -11,21 +11,50 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/detail/invoke.hpp>
-#include <pthread.h>
-#include <boost/assert.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
-#include <boost/cstdint.hpp>
#include <boost/thread/detail/delete.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/bind.hpp>
+#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
+#include <boost/cstdint.hpp>
+#include <pthread.h>
+#include <csignal>
+
namespace boost
{
-#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
+ struct once_flag;
+
+ #define BOOST_ONCE_INITIAL_FLAG_VALUE 0
+
+ namespace thread_detail
+ {
+ typedef boost::uint32_t uintmax_atomic_t;
+ #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(value) value##u
+ #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(~0)
+
+ }
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template<typename Function, class ...ArgTypes>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args);
+#else
+ template<typename Function>
+ inline void call_once(once_flag& flag, Function f);
+ template<typename Function, typename T1>
+ inline void call_once(once_flag& flag, Function f, T1 p1);
+ template<typename Function, typename T1, typename T2>
+ inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2);
+ template<typename Function, typename T1, typename T2, typename T3>
+ inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3);
+#endif
struct once_flag
{
@@ -34,78 +63,476 @@ namespace boost
: epoch(BOOST_ONCE_INITIAL_FLAG_VALUE)
{}
private:
- boost::uintmax_t epoch;
+ volatile thread_detail::uintmax_atomic_t epoch;
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template<typename Function, class ...ArgTypes>
+ friend void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args);
+#else
template<typename Function>
- friend
- void call_once(once_flag& flag,Function f);
+ friend void call_once(once_flag& flag, Function f);
+ template<typename Function, typename T1>
+ friend void call_once(once_flag& flag, Function f, T1 p1);
+ template<typename Function, typename T1, typename T2>
+ friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2);
+ template<typename Function, typename T1, typename T2, typename T3>
+ friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3);
+
+#endif
+
};
+#define BOOST_ONCE_INIT once_flag()
+
#else // BOOST_THREAD_PROVIDES_ONCE_CXX11
struct once_flag
{
- boost::uintmax_t epoch;
+ volatile thread_detail::uintmax_atomic_t epoch;
};
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
- namespace detail
+
+#if defined BOOST_THREAD_PROVIDES_INVOKE
+#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL
+#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET
+#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void>
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL
+#else
+#define BOOST_THREAD_INVOKE_RET_VOID boost::bind
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL ()
+#endif
+
+ namespace thread_detail
{
- BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
- BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch;
+ BOOST_THREAD_DECL uintmax_atomic_t& get_once_per_thread_epoch();
+ BOOST_THREAD_DECL extern uintmax_atomic_t once_global_epoch;
BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
}
// Based on Mike Burrows fast_pthread_once algorithm as described in
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
- template<typename Function>
- void call_once(once_flag& flag,Function f)
+
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+
+ template<typename Function, class ...ArgTypes>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args)
+ {
+ static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
+ static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
+ thread_detail::uintmax_atomic_t const epoch=flag.epoch;
+ thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
+
+ if(epoch<this_thread_epoch)
{
- static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
- static boost::uintmax_t const being_initialized=uninitialized_flag+1;
- boost::uintmax_t const epoch=flag.epoch;
- boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
+ pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
- if(epoch<this_thread_epoch)
+ while(flag.epoch<=being_initialized)
{
- pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
+ if(flag.epoch==uninitialized_flag)
+ {
+ flag.epoch=being_initialized;
+ BOOST_TRY
+ {
+ pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ flag.epoch=uninitialized_flag;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ flag.epoch=--thread_detail::once_global_epoch;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ }
+ else
+ {
+ while(flag.epoch==being_initialized)
+ {
+ BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ }
+ }
+ }
+ this_thread_epoch=thread_detail::once_global_epoch;
- while(flag.epoch<=being_initialized)
+ }
+ }
+#else
+ template<typename Function>
+ inline void call_once(once_flag& flag, Function f)
+ {
+ static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
+ static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
+ thread_detail::uintmax_atomic_t const epoch=flag.epoch;
+ thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
+
+ if(epoch<this_thread_epoch)
+ {
+ pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
+
+ while(flag.epoch<=being_initialized)
+ {
+ if(flag.epoch==uninitialized_flag)
{
- if(flag.epoch==uninitialized_flag)
+ flag.epoch=being_initialized;
+ BOOST_TRY
{
- flag.epoch=being_initialized;
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
- {
-#endif
- pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
- f();
-#ifndef BOOST_NO_EXCEPTIONS
- }
- catch(...) // BOOST_NO_EXCEPTIONS protected
- {
- flag.epoch=uninitialized_flag;
- BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
- throw; // BOOST_NO_EXCEPTIONS protected
- }
-#endif
- flag.epoch=--detail::once_global_epoch;
- BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
+ pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
+ f();
+ }
+ BOOST_CATCH (...)
+ {
+ flag.epoch=uninitialized_flag;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ flag.epoch=--thread_detail::once_global_epoch;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ }
+ else
+ {
+ while(flag.epoch==being_initialized)
+ {
+ BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ }
+ }
+ }
+ this_thread_epoch=thread_detail::once_global_epoch;
+ }
+ }
+
+ template<typename Function, typename T1>
+ inline void call_once(once_flag& flag, Function f, T1 p1)
+ {
+ static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
+ static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
+ thread_detail::uintmax_atomic_t const epoch=flag.epoch;
+ thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
+
+ if(epoch<this_thread_epoch)
+ {
+ pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
+
+ while(flag.epoch<=being_initialized)
+ {
+ if(flag.epoch==uninitialized_flag)
+ {
+ flag.epoch=being_initialized;
+ BOOST_TRY
+ {
+ pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ flag.epoch=uninitialized_flag;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ flag.epoch=--thread_detail::once_global_epoch;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ }
+ else
+ {
+ while(flag.epoch==being_initialized)
+ {
+ BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ }
+ }
+ }
+ this_thread_epoch=thread_detail::once_global_epoch;
+ }
+ }
+ template<typename Function, typename T1, typename T2>
+ inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2)
+ {
+ static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
+ static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
+ thread_detail::uintmax_atomic_t const epoch=flag.epoch;
+ thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
+
+ if(epoch<this_thread_epoch)
+ {
+ pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
+
+ while(flag.epoch<=being_initialized)
+ {
+ if(flag.epoch==uninitialized_flag)
+ {
+ flag.epoch=being_initialized;
+ BOOST_TRY
+ {
+ pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ flag.epoch=uninitialized_flag;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ flag.epoch=--thread_detail::once_global_epoch;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ }
+ else
+ {
+ while(flag.epoch==being_initialized)
+ {
+ BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ }
+ }
+ }
+ this_thread_epoch=thread_detail::once_global_epoch;
+ }
+ }
+
+ template<typename Function, typename T1, typename T2, typename T3>
+ inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3)
+ {
+ static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
+ static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
+ thread_detail::uintmax_atomic_t const epoch=flag.epoch;
+ thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
+
+ if(epoch<this_thread_epoch)
+ {
+ pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
+
+ while(flag.epoch<=being_initialized)
+ {
+ if(flag.epoch==uninitialized_flag)
+ {
+ flag.epoch=being_initialized;
+ BOOST_TRY
+ {
+ pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ flag.epoch=uninitialized_flag;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_RETHROW
}
- else
+ BOOST_CATCH_END
+ flag.epoch=--thread_detail::once_global_epoch;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ }
+ else
+ {
+ while(flag.epoch==being_initialized)
{
- while(flag.epoch==being_initialized)
- {
- BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex));
- }
+ BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
}
}
- this_thread_epoch=detail::once_global_epoch;
}
+ this_thread_epoch=thread_detail::once_global_epoch;
}
+ }
+
+ template<typename Function>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
+ {
+ static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
+ static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
+ thread_detail::uintmax_atomic_t const epoch=flag.epoch;
+ thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
+
+ if(epoch<this_thread_epoch)
+ {
+ pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
+
+ while(flag.epoch<=being_initialized)
+ {
+ if(flag.epoch==uninitialized_flag)
+ {
+ flag.epoch=being_initialized;
+ BOOST_TRY
+ {
+ pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
+ f();
+ }
+ BOOST_CATCH (...)
+ {
+ flag.epoch=uninitialized_flag;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ flag.epoch=--thread_detail::once_global_epoch;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ }
+ else
+ {
+ while(flag.epoch==being_initialized)
+ {
+ BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ }
+ }
+ }
+ this_thread_epoch=thread_detail::once_global_epoch;
+ }
+ }
+
+ template<typename Function, typename T1>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1)
+ {
+ static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
+ static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
+ thread_detail::uintmax_atomic_t const epoch=flag.epoch;
+ thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
+
+ if(epoch<this_thread_epoch)
+ {
+ pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
+
+ while(flag.epoch<=being_initialized)
+ {
+ if(flag.epoch==uninitialized_flag)
+ {
+ flag.epoch=being_initialized;
+ BOOST_TRY
+ {
+ pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ flag.epoch=uninitialized_flag;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ flag.epoch=--thread_detail::once_global_epoch;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ }
+ else
+ {
+ while(flag.epoch==being_initialized)
+ {
+ BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ }
+ }
+ }
+ this_thread_epoch=thread_detail::once_global_epoch;
+ }
+ }
+ template<typename Function, typename T1, typename T2>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
+ {
+ static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
+ static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
+ thread_detail::uintmax_atomic_t const epoch=flag.epoch;
+ thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
+
+ if(epoch<this_thread_epoch)
+ {
+ pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
+
+ while(flag.epoch<=being_initialized)
+ {
+ if(flag.epoch==uninitialized_flag)
+ {
+ flag.epoch=being_initialized;
+ BOOST_TRY
+ {
+ pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T1>(p2))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ flag.epoch=uninitialized_flag;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ flag.epoch=--thread_detail::once_global_epoch;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ }
+ else
+ {
+ while(flag.epoch==being_initialized)
+ {
+ BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ }
+ }
+ }
+ this_thread_epoch=thread_detail::once_global_epoch;
+ }
+ }
+
+ template<typename Function, typename T1, typename T2, typename T3>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3)
+ {
+ static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
+ static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
+ thread_detail::uintmax_atomic_t const epoch=flag.epoch;
+ thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
+
+ if(epoch<this_thread_epoch)
+ {
+ pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
+
+ while(flag.epoch<=being_initialized)
+ {
+ if(flag.epoch==uninitialized_flag)
+ {
+ flag.epoch=being_initialized;
+ BOOST_TRY
+ {
+ pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T1>(p2)),
+ thread_detail::decay_copy(boost::forward<T1>(p3))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ flag.epoch=uninitialized_flag;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ flag.epoch=--thread_detail::once_global_epoch;
+ BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ }
+ else
+ {
+ while(flag.epoch==being_initialized)
+ {
+ BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ }
+ }
+ }
+ this_thread_epoch=thread_detail::once_global_epoch;
+ }
+ }
+
+#endif
+
}
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/pthread/once_atomic.hpp b/boost/thread/pthread/once_atomic.hpp
new file mode 100644
index 0000000000..923f07bd90
--- /dev/null
+++ b/boost/thread/pthread/once_atomic.hpp
@@ -0,0 +1,313 @@
+#ifndef BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP
+#define BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP
+
+// once.hpp
+//
+// (C) Copyright 2013 Andrey Semashev
+// (C) Copyright 2013 Vicente J. Botet Escriba
+//
+// 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/thread/detail/config.hpp>
+
+#include <boost/cstdint.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/detail/invoke.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/bind.hpp>
+#include <boost/atomic.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ struct once_flag;
+
+ namespace thread_detail
+ {
+
+#if BOOST_ATOMIC_INT_LOCK_FREE == 2
+ typedef unsigned int atomic_int_type;
+#elif BOOST_ATOMIC_SHORT_LOCK_FREE == 2
+ typedef unsigned short atomic_int_type;
+#elif BOOST_ATOMIC_CHAR_LOCK_FREE == 2
+ typedef unsigned char atomic_int_type;
+#elif BOOST_ATOMIC_LONG_LOCK_FREE == 2
+ typedef unsigned long atomic_int_type;
+#elif defined(BOOST_HAS_LONG_LONG) && BOOST_ATOMIC_LLONG_LOCK_FREE == 2
+ typedef ulong_long_type atomic_int_type;
+#else
+ // All tested integer types are not atomic, the spinlock pool will be used
+ typedef unsigned int atomic_int_type;
+#endif
+
+ typedef boost::atomic<atomic_int_type> atomic_type;
+
+ BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT;
+ BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT;
+ BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT;
+ inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT;
+ }
+
+#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
+
+ struct once_flag
+ {
+ BOOST_THREAD_NO_COPYABLE(once_flag)
+ BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT : storage(0)
+ {
+ }
+
+ private:
+ thread_detail::atomic_type storage;
+
+ friend BOOST_THREAD_DECL bool thread_detail::enter_once_region(once_flag& flag) BOOST_NOEXCEPT;
+ friend BOOST_THREAD_DECL void thread_detail::commit_once_region(once_flag& flag) BOOST_NOEXCEPT;
+ friend BOOST_THREAD_DECL void thread_detail::rollback_once_region(once_flag& flag) BOOST_NOEXCEPT;
+ friend thread_detail::atomic_type& thread_detail::get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT;
+ };
+
+#define BOOST_ONCE_INIT boost::once_flag()
+
+ namespace thread_detail
+ {
+ inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT
+ {
+ //return reinterpret_cast< atomic_type& >(flag.storage);
+ return flag.storage;
+ }
+ }
+
+#else // BOOST_THREAD_PROVIDES_ONCE_CXX11
+ struct once_flag
+ {
+ // The thread_detail::atomic_int_type storage is marked
+ // with this attribute in order to let the compiler know that it will alias this member
+ // and silence compilation warnings.
+ BOOST_THREAD_ATTRIBUTE_MAY_ALIAS thread_detail::atomic_int_type storage;
+ };
+
+ #define BOOST_ONCE_INIT {0}
+
+ namespace thread_detail
+ {
+ inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT
+ {
+ return reinterpret_cast< atomic_type& >(flag.storage);
+ }
+
+ }
+
+#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
+
+#if defined BOOST_THREAD_PROVIDES_INVOKE
+#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL
+#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET
+#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void>
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL
+#else
+#define BOOST_THREAD_INVOKE_RET_VOID boost::bind
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL ()
+#endif
+
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ template<typename Function, class ...ArgTypes>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args)
+ {
+ if (thread_detail::enter_once_region(flag))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ thread_detail::rollback_once_region(flag);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ thread_detail::commit_once_region(flag);
+ }
+ }
+#else
+ template<typename Function>
+ inline void call_once(once_flag& flag, Function f)
+ {
+ if (thread_detail::enter_once_region(flag))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH (...)
+ {
+ thread_detail::rollback_once_region(flag);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ thread_detail::commit_once_region(flag);
+ }
+ }
+
+ template<typename Function, typename T1>
+ inline void call_once(once_flag& flag, Function f, T1 p1)
+ {
+ if (thread_detail::enter_once_region(flag))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f, p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ thread_detail::rollback_once_region(flag);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ thread_detail::commit_once_region(flag);
+ }
+ }
+
+ template<typename Function, typename T1, typename T2>
+ inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2)
+ {
+ if (thread_detail::enter_once_region(flag))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ thread_detail::rollback_once_region(flag);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ thread_detail::commit_once_region(flag);
+ }
+ }
+
+ template<typename Function, typename T1, typename T2, typename T3>
+ inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3)
+ {
+ if (thread_detail::enter_once_region(flag))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ thread_detail::rollback_once_region(flag);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ thread_detail::commit_once_region(flag);
+ }
+ }
+
+ template<typename Function>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
+ {
+ if (thread_detail::enter_once_region(flag))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH (...)
+ {
+ thread_detail::rollback_once_region(flag);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ thread_detail::commit_once_region(flag);
+ }
+ }
+
+ template<typename Function, typename T1>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1)
+ {
+ if (thread_detail::enter_once_region(flag))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ thread_detail::rollback_once_region(flag);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ thread_detail::commit_once_region(flag);
+ }
+ }
+ template<typename Function, typename T1, typename T2>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
+ {
+ if (thread_detail::enter_once_region(flag))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T1>(p2))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH (...)
+ {
+ thread_detail::rollback_once_region(flag);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ thread_detail::commit_once_region(flag);
+ }
+ }
+ template<typename Function, typename T1, typename T2, typename T3>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3)
+ {
+ if (thread_detail::enter_once_region(flag))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T1>(p2)),
+ thread_detail::decay_copy(boost::forward<T1>(p3))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+
+ }
+ BOOST_CATCH (...)
+ {
+ thread_detail::rollback_once_region(flag);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ thread_detail::commit_once_region(flag);
+ }
+ }
+
+
+
+#endif
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
+
diff --git a/boost/thread/pthread/recursive_mutex.hpp b/boost/thread/pthread/recursive_mutex.hpp
index 22acf41fa2..9330d77de9 100644
--- a/boost/thread/pthread/recursive_mutex.hpp
+++ b/boost/thread/pthread/recursive_mutex.hpp
@@ -9,7 +9,9 @@
#include <pthread.h>
#include <boost/throw_exception.hpp>
#include <boost/thread/exceptions.hpp>
-#include <boost/thread/locks.hpp>
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+#include <boost/thread/lock_types.hpp>
+#endif
#include <boost/thread/thread_time.hpp>
#include <boost/assert.hpp>
#ifndef _WIN32
@@ -26,10 +28,13 @@
#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
-#if _POSIX_TIMEOUTS >= 0
+#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
+#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
+#endif
+
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
@@ -110,7 +115,7 @@ namespace boost
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
- bool try_lock()
+ bool try_lock() BOOST_NOEXCEPT
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
@@ -167,8 +172,10 @@ namespace boost
#endif
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
typedef unique_lock<recursive_mutex> scoped_lock;
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
+#endif
};
typedef recursive_mutex recursive_try_mutex;
@@ -232,11 +239,13 @@ namespace boost
#endif
}
+#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
+#endif
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
void lock()
@@ -294,7 +303,7 @@ namespace boost
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
- bool try_lock()
+ bool try_lock() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && !pthread_equal(owner,pthread_self()))
@@ -334,12 +343,13 @@ namespace boost
#endif
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(system_time const & abs_time)
{
- struct timespec const ts=detail::get_timespec(abs_time);
+ struct timespec const ts=detail::to_timespec(abs_time);
return do_try_lock_until(ts);
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
@@ -363,12 +373,9 @@ namespace boost
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
- using namespace chrono;
- nanoseconds d = tp.time_since_epoch();
- timespec ts;
- seconds s = duration_cast<seconds>(d);
- ts.tv_sec = static_cast<long>(s.count());
- ts.tv_nsec = static_cast<long>((d - s).count());
+ //using namespace chrono;
+ chrono::nanoseconds d = tp.time_since_epoch();
+ timespec ts = boost::detail::to_timespec(d);
return do_try_lock_until(ts);
}
#endif
@@ -380,9 +387,11 @@ namespace boost
return &m;
}
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
+#endif
};
}
diff --git a/boost/thread/pthread/shared_mutex.hpp b/boost/thread/pthread/shared_mutex.hpp
index cf45188606..458d6c8361 100644
--- a/boost/thread/pthread/shared_mutex.hpp
+++ b/boost/thread/pthread/shared_mutex.hpp
@@ -12,12 +12,15 @@
#include <boost/static_assert.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
#include <boost/thread/detail/thread_interruption.hpp>
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
+#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -26,8 +29,125 @@ namespace boost
class shared_mutex
{
private:
- struct state_data
+ class state_data
{
+ public:
+ state_data () :
+ shared_count(0),
+ exclusive(false),
+ upgrade(false),
+ exclusive_waiting_blocked(false)
+ {}
+
+ void assert_free() const
+ {
+ BOOST_ASSERT( ! exclusive );
+ BOOST_ASSERT( ! upgrade );
+ BOOST_ASSERT( shared_count==0 );
+ }
+
+ void assert_locked() const
+ {
+ BOOST_ASSERT( exclusive );
+ BOOST_ASSERT( shared_count==0 );
+ BOOST_ASSERT( ! upgrade );
+ }
+
+ void assert_lock_shared () const
+ {
+ BOOST_ASSERT( ! exclusive );
+ BOOST_ASSERT( shared_count>0 );
+ //BOOST_ASSERT( (! upgrade) || (shared_count>1));
+ // if upgraded there are at least 2 threads sharing the mutex,
+ // except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership.
+ }
+
+ void assert_lock_upgraded () const
+ {
+ BOOST_ASSERT( ! exclusive );
+ BOOST_ASSERT( upgrade );
+ BOOST_ASSERT( shared_count>0 );
+ }
+
+ void assert_lock_not_upgraded () const
+ {
+ BOOST_ASSERT( ! upgrade );
+ }
+
+ bool can_lock () const
+ {
+ return ! (shared_count || exclusive);
+ }
+
+ void exclusive_blocked (bool blocked)
+ {
+ exclusive_waiting_blocked = blocked;
+ }
+
+ void lock ()
+ {
+ exclusive = true;
+ }
+
+ void unlock ()
+ {
+ exclusive = false;
+ exclusive_waiting_blocked = false;
+ }
+
+ bool can_lock_shared () const
+ {
+ return ! (exclusive || exclusive_waiting_blocked);
+ }
+
+ bool more_shared () const
+ {
+ return shared_count > 0 ;
+ }
+ unsigned get_shared_count () const
+ {
+ return shared_count ;
+ }
+ unsigned lock_shared ()
+ {
+ return ++shared_count;
+ }
+
+
+ void unlock_shared ()
+ {
+ --shared_count;
+ }
+
+ bool unlock_shared_downgrades()
+ {
+ if (upgrade) {
+ upgrade=false;
+ exclusive=true;
+ return true;
+ } else {
+ exclusive_waiting_blocked=false;
+ return false;
+ }
+ }
+
+ void lock_upgrade ()
+ {
+ ++shared_count;
+ upgrade=true;
+ }
+ bool can_lock_upgrade () const
+ {
+ return ! (exclusive || exclusive_waiting_blocked || upgrade);
+ }
+
+ void unlock_upgrade ()
+ {
+ upgrade=false;
+ --shared_count;
+ }
+
+ //private:
unsigned shared_count;
bool exclusive;
bool upgrade;
@@ -49,12 +169,11 @@ namespace boost
}
public:
+
BOOST_THREAD_NO_COPYABLE(shared_mutex)
shared_mutex()
{
- state_data state_={0,0,0,0};
- state=state_;
}
~shared_mutex()
@@ -63,44 +182,45 @@ namespace boost
void lock_shared()
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
-
- while(state.exclusive || state.exclusive_waiting_blocked)
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ while(!state.can_lock_shared())
{
shared_cond.wait(lk);
}
- ++state.shared_count;
+ state.lock_shared();
}
bool try_lock_shared()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
- if(state.exclusive || state.exclusive_waiting_blocked)
+ if(!state.can_lock_shared())
{
return false;
}
- else
- {
- ++state.shared_count;
- return true;
- }
+ state.lock_shared();
+ return true;
}
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock_shared(system_time const& timeout)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
- while(state.exclusive || state.exclusive_waiting_blocked)
+ while(!state.can_lock_shared())
{
if(!shared_cond.timed_wait(lk,timeout))
{
return false;
}
}
- ++state.shared_count;
+ state.lock_shared();
return true;
}
@@ -109,6 +229,7 @@ namespace boost
{
return timed_lock_shared(get_system_time()+relative_time);
}
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
@@ -118,36 +239,43 @@ namespace boost
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
- while(state.exclusive || state.exclusive_waiting_blocked)
+ while(!state.can_lock_shared())
+ //while(state.exclusive || state.exclusive_waiting_blocked)
{
if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
{
return false;
}
}
- ++state.shared_count;
+ state.lock_shared();
return true;
}
#endif
void unlock_shared()
{
- boost::mutex::scoped_lock lk(state_change);
- bool const last_reader=!--state.shared_count;
-
- if(last_reader)
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
+ state.unlock_shared();
+ if (! state.more_shared())
{
- if(state.upgrade)
+ if (state.upgrade)
{
+ // As there is a thread doing a unlock_upgrade_and_lock that is waiting for ! state.more_shared()
+ // avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified.
state.upgrade=false;
state.exclusive=true;
+ lk.unlock();
upgrade_cond.notify_one();
}
else
{
state.exclusive_waiting_blocked=false;
+ lk.unlock();
}
release_waiters();
}
@@ -155,10 +283,12 @@ namespace boost
void lock()
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
- while(state.shared_count || state.exclusive)
+ while (state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
exclusive_cond.wait(lk);
@@ -166,10 +296,13 @@ namespace boost
state.exclusive=true;
}
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(system_time const& timeout)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
while(state.shared_count || state.exclusive)
{
@@ -194,7 +327,7 @@ namespace boost
{
return timed_lock(get_system_time()+relative_time);
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
@@ -204,8 +337,10 @@ namespace boost
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
while(state.shared_count || state.exclusive)
{
@@ -228,7 +363,7 @@ namespace boost
bool try_lock()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
if(state.shared_count || state.exclusive)
{
@@ -244,28 +379,35 @@ namespace boost
void unlock()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_locked();
state.exclusive=false;
state.exclusive_waiting_blocked=false;
+ state.assert_free();
release_waiters();
}
void lock_upgrade()
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
shared_cond.wait(lk);
}
- ++state.shared_count;
+ state.lock_shared();
state.upgrade=true;
}
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock_upgrade(system_time const& timeout)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
if(!shared_cond.timed_wait(lk,timeout))
@@ -277,7 +419,7 @@ namespace boost
break;
}
}
- ++state.shared_count;
+ state.lock_shared();
state.upgrade=true;
return true;
}
@@ -287,7 +429,7 @@ namespace boost
{
return timed_lock_upgrade(get_system_time()+relative_time);
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
@@ -297,8 +439,10 @@ namespace boost
template <class Clock, class Duration>
bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
@@ -310,68 +454,75 @@ namespace boost
break;
}
}
- ++state.shared_count;
+ state.lock_shared();
state.upgrade=true;
return true;
}
#endif
bool try_lock_upgrade()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
else
{
- ++state.shared_count;
+ state.lock_shared();
state.upgrade=true;
+ state.assert_lock_upgraded();
return true;
}
}
void unlock_upgrade()
{
- boost::mutex::scoped_lock lk(state_change);
- state.upgrade=false;
- bool const last_reader=!--state.shared_count;
-
- if(last_reader)
+ boost::unique_lock<boost::mutex> lk(state_change);
+ //state.upgrade=false;
+ state.unlock_upgrade();
+ if(! state.more_shared() )
{
state.exclusive_waiting_blocked=false;
release_waiters();
} else {
- shared_cond.notify_all();
+ shared_cond.notify_all();
}
}
// Upgrade <-> Exclusive
void unlock_upgrade_and_lock()
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
- --state.shared_count;
- while(state.shared_count)
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
+ state.unlock_shared();
+ while (state.more_shared())
{
upgrade_cond.wait(lk);
}
state.upgrade=false;
state.exclusive=true;
+ state.assert_locked();
}
void unlock_and_lock_upgrade()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_locked();
state.exclusive=false;
state.upgrade=true;
- ++state.shared_count;
+ state.lock_shared();
state.exclusive_waiting_blocked=false;
+ state.assert_lock_upgraded();
release_waiters();
}
bool try_unlock_upgrade_and_lock()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& state.upgrade
@@ -380,6 +531,7 @@ namespace boost
state.shared_count=0;
state.exclusive=true;
state.upgrade=false;
+ state.assert_locked();
return true;
}
return false;
@@ -398,8 +550,11 @@ namespace boost
try_unlock_upgrade_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
if (state.shared_count != 1)
{
for (;;)
@@ -422,9 +577,10 @@ namespace boost
// Shared <-> Exclusive
void unlock_and_lock_shared()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_locked();
state.exclusive=false;
- ++state.shared_count;
+ state.lock_shared();
state.exclusive_waiting_blocked=false;
release_waiters();
}
@@ -432,7 +588,8 @@ namespace boost
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
@@ -458,8 +615,11 @@ namespace boost
try_unlock_shared_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
if (state.shared_count != 1)
{
for (;;)
@@ -483,7 +643,8 @@ namespace boost
// Shared <-> Upgrade
void unlock_upgrade_and_lock_shared()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
state.upgrade=false;
state.exclusive_waiting_blocked=false;
release_waiters();
@@ -492,7 +653,8 @@ namespace boost
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock_upgrade()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
@@ -517,8 +679,11 @@ namespace boost
try_unlock_shared_and_lock_upgrade_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
if( state.exclusive
|| state.exclusive_waiting_blocked
|| state.upgrade
diff --git a/boost/thread/pthread/shared_mutex_assert.hpp b/boost/thread/pthread/shared_mutex_assert.hpp
new file mode 100644
index 0000000000..186ab7984b
--- /dev/null
+++ b/boost/thread/pthread/shared_mutex_assert.hpp
@@ -0,0 +1,724 @@
+#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
+#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
+
+// (C) Copyright 2006-8 Anthony Williams
+// (C) Copyright 2012 Vicente J. Botet Escriba
+//
+// 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/assert.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+#include <boost/thread/detail/thread_interruption.hpp>
+#endif
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
+#include <boost/thread/detail/delete.hpp>
+#include <boost/assert.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ class shared_mutex
+ {
+ private:
+ class state_data
+ {
+ public:
+ state_data () :
+ shared_count(0),
+ exclusive(false),
+ upgrade(false),
+ exclusive_waiting_blocked(false)
+ {}
+
+ void assert_free() const
+ {
+ BOOST_ASSERT( ! exclusive );
+ BOOST_ASSERT( ! upgrade );
+ BOOST_ASSERT( shared_count==0 );
+ }
+
+ void assert_locked() const
+ {
+ BOOST_ASSERT( exclusive );
+ BOOST_ASSERT( shared_count==0 );
+ BOOST_ASSERT( ! upgrade );
+ }
+
+ void assert_lock_shared () const
+ {
+ BOOST_ASSERT( ! exclusive );
+ BOOST_ASSERT( shared_count>0 );
+ //BOOST_ASSERT( (! upgrade) || (shared_count>1));
+ // if upgraded there are at least 2 threads sharing the mutex,
+ // except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership.
+ }
+
+ void assert_lock_upgraded () const
+ {
+ BOOST_ASSERT( ! exclusive );
+ BOOST_ASSERT( upgrade );
+ BOOST_ASSERT( shared_count>0 );
+ }
+
+ void assert_lock_not_upgraded () const
+ {
+ BOOST_ASSERT( ! upgrade );
+ }
+
+ bool can_lock () const
+ {
+ return ! (shared_count || exclusive);
+ }
+
+ void exclusive_blocked (bool blocked)
+ {
+ exclusive_waiting_blocked = blocked;
+ }
+
+ void lock ()
+ {
+ exclusive = true;
+ }
+
+ void unlock ()
+ {
+ exclusive = false;
+ exclusive_waiting_blocked = false;
+ }
+
+ bool can_lock_shared () const
+ {
+ return ! (exclusive || exclusive_waiting_blocked);
+ }
+
+ bool is_last_shared () const
+ {
+ return !shared_count ;
+ }
+ unsigned get_shared_count () const
+ {
+ return shared_count ;
+ }
+ unsigned lock_shared ()
+ {
+ return ++shared_count;
+ }
+
+
+ void unlock_shared ()
+ {
+ --shared_count;
+ }
+
+ bool unlock_shared_downgrades()
+ {
+ if (upgrade) {
+ upgrade=false;
+ exclusive=true;
+ return true;
+ } else {
+ exclusive_waiting_blocked=false;
+ return false;
+ }
+ }
+
+ void lock_upgrade ()
+ {
+ lock_shared ();
+ upgrade=true;
+ }
+ bool can_lock_upgrade () const
+ {
+ return ! (exclusive || exclusive_waiting_blocked || upgrade);
+ }
+
+ void unlock_upgrade ()
+ {
+ upgrade=false;
+ unlock_shared();
+ }
+
+ //private:
+ unsigned shared_count;
+ bool exclusive;
+ bool upgrade;
+ bool exclusive_waiting_blocked;
+ };
+
+
+
+ state_data state;
+ boost::mutex state_change;
+ boost::condition_variable shared_cond;
+ boost::condition_variable exclusive_cond;
+ boost::condition_variable upgrade_cond;
+
+ void release_waiters()
+ {
+ exclusive_cond.notify_one();
+ shared_cond.notify_all();
+ }
+
+ public:
+ BOOST_THREAD_NO_COPYABLE(shared_mutex)
+
+ shared_mutex()
+ {
+ }
+
+ ~shared_mutex()
+ {
+ }
+
+ void lock_shared()
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+
+ while(!state.can_lock_shared())
+ {
+ shared_cond.wait(lk);
+ }
+ state.lock_shared();
+ }
+
+ bool try_lock_shared()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ if(!state.can_lock_shared())
+ {
+ return false;
+ }
+ else
+ {
+ state.lock_shared();
+ return true;
+ }
+ }
+
+#if defined BOOST_THREAD_USES_DATETIME
+ bool timed_lock_shared(system_time const& timeout)
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+
+ while(!state.can_lock_shared())
+ {
+ if(!shared_cond.timed_wait(lk,timeout))
+ {
+ return false;
+ }
+ }
+ state.lock_shared();
+ return true;
+ }
+
+ template<typename TimeDuration>
+ bool timed_lock_shared(TimeDuration const & relative_time)
+ {
+ return timed_lock_shared(get_system_time()+relative_time);
+ }
+#endif
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+
+ while(!state.can_lock_shared())
+ {
+ if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
+ {
+ return false;
+ }
+ }
+ state.lock_shared();
+ return true;
+ }
+#endif
+ void unlock_shared()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
+ state.unlock_shared();
+ if (state.get_shared_count () == 0)
+ {
+ if (state.unlock_shared_downgrades())
+ {
+ lk.unlock();
+ upgrade_cond.notify_one();
+ } else {
+ lk.unlock();
+ }
+ release_waiters();
+ }
+ }
+
+ void lock()
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+
+ while(!state.can_lock())
+ {
+ state.exclusive_blocked(true);
+ exclusive_cond.wait(lk);
+ }
+ state.lock();
+ }
+
+#if defined BOOST_THREAD_USES_DATETIME
+ bool timed_lock(system_time const& timeout)
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+
+ while(!state.can_lock())
+ {
+ state.exclusive_blocked(true);
+ if(!exclusive_cond.timed_wait(lk,timeout))
+ {
+ if(!state.can_lock())
+ {
+ state.exclusive_blocked(false);
+ release_waiters();
+ return false;
+ }
+ break;
+ }
+ }
+ state.exclusive=true;
+ //state.lock();
+ return true;
+ }
+
+ template<typename TimeDuration>
+ bool timed_lock(TimeDuration const & relative_time)
+ {
+ return timed_lock(get_system_time()+relative_time);
+ }
+#endif
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_lock_until(chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+
+ while(!state.can_lock())
+ {
+ state.exclusive_blocked(true);
+ if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time))
+ {
+ if(!state.can_lock())
+ {
+ state.exclusive_blocked(false);
+ release_waiters();
+ return false;
+ }
+ break;
+ }
+ }
+ state.exclusive=true;
+ //state.lock();
+ return true;
+ }
+#endif
+
+ bool try_lock()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+
+ if(!state.can_lock())
+ {
+ return false;
+ }
+ else
+ {
+ state.lock();
+ return true;
+ }
+
+ }
+
+ void unlock()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_locked();
+ state.unlock();
+ state.assert_free();
+ release_waiters();
+ }
+
+ void lock_upgrade()
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ while(!state.can_lock_upgrade())
+ {
+ shared_cond.wait(lk);
+ }
+ state.lock_upgrade();
+ }
+
+#if defined BOOST_THREAD_USES_DATETIME
+ bool timed_lock_upgrade(system_time const& timeout)
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ while(!state.can_lock_upgrade())
+ {
+ if(!shared_cond.timed_wait(lk,timeout))
+ {
+ if(!state.can_lock_upgrade())
+ {
+ return false;
+ }
+ break;
+ }
+ }
+ state.lock_upgrade();
+ return true;
+ }
+
+ template<typename TimeDuration>
+ bool timed_lock_upgrade(TimeDuration const & relative_time)
+ {
+ return timed_lock_upgrade(get_system_time()+relative_time);
+ }
+#endif
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ while(!state.can_lock_upgrade())
+ {
+ if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
+ {
+ if(!state.can_lock_upgrade())
+ {
+ return false;
+ }
+ break;
+ }
+ }
+ state.lock_upgrade();
+ return true;
+ }
+#endif
+ bool try_lock_upgrade()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ if(!state.can_lock_upgrade())
+ {
+ return false;
+ }
+ else
+ {
+ state.lock_upgrade();
+ state.assert_lock_upgraded();
+ return true;
+ }
+ }
+
+ void unlock_upgrade()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
+ state.unlock_upgrade();
+ state.assert_lock_not_upgraded ();
+ if(state.get_shared_count () == 0)
+ {
+ state.exclusive_blocked(false);
+ lk.unlock();
+ release_waiters();
+ } else {
+ lk.unlock();
+ shared_cond.notify_all();
+ }
+ }
+
+ // Upgrade <-> Exclusive
+ void unlock_upgrade_and_lock()
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
+ // assert state.get_shared_count() >=1
+ while(
+ //! state.exclusive_waiting_blocked // Fixme: is this needed?
+ //&&
+ state.get_shared_count()!=1)
+ {
+ upgrade_cond.wait(lk);
+ }
+ state.unlock_upgrade();
+ state.lock();
+ state.assert_locked();
+ }
+
+ void unlock_and_lock_upgrade()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_locked();
+ state.unlock();
+ state.lock_upgrade();
+ state.assert_lock_upgraded();
+ release_waiters();
+ }
+
+ bool try_unlock_upgrade_and_lock()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
+ if( //!state.exclusive // this should be removed once the assertion work
+ ! state.exclusive_waiting_blocked // Fixme: why this is needed?
+ //&& state.upgrade // this should be removed once the assertion work
+ && state.get_shared_count()==1)
+ {
+ state.unlock_upgrade();
+ state.lock();
+ state.assert_locked();
+ return true;
+ }
+ return false;
+ }
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool
+ try_unlock_upgrade_and_lock_for(
+ const chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_unlock_upgrade_and_lock_until(
+ chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_unlock_upgrade_and_lock_until(
+ const chrono::time_point<Clock, Duration>& abs_time)
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
+ if (//state.exclusive // this should be removed once the assertion work
+ state.exclusive_waiting_blocked // Fixme: is this needed?
+ //|| ! state.upgrade // this should be removed once the assertion work
+ || state.get_shared_count() != 1)
+ {
+ for (;;)
+ {
+ //cv_status status = shared_cond.wait_until(lk,abs_time);
+ cv_status status = upgrade_cond.wait_until(lk,abs_time);
+ if (//!state.exclusive // this should be removed once the assertion work
+ ! state.exclusive_waiting_blocked // Fixme: is this needed?
+ //&& ! state.upgrade // this should be removed once the assertion work
+ && state.get_shared_count() == 1)
+ break;
+ if(status == cv_status::timeout)
+ return false;
+ }
+ }
+ state.unlock_upgrade();
+ state.lock();
+ return true;
+ }
+#endif
+
+ // Shared <-> Exclusive
+ void unlock_and_lock_shared()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_locked();
+ state.unlock();
+ state.lock_shared();
+ release_waiters();
+ }
+
+#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ bool try_unlock_shared_and_lock()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
+ if( //!state.exclusive // this should be removed once the assertion work
+ ! state.exclusive_waiting_blocked // Fixme: why this is needed?
+ //&& ! state.upgrade // Fixme: why this is needed if state.get_shared_count()==1?
+ && state.get_shared_count()==1)
+ {
+ state.unlock_shared();
+ state.lock();
+ return true;
+ }
+ return false;
+ }
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool
+ try_unlock_shared_and_lock_for(
+ const chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_unlock_shared_and_lock_until(
+ chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_unlock_shared_and_lock_until(
+ const chrono::time_point<Clock, Duration>& abs_time)
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
+ if ( // !state.exclusive // this should be removed once the assertion work
+ state.exclusive_waiting_blocked // Fixme: is this needed?
+ //|| state.upgrade // Fixme: why this is needed if state.get_shared_count()==1?
+ || state.get_shared_count() != 1)
+ {
+ for (;;)
+ {
+ cv_status status = shared_cond.wait_until(lk,abs_time);
+ if ( //! state.exclusive // this should be removed once the assertion work
+ ! state.exclusive_waiting_blocked // Fixme: is this needed?
+ //&& ! state.upgrade
+ && state.get_shared_count() == 1)
+ break;
+ if(status == cv_status::timeout)
+ return false;
+ }
+ }
+ state.unlock_shared();
+ state.lock();
+ state.upgrade=false; // Is this absolutely needed?
+ state.exclusive_waiting_blocked=false; // Is this absolutely needed?
+ return true;
+ }
+#endif
+#endif
+
+ // Shared <-> Upgrade
+ void unlock_upgrade_and_lock_shared()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
+ //state.unlock_upgrade();
+ //state.lock_shared(); // less efficient
+ state.upgrade=false;
+ state.exclusive_waiting_blocked=false; // Is this absolutely needed?
+ release_waiters();
+ }
+
+#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ bool try_unlock_shared_and_lock_upgrade()
+ {
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
+ if( //! state.exclusive // this should be removed once the assertion work
+ ! state.exclusive_waiting_blocked // Fixme: is this needed?
+ && ! state.upgrade
+ )
+ {
+ state.upgrade=true;
+ return true;
+ }
+ return false;
+ }
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool
+ try_unlock_shared_and_lock_upgrade_for(
+ const chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_unlock_shared_and_lock_upgrade_until(
+ chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_unlock_shared_and_lock_upgrade_until(
+ const chrono::time_point<Clock, Duration>& abs_time)
+ {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ boost::this_thread::disable_interruption do_not_disturb;
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
+ if( //state.exclusive // this should be removed once the assertion work
+ state.exclusive_waiting_blocked // Fixme: is this needed?
+ || state.upgrade
+ )
+ {
+ for (;;)
+ {
+ cv_status status = exclusive_cond.wait_until(lk,abs_time);
+ if( //! state.exclusive // this should be removed once the assertion work
+ ! state.exclusive_waiting_blocked // Fixme: is this needed?
+ && ! state.upgrade
+ )
+ break;
+ if(status == cv_status::timeout)
+ return false;
+ }
+ }
+ //state.unlock_shared();
+ //state.lock_upgrade(); // less efficient
+ state.upgrade=true;
+ return true;
+ }
+#endif
+#endif
+ };
+
+ typedef shared_mutex upgrade_mutex;
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/pthread/thread_data.hpp b/boost/thread/pthread/thread_data.hpp
index 5f84799f85..801f470b46 100644
--- a/boost/thread/pthread/thread_data.hpp
+++ b/boost/thread/pthread/thread_data.hpp
@@ -8,18 +8,29 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
+#include <boost/thread/lock_guard.hpp>
+#include <boost/thread/lock_types.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/pthread/condition_variable_fwd.hpp>
+
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/optional.hpp>
-#include <pthread.h>
#include <boost/assert.hpp>
-#include <boost/thread/pthread/condition_variable_fwd.hpp>
-#include <map>
-#include <unistd.h>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#endif
+
+#include <map>
+#include <vector>
+#include <utility>
+
+#if defined(__ANDROID__)
+#include <asm/page.h> // http://code.google.com/p/android/issues/detail?id=39983
+#endif
+
+#include <pthread.h>
+#include <unistd.h>
+
#include <boost/config/abi_prefix.hpp>
namespace boost
@@ -70,6 +81,7 @@ namespace boost
namespace detail
{
+ struct shared_state_base;
struct tss_cleanup_function;
struct thread_exit_callback_node;
struct tss_data_node
@@ -100,27 +112,57 @@ namespace boost
bool joined;
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
std::map<void const*,boost::detail::tss_data_node> tss_data;
- bool interrupt_enabled;
- bool interrupt_requested;
+
pthread_mutex_t* cond_mutex;
pthread_cond_t* current_cond;
+ typedef std::vector<std::pair<condition_variable*, mutex*>
+ //, hidden_allocator<std::pair<condition_variable*, mutex*> >
+ > notify_list_t;
+ notify_list_t notify;
+ typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
+ async_states_t async_states_;
+
+//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ // These data must be at the end so that the access to the other fields doesn't change
+ // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined.
+ // Another option is to have them always
+ bool interrupt_enabled;
+ bool interrupt_requested;
+//#endif
thread_data_base():
+ thread_handle(0),
done(false),join_started(false),joined(false),
thread_exit_callbacks(0),
- interrupt_enabled(true),
- interrupt_requested(false),
- current_cond(0)
+ cond_mutex(0),
+ current_cond(0),
+ notify(),
+ async_states_()
+//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ , interrupt_enabled(true)
+ , interrupt_requested(false)
+//#endif
{}
virtual ~thread_data_base();
typedef pthread_t native_handle_type;
virtual void run()=0;
+ virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
+ {
+ notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
+ }
+
+ void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
+ {
+ async_states_.push_back(as);
+ }
+
};
BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
class interruption_checker
{
thread_data_base* const thread_info;
@@ -172,35 +214,68 @@ namespace boost
}
}
};
+#endif
}
namespace this_thread
{
+ namespace hiden
+ {
+ void BOOST_THREAD_DECL sleep_for(const timespec& ts);
+ void BOOST_THREAD_DECL sleep_until(const timespec& ts);
+ }
+
#ifdef BOOST_THREAD_USES_CHRONO
- void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns);
+#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
+
+ inline
+ void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
+ {
+ return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns));
+ }
#endif
+#endif // BOOST_THREAD_USES_CHRONO
+
+ namespace no_interruption_point
+ {
+ namespace hiden
+ {
+ void BOOST_THREAD_DECL sleep_for(const timespec& ts);
+ void BOOST_THREAD_DECL sleep_until(const timespec& ts);
+ }
+
+ #ifdef BOOST_THREAD_USES_CHRONO
+ #ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
+
+ inline
+ void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
+ {
+ return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns));
+ }
+ #endif
+ #endif // BOOST_THREAD_USES_CHRONO
+
+ } // no_interruption_point
+
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
+#if defined BOOST_THREAD_USES_DATETIME
#ifdef __DECXXX
/// Workaround of DECCXX issue of incorrect template substitution
- template<typename TimeDuration>
- inline void sleep(TimeDuration const& rel_time)
+ template<>
+#endif
+ inline void sleep(system_time const& abs_time)
{
- this_thread::sleep(get_system_time()+rel_time);
+ return boost::this_thread::hiden::sleep_until(boost::detail::to_timespec(abs_time));
}
- template<>
- void BOOST_THREAD_DECL sleep(system_time const& abs_time);
-#else
- void BOOST_THREAD_DECL sleep(system_time const& abs_time);
-
template<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
this_thread::sleep(get_system_time()+rel_time);
}
-#endif
- }
+#endif // BOOST_THREAD_USES_DATETIME
+ } // this_thread
}
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/pthread/thread_heap_alloc.hpp b/boost/thread/pthread/thread_heap_alloc.hpp
index 737c29858b..7828318f05 100644
--- a/boost/thread/pthread/thread_heap_alloc.hpp
+++ b/boost/thread/pthread/thread_heap_alloc.hpp
@@ -17,7 +17,7 @@ namespace boost
return new T();
}
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
@@ -72,7 +72,7 @@ namespace boost
{
return heap_new_impl<T,A1&>(a1);
}
-
+
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2 const& a2)
{
@@ -218,8 +218,8 @@ namespace boost
{
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
-
-#endif
+
+#endif
template<typename T>
inline void heap_delete(T* data)
{
diff --git a/boost/thread/pthread/timespec.hpp b/boost/thread/pthread/timespec.hpp
index d7465c1ac3..82f50f6ca7 100644
--- a/boost/thread/pthread/timespec.hpp
+++ b/boost/thread/pthread/timespec.hpp
@@ -1,34 +1,118 @@
#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP
#define BOOST_THREAD_PTHREAD_TIMESPEC_HPP
-// (C) Copyright 2007-8 Anthony Williams
+// (C) Copyright 2007-8 Anthony Williams
+// (C) Copyright 2012 Vicente J. Botet Escriba
//
// 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/thread/detail/config.hpp>
#include <boost/thread/thread_time.hpp>
+#if defined BOOST_THREAD_USES_DATETIME
#include <boost/date_time/posix_time/conversion.hpp>
+#endif
#include <pthread.h>
#ifndef _WIN32
#include <unistd.h>
#endif
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/duration.hpp>
+#endif
+
+#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+# define BOOST_THREAD_TIMESPEC_MAC_API
+#include <sys/time.h> //for gettimeofday and timeval
+#else
+#include <time.h> // for clock_gettime
+#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
- namespace detail
- {
- inline struct timespec get_timespec(boost::system_time const& abs_time)
- {
- struct timespec timeout={0,0};
- boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
-
- timeout.tv_sec=time_since_epoch.total_seconds();
- timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second()));
- return timeout;
- }
+ namespace detail
+ {
+#if defined BOOST_THREAD_USES_DATETIME
+ inline struct timespec to_timespec(boost::system_time const& abs_time)
+ {
+ struct timespec timeout = { 0,0};
+ boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
+
+ timeout.tv_sec=time_since_epoch.total_seconds();
+ timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second()));
+ return timeout;
+ }
+#endif
+#if defined BOOST_THREAD_USES_CHRONO
+ inline timespec to_timespec(chrono::nanoseconds const& ns)
+ {
+ struct timespec ts;
+ 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 ts;
}
+
+#endif
+
+ inline timespec to_timespec(boost::intmax_t const& ns)
+ {
+ boost::intmax_t s = ns / 1000000000l;
+ struct timespec ts;
+ ts.tv_sec = static_cast<long> (s);
+ ts.tv_nsec = static_cast<long> (ns - s * 1000000000l);
+ return ts;
+ }
+ inline boost::intmax_t to_nanoseconds_int_max(timespec const& ts)
+ {
+ return static_cast<boost::intmax_t>(ts.tv_sec) * 1000000000l + ts.tv_nsec;
+ }
+ inline bool timespec_ge_zero(timespec const& ts)
+ {
+ return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0);
+ }
+ inline timespec timespec_now()
+ {
+ timespec ts;
+
+#if 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 ) )
+ {
+ BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
+ }
+#endif
+ return ts;
+ }
+ inline timespec timespec_zero()
+ {
+ timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ return ts;
+ }
+ inline timespec timespec_plus(timespec const& lhs, timespec const& rhs)
+ {
+ return to_timespec(to_nanoseconds_int_max(lhs) + to_nanoseconds_int_max(rhs));
+ }
+ inline timespec timespec_minus(timespec const& lhs, timespec const& rhs)
+ {
+ return to_timespec(to_nanoseconds_int_max(lhs) - to_nanoseconds_int_max(rhs));
+ }
+ inline bool timespec_gt(timespec const& lhs, timespec const& rhs)
+ {
+ return to_nanoseconds_int_max(lhs) > to_nanoseconds_int_max(rhs);
+ }
+ inline bool timespec_ge(timespec const& lhs, timespec const& rhs)
+ {
+ return to_nanoseconds_int_max(lhs) >= to_nanoseconds_int_max(rhs);
+ }
+
+ }
}
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/recursive_mutex.hpp b/boost/thread/recursive_mutex.hpp
index d5f6116e72..e716a190ff 100644
--- a/boost/thread/recursive_mutex.hpp
+++ b/boost/thread/recursive_mutex.hpp
@@ -3,7 +3,7 @@
// recursive_mutex.hpp
//
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -18,4 +18,47 @@
#error "Boost threads unavailable on this platform"
#endif
+#include <boost/thread/lockable_traits.hpp>
+
+namespace boost
+{
+ namespace sync
+ {
+
+#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
+ template<>
+ struct is_basic_lockable<recursive_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<>
+ struct is_lockable<recursive_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<>
+ struct is_basic_lockable<recursive_timed_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<>
+ struct is_lockable<recursive_timed_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+#endif
+
+ template<>
+ struct is_recursive_mutex_sur_parolle<recursive_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<>
+ struct is_recursive_mutex_sur_parolle<recursive_timed_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+
+ }
+}
#endif
diff --git a/boost/thread/reverse_lock.hpp b/boost/thread/reverse_lock.hpp
index c196cde072..479c314bdb 100644
--- a/boost/thread/reverse_lock.hpp
+++ b/boost/thread/reverse_lock.hpp
@@ -6,7 +6,9 @@
#ifndef BOOST_THREAD_REVERSE_LOCK_HPP
#define BOOST_THREAD_REVERSE_LOCK_HPP
#include <boost/thread/detail/config.hpp>
-#include <boost/thread/locks.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/lockable_traits.hpp>
+#include <boost/thread/lock_options.hpp>
#include <boost/thread/detail/delete.hpp>
namespace boost
@@ -15,7 +17,6 @@ namespace boost
template<typename Lock>
class reverse_lock
{
-
public:
typedef typename Lock::mutex_type mutex_type;
BOOST_THREAD_NO_COPYABLE(reverse_lock)
diff --git a/boost/thread/scoped_thread.hpp b/boost/thread/scoped_thread.hpp
new file mode 100644
index 0000000000..ae0d1efc53
--- /dev/null
+++ b/boost/thread/scoped_thread.hpp
@@ -0,0 +1,289 @@
+// 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)
+// (C) Copyright 2009-2012 Anthony Williams
+// (C) Copyright 2012 Vicente J. Botet Escriba
+
+// Based on the Anthony's idea of scoped_thread in CCiA
+
+#ifndef BOOST_THREAD_SCOPED_THREAD_HPP
+#define BOOST_THREAD_SCOPED_THREAD_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/thread_functors.hpp>
+#include <boost/thread/thread_only.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ /**
+ * RAI @c thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
+ *
+ * CallableThread: A callable void(thread&) .
+ * The default is a join_if_joinable.
+ *
+ * thread std/boost::thread destructor terminates the program if the thread is not joinable.
+ * Having a wrapper that can join the thread before destroying it seems a natural need.
+ *
+ * Example:
+ *
+ * boost::strict_scoped_thread<> t((boost::thread(F)));
+ *
+ */
+ template <class CallableThread = join_if_joinable>
+ class strict_scoped_thread
+ {
+ thread t_;
+ struct dummy;
+ public:
+
+ BOOST_THREAD_NO_COPYABLE( strict_scoped_thread) /// non copyable
+
+ /*
+ *
+ */
+#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>
+ 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) :
+ 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) :
+ t_(boost::forward<F>(f), boost::forward<A1>(a1)) {}
+ template <class F, class A1, class A2>
+ strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) :
+ t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2)) {}
+ template <class F, class A1, class A2, class A3>
+ strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) :
+ t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)) {}
+#endif
+
+ /**
+ * Constructor from the thread to own.
+ *
+ * @param t: the thread to own.
+ *
+ * Effects: move the thread to own @c t.
+ */
+ explicit strict_scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT :
+ t_(boost::move(t))
+ {
+ }
+
+ /**
+ * Destructor
+ * Effects: Call the CallableThread functor before destroying the owned thread.
+ * Remark: The CallableThread should not throw when joining the thread as the scoped variable is on a scope outside the thread function.
+ */
+ ~strict_scoped_thread()
+ {
+ CallableThread on_destructor;
+
+ on_destructor(t_);
+ }
+
+ };
+
+ /**
+ * RAI @c thread wrapper adding a specific destroyer allowing to master what can be done at destruction time.
+ *
+ * CallableThread: A callable void(thread&) .
+ * The default is join_if_joinable.
+ *
+ * thread std::thread destructor terminates the program if the thread is not joinable.
+ * Having a wrapper that can join the thread before destroying it seems a natural need.
+ *
+ * Remark: @c scoped_thread is not a @c thread as @c thread is not designed to be derived from as a polymorphic type.
+ * Anyway @c scoped_thread can be used in most of the contexts a @c thread could be used as it has the
+ * same non-deprecated interface with the exception of the construction.
+ *
+ * Example:
+ *
+ * boost::scoped_thread<> t((boost::thread(F)));
+ * t.interrupt();
+ *
+ */
+ template <class CallableThread = join_if_joinable>
+ class scoped_thread
+ {
+ thread t_;
+ struct dummy;
+ public:
+
+ typedef thread::id id;
+
+ BOOST_THREAD_MOVABLE_ONLY( scoped_thread) /// Movable only
+
+ /**
+ * Default Constructor.
+ *
+ * Effects: wraps a not-a-thread.
+ */
+ scoped_thread() BOOST_NOEXCEPT:
+ t_()
+ {
+ }
+
+ /**
+ *
+ */
+
+#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>
+ 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) :
+ t_(boost::forward<F>(f)) {}
+ template <class F, class A1>
+ scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
+ t_(boost::forward<F>(f), boost::forward<A1>(a1)) {}
+ template <class F, class A1, class A2>
+ scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) :
+ t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2)) {}
+ template <class F, class A1, class A2, class A3>
+ scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) :
+ t_(boost::forward<F>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)) {}
+
+#endif
+ /**
+ * Constructor from the thread to own.
+ *
+ * @param t: the thread to own.
+ *
+ * Effects: move the thread to own @c t.
+ */
+ explicit scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT :
+ t_(boost::move(t))
+ {
+ }
+
+// explicit operator thread()
+// {
+// return boost::move(t_);
+// }
+
+ /**
+ * Move constructor.
+ */
+ scoped_thread(BOOST_RV_REF(scoped_thread) x) BOOST_NOEXCEPT :
+ t_(boost::move(BOOST_THREAD_RV(x).t_))
+ {}
+
+ /**
+ * Destructor
+ *
+ * Effects: Call the CallableThread functor before destroying the owned thread.
+ */
+ ~scoped_thread()
+ {
+ CallableThread on_destructor;
+
+ on_destructor(t_);
+ }
+
+ /**
+ * Move assignment.
+ */
+ scoped_thread& operator=(BOOST_RV_REF(scoped_thread) x)
+ {
+ t_ = boost::move(BOOST_THREAD_RV(x).t_);
+ return *this;
+ }
+
+ /**
+ *
+ */
+ void swap(scoped_thread& x) BOOST_NOEXCEPT
+ {
+ t_.swap(x.t_);
+ }
+
+ // forwarded thread functions
+ inline thread::id get_id() const BOOST_NOEXCEPT
+ {
+ return t_.get_id();
+ }
+
+ void detach()
+ {
+ t_.detach();
+ }
+
+ void join()
+ {
+ t_.join();
+ }
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ return t_.try_join_for(rel_time);
+ }
+
+ template <class Clock, class Duration>
+ bool try_join_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+ return t_.try_join_until(abs_time);
+ }
+#endif
+
+ thread::native_handle_type native_handle()BOOST_NOEXCEPT
+ {
+ return t_.native_handle();
+ }
+
+ bool joinable() const BOOST_NOEXCEPT
+ {
+ return t_.joinable();
+ }
+
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ void interrupt()
+ {
+ t_.interrupt();
+ }
+
+ bool interruption_requested() const BOOST_NOEXCEPT
+ {
+ return t_.interruption_requested();
+ }
+#endif
+
+ static unsigned hardware_concurrency() BOOST_NOEXCEPT
+ {
+ return thread::hardware_concurrency();
+ }
+
+#ifdef BOOST_THREAD_PROVIDES_PHYSICAL_CONCURRENCY
+ static unsigned physical_concurrency() BOOST_NOEXCEPT
+ {
+ return thread::physical_concurrency();
+ }
+#endif
+ };
+
+ /**
+ * Effects: swaps the contents of two scoped threads.
+ */
+ template <class Destroyer>
+ void swap(scoped_thread<Destroyer>& lhs, scoped_thread<Destroyer>& rhs)
+BOOST_NOEXCEPT {
+ return lhs.swap(rhs);
+}
+
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/shared_lock_guard.hpp b/boost/thread/shared_lock_guard.hpp
index 8a2f2c54d1..97a6397c1e 100644
--- a/boost/thread/shared_lock_guard.hpp
+++ b/boost/thread/shared_lock_guard.hpp
@@ -6,7 +6,8 @@
#ifndef BOOST_THREAD_SHARED_LOCK_GUARD_HPP
#define BOOST_THREAD_SHARED_LOCK_GUARD_HPP
#include <boost/thread/detail/config.hpp>
-#include <boost/thread/locks.hpp>
+//#include <boost/thread/locks.hpp>
+#include <boost/thread/lock_options.hpp>
#include <boost/thread/detail/delete.hpp>
namespace boost
diff --git a/boost/thread/shared_mutex.hpp b/boost/thread/shared_mutex.hpp
index e85e269d44..b968f2ac10 100644
--- a/boost/thread/shared_mutex.hpp
+++ b/boost/thread/shared_mutex.hpp
@@ -18,9 +18,32 @@
#include <boost/thread/win32/shared_mutex.hpp>
#endif
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
+//#include <boost/thread/v2/shared_mutex.hpp>
#include <boost/thread/pthread/shared_mutex.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
+#include <boost/thread/lockable_traits.hpp>
+
+namespace boost
+{
+ namespace sync
+ {
+#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
+ template<>
+ struct is_basic_lockable<shared_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+ template<>
+ struct is_lockable<shared_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+#endif
+
+ }
+}
+
#endif
diff --git a/boost/thread/strict_lock.hpp b/boost/thread/strict_lock.hpp
new file mode 100644
index 0000000000..93b7b1e71c
--- /dev/null
+++ b/boost/thread/strict_lock.hpp
@@ -0,0 +1,235 @@
+// 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)
+// (C) Copyright 2008-2009,2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_STRICT_LOCK_HPP
+#define BOOST_THREAD_STRICT_LOCK_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/lockable_wrapper.hpp>
+#include <boost/thread/lock_options.hpp>
+#include <boost/thread/lock_traits.hpp>
+#include <boost/thread/lockable_traits.hpp>
+#include <boost/thread/lockable_concepts.hpp>
+#include <boost/thread/lock_concepts.hpp>
+#include <boost/thread/exceptions.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+
+ //[strict_lock
+ template <typename Lockable>
+ class strict_lock
+ {
+
+ BOOST_CONCEPT_ASSERT(( BasicLockable<Lockable> ));
+ public:
+ typedef Lockable mutex_type;
+
+ // construct/copy/destroy:
+
+ BOOST_THREAD_NO_COPYABLE( strict_lock)
+
+ /**
+ * Constructor from a mutex reference.
+ *
+ * @param mtx the mutex to lock.
+ *
+ * __Effects: Stores a reference to the mutex to lock and locks it.
+ * __Throws: Any exception BasicMutex::lock() can throw.
+ */
+ explicit strict_lock(mutex_type& mtx) :
+ mtx_(mtx)
+ {
+ mtx.lock();
+ } /*< locks on construction >*/
+
+
+#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST
+ strict_lock(std::initializer_list<thread_detail::lockable_wrapper<Lockable> > l_) :
+ mtx_(*(const_cast<thread_detail::lockable_wrapper<Lockable>*>(l_.begin())->m))
+ {
+ mtx_.lock();
+ }
+#endif
+
+ /**
+ * Destructor
+ *
+ * __Effects: unlocks the stored mutex.
+ *
+ * __Throws
+ */
+ ~strict_lock()
+ {
+ mtx_.unlock();
+ } /*< unlocks on destruction >*/
+
+
+ // observers
+
+ /**
+ * @return the owned mutex.
+ */
+ mutex_type* mutex() const BOOST_NOEXCEPT
+ {
+ return &mtx_;
+ }
+
+ /**
+ * @return whether this lock is locking a mutex.
+ */
+ bool owns_lock() const BOOST_NOEXCEPT
+ {
+ return true;
+ }
+
+ /**
+ * @return whether this lock is locking that mutex.
+ */
+ bool owns_lock(const mutex_type* l) const BOOST_NOEXCEPT
+ {
+ return l == mutex();
+ } /*< strict locks specific function >*/
+
+ //BOOST_ADRESS_OF_DELETE(strict_lock) /*< disable aliasing >*/
+ //BOOST_HEAP_ALLOCATION_DELETE(strict_lock) /*< disable heap allocation >*/
+
+ /*< no possibility to unlock >*/
+
+ private:
+ mutex_type& mtx_;
+ };
+ //]
+ template <typename Lockable>
+ struct is_strict_lock_sur_parole<strict_lock<Lockable> > : true_type
+ {
+ };
+
+ /**
+ * A nested strict lock is a scoped lock guard ensuring the mutex is locked on its
+ * scope, by taking ownership of an nesting lock, locking the mutex on construction if not already locked
+ * and restoring the ownership to the nesting lock on destruction.
+ */
+ //[nested_strict_lock
+ template <typename Lock>
+ class nested_strict_lock
+ {
+ BOOST_CONCEPT_ASSERT(( BasicLock<Lock> )); /*< The Lock must be a movable lock >*/
+ public:
+ typedef typename Lock::mutex_type mutex_type; /*< Name the lockable type locked by Lock >*/
+
+ BOOST_THREAD_NO_COPYABLE( nested_strict_lock)
+
+ /**
+ * Constructor from a nesting @c Lock.
+ *
+ * @param lk the nesting lock
+ *
+ * __Requires: <c>lk.mutex() != null_ptr</c>
+ * __Effects: Stores the reference to the lock parameter and takes ownership on it.
+ * If the lock doesn't owns the mutex @c mtx lock it.
+ * __Postconditions: @c owns_lock(lk.mutex())
+ * __StrongException
+ * __Throws:
+ *
+ * - lock_error when BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined and lk.mutex() == null_ptr
+ *
+ * - Any exception that @c lk.lock() can throw.
+ *
+ */
+ explicit nested_strict_lock(Lock& lk) :
+ lk_(lk) /*< Store reference to lk >*/
+ {
+ /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/
+ BOOST_THREAD_ASSERT_PRECONDITION( lk.mutex() != 0,
+ lock_error()
+ );
+ if (!lk.owns_lock()) lk.lock(); /*< ensures it is locked >*/
+ tmp_lk_ = move(lk); /*< Move ownership to temporary lk >*/
+ }
+
+#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST
+ nested_strict_lock(std::initializer_list<thread_detail::lockable_wrapper<Lock> > l_) :
+ lk_(*(const_cast<thread_detail::lockable_wrapper<Lock>*>(l_.begin())->m))
+ {
+ /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/
+ BOOST_THREAD_ASSERT_PRECONDITION( lk_.mutex() != 0,
+ lock_error()
+ );
+ if (!lk_.owns_lock()) lk_.lock(); /*< ensures it is locked >*/
+ tmp_lk_ = move(lk_); /*< Move ownership to temporary lk >*/
+ }
+#endif
+
+ /**
+ * Destructor
+ *
+ * __Effects: Restores ownership to the nesting lock.
+ */
+ ~nested_strict_lock()BOOST_NOEXCEPT
+ {
+ lk_ = move(tmp_lk_); /*< Move ownership to nesting lock >*/
+ }
+
+ // observers
+ /**
+ * return @c the owned mutex.
+ */
+ mutex_type* mutex() const BOOST_NOEXCEPT
+ {
+ return tmp_lk_.mutex();
+ }
+
+ /**
+ * @return whether this lock is locking a mutex.
+ */
+ bool owns_lock() const BOOST_NOEXCEPT
+ {
+ return true;
+ }
+
+ /**
+ * @return whether if this lock is locking that mutex.
+ */
+ bool owns_lock(mutex_type const* l) const BOOST_NOEXCEPT
+ {
+ return l == mutex();
+ }
+
+ //BOOST_ADRESS_OF_DELETE(nested_strict_lock)
+ //BOOST_HEAP_ALLOCATEION_DELETE(nested_strict_lock)
+
+ private:
+ Lock& lk_;
+ Lock tmp_lk_;
+ };
+ //]
+
+ template <typename Lock>
+ struct is_strict_lock_sur_parole<nested_strict_lock<Lock> > : true_type
+ {
+ };
+
+#if ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK
+ template <typename Lockable>
+ strict_lock<Lockable> make_strict_lock(Lockable& mtx)
+ {
+ return { thread_detail::lockable_wrapper<Lockable>(mtx) };
+ }
+ template <typename Lock>
+ nested_strict_lock<Lock> make_nested_strict_lock(Lock& lk)
+ {
+ return { thread_detail::lockable_wrapper<Lock>(lk) };
+ }
+#endif
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/sync_bounded_queue.hpp b/boost/thread/sync_bounded_queue.hpp
new file mode 100644
index 0000000000..63afb614ee
--- /dev/null
+++ b/boost/thread/sync_bounded_queue.hpp
@@ -0,0 +1,722 @@
+#ifndef BOOST_THREAD_SYNC_BOUNDED_QUEUE_HPP
+#define BOOST_THREAD_SYNC_BOUNDED_QUEUE_HPP
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2013-2014. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/thread/concurrent_queues/queue_op_status.hpp>
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#endif
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ template <typename ValueType>
+ class sync_bounded_queue
+ {
+ public:
+ typedef ValueType value_type;
+ typedef std::size_t size_type;
+
+ // Constructors/Assignment/Destructors
+ BOOST_THREAD_NO_COPYABLE(sync_bounded_queue)
+ explicit sync_bounded_queue(size_type max_elems);
+ template <typename Range>
+ sync_bounded_queue(size_type max_elems, Range range);
+ ~sync_bounded_queue();
+
+ // Observers
+ inline bool empty() const;
+ inline bool full() const;
+ inline size_type capacity() const;
+ inline size_type size() const;
+ inline bool closed() const;
+
+ // Modifiers
+ inline void close();
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ inline void push(const value_type& x);
+ inline void push(BOOST_THREAD_RV_REF(value_type) x);
+ inline bool try_push(const value_type& x);
+ inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
+ inline bool try_push(no_block_tag, const value_type& x);
+ inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
+#endif
+ inline void push_back(const value_type& x);
+ inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
+ inline queue_op_status try_push_back(const value_type& x);
+ inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
+ inline queue_op_status nonblocking_push_back(const value_type& x);
+ inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
+ inline queue_op_status wait_push_back(const value_type& x);
+ inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
+
+ // Observers/Modifiers
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ inline void pull(value_type&);
+ // enable_if is_nothrow_copy_movable<value_type>
+ inline value_type pull();
+ inline shared_ptr<ValueType> ptr_pull();
+ inline bool try_pull(value_type&);
+ inline bool try_pull(no_block_tag,value_type&);
+ inline shared_ptr<ValueType> try_pull();
+#endif
+ inline void pull_front(value_type&);
+ // enable_if is_nothrow_copy_movable<value_type>
+ inline value_type pull_front();
+ inline queue_op_status try_pull_front(value_type&);
+ inline queue_op_status nonblocking_pull_front(value_type&);
+
+ inline queue_op_status wait_pull_front(ValueType& elem);
+
+ private:
+ mutable mutex mtx_;
+ condition_variable not_empty_;
+ condition_variable not_full_;
+ size_type waiting_full_;
+ size_type waiting_empty_;
+ value_type* data_;
+ size_type in_;
+ size_type out_;
+ size_type capacity_;
+ bool closed_;
+
+ inline size_type inc(size_type idx) const BOOST_NOEXCEPT
+ {
+ return (idx + 1) % capacity_;
+ }
+
+ inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
+ {
+ return in_ == out_;
+ }
+ inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
+ {
+ return in_ == out_;
+ }
+ inline bool full(unique_lock<mutex>& ) const BOOST_NOEXCEPT
+ {
+ return (inc(in_) == out_);
+ }
+ inline bool full(lock_guard<mutex>& ) const BOOST_NOEXCEPT
+ {
+ return (inc(in_) == out_);
+ }
+ inline size_type capacity(lock_guard<mutex>& ) const BOOST_NOEXCEPT
+ {
+ return capacity_-1;
+ }
+ inline size_type size(lock_guard<mutex>& lk) const BOOST_NOEXCEPT
+ {
+ if (full(lk)) return capacity(lk);
+ return ((out_+capacity(lk)-in_) % capacity(lk));
+ }
+
+ inline void throw_if_closed(unique_lock<mutex>&);
+ inline bool closed(unique_lock<mutex>&) const;
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
+ inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
+ inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
+ inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
+#endif
+ inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
+ inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
+ inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
+
+ inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
+ inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
+ inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
+
+ inline void wait_until_not_empty(unique_lock<mutex>& lk);
+ inline void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
+ inline size_type wait_until_not_full(unique_lock<mutex>& lk);
+ inline size_type wait_until_not_full(unique_lock<mutex>& lk, bool&);
+
+
+ inline void notify_not_empty_if_needed(unique_lock<mutex>& lk)
+ {
+ if (waiting_empty_ > 0)
+ {
+ --waiting_empty_;
+ lk.unlock();
+ not_empty_.notify_one();
+ }
+ }
+ inline void notify_not_full_if_needed(unique_lock<mutex>& lk)
+ {
+ if (waiting_full_ > 0)
+ {
+ --waiting_full_;
+ lk.unlock();
+ not_full_.notify_one();
+ }
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ inline void pull(value_type& elem, unique_lock<mutex>& lk)
+ {
+ elem = boost::move(data_[out_]);
+ out_ = inc(out_);
+ notify_not_full_if_needed(lk);
+ }
+ inline value_type pull(unique_lock<mutex>& lk)
+ {
+ value_type elem = boost::move(data_[out_]);
+ out_ = inc(out_);
+ notify_not_full_if_needed(lk);
+ return boost::move(elem);
+ }
+ inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& lk)
+ {
+ shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_[out_]));
+ out_ = inc(out_);
+ notify_not_full_if_needed(lk);
+ return res;
+ }
+#endif
+ inline void pull_front(value_type& elem, unique_lock<mutex>& lk)
+ {
+ elem = boost::move(data_[out_]);
+ out_ = inc(out_);
+ notify_not_full_if_needed(lk);
+ }
+ inline value_type pull_front(unique_lock<mutex>& lk)
+ {
+ value_type elem = boost::move(data_[out_]);
+ out_ = inc(out_);
+ notify_not_full_if_needed(lk);
+ return boost::move(elem);
+ }
+
+ inline void set_in(size_type in, unique_lock<mutex>& lk)
+ {
+ in_ = in;
+ notify_not_empty_if_needed(lk);
+ }
+
+ inline void push_at(const value_type& elem, size_type in_p_1, unique_lock<mutex>& lk)
+ {
+ data_[in_] = elem;
+ set_in(in_p_1, lk);
+ }
+
+ inline void push_at(BOOST_THREAD_RV_REF(value_type) elem, size_type in_p_1, unique_lock<mutex>& lk)
+ {
+ data_[in_] = boost::move(elem);
+ set_in(in_p_1, lk);
+ }
+ };
+
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>::sync_bounded_queue(typename sync_bounded_queue<ValueType>::size_type max_elems) :
+ waiting_full_(0), waiting_empty_(0), data_(new value_type[max_elems + 1]), in_(0), out_(0), capacity_(max_elems + 1),
+ closed_(false)
+ {
+ BOOST_ASSERT_MSG(max_elems >= 1, "number of elements must be > 1");
+ }
+
+// template <typename ValueType>
+// template <typename Range>
+// sync_bounded_queue<ValueType>::sync_bounded_queue(size_type max_elems, Range range) :
+// waiting_full_(0), waiting_empty_(0), data_(new value_type[max_elems + 1]), in_(0), out_(0), capacity_(max_elems + 1),
+// closed_(false)
+// {
+// BOOST_ASSERT_MSG(max_elems >= 1, "number of elements must be > 1");
+// BOOST_ASSERT_MSG(max_elems == size(range), "number of elements must match range's size");
+// try
+// {
+// typedef typename Range::iterator iterator_t;
+// iterator_t first = boost::begin(range);
+// iterator_t end = boost::end(range);
+// size_type in = 0;
+// for (iterator_t cur = first; cur != end; ++cur, ++in)
+// {
+// data_[in] = *cur;
+// }
+// set_in(in);
+// }
+// catch (...)
+// {
+// delete[] data_;
+// }
+// }
+
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>::~sync_bounded_queue()
+ {
+ delete[] data_;
+ }
+
+ template <typename ValueType>
+ void sync_bounded_queue<ValueType>::close()
+ {
+ {
+ lock_guard<mutex> lk(mtx_);
+ closed_ = true;
+ }
+ not_empty_.notify_all();
+ not_full_.notify_all();
+ }
+
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::closed() const
+ {
+ lock_guard<mutex> lk(mtx_);
+ return closed_;
+ }
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::closed(unique_lock<mutex>& ) const
+ {
+ return closed_;
+ }
+
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::empty() const
+ {
+ lock_guard<mutex> lk(mtx_);
+ return empty(lk);
+ }
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::full() const
+ {
+ lock_guard<mutex> lk(mtx_);
+ return full(lk);
+ }
+
+ template <typename ValueType>
+ typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::capacity() const
+ {
+ lock_guard<mutex> lk(mtx_);
+ return capacity(lk);
+ }
+
+ template <typename ValueType>
+ typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::size() const
+ {
+ lock_guard<mutex> lk(mtx_);
+ return size(lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
+ {
+ if (empty(lk))
+ {
+ throw_if_closed(lk);
+ return false;
+ }
+ pull(elem, lk);
+ return true;
+ }
+ template <typename ValueType>
+ shared_ptr<ValueType> sync_bounded_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
+ {
+ if (empty(lk))
+ {
+ throw_if_closed(lk);
+ return shared_ptr<ValueType>();
+ }
+ return ptr_pull(lk);
+ }
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::try_pull(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_pull(elem, lk);
+ }
+#endif
+
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
+ {
+ if (empty(lk))
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ return queue_op_status::empty;
+ }
+ pull_front(elem, lk);
+ return queue_op_status::success;
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::try_pull_front(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_pull_front(elem, lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock())
+ {
+ return false;
+ }
+ return try_pull(elem, lk);
+ }
+ template <typename ValueType>
+ boost::shared_ptr<ValueType> sync_bounded_queue<ValueType>::try_pull()
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_pull(lk);
+ }
+#endif
+
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::nonblocking_pull_front(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock())
+ {
+ return queue_op_status::busy;
+ }
+ return try_pull_front(elem, lk);
+ }
+
+ template <typename ValueType>
+ void sync_bounded_queue<ValueType>::throw_if_closed(unique_lock<mutex>&)
+ {
+ if (closed_)
+ {
+ BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
+ }
+ }
+
+ template <typename ValueType>
+ void sync_bounded_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk)
+ {
+ for (;;)
+ {
+ if (out_ != in_) break;
+ throw_if_closed(lk);
+ ++waiting_empty_;
+ not_empty_.wait(lk);
+ }
+ }
+ template <typename ValueType>
+ void sync_bounded_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk, bool & closed)
+ {
+ for (;;)
+ {
+ if (out_ != in_) break;
+ if (closed_) {closed=true; return;}
+ ++waiting_empty_;
+ not_empty_.wait(lk);
+ }
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ void sync_bounded_queue<ValueType>::pull(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk);
+ pull(elem, lk);
+ }
+// template <typename ValueType>
+// void sync_bounded_queue<ValueType>::pull(ValueType& elem, bool & closed)
+// {
+// unique_lock<mutex> lk(mtx_);
+// wait_until_not_empty(lk, closed);
+// if (closed) {return;}
+// pull(elem, lk);
+// }
+
+ // enable if ValueType is nothrow movable
+ template <typename ValueType>
+ ValueType sync_bounded_queue<ValueType>::pull()
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk);
+ return pull(lk);
+ }
+ template <typename ValueType>
+ boost::shared_ptr<ValueType> sync_bounded_queue<ValueType>::ptr_pull()
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk);
+ return ptr_pull(lk);
+ }
+
+#endif
+
+ template <typename ValueType>
+ void sync_bounded_queue<ValueType>::pull_front(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk);
+ pull_front(elem, lk);
+ }
+
+ // enable if ValueType is nothrow movable
+ template <typename ValueType>
+ ValueType sync_bounded_queue<ValueType>::pull_front()
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk);
+ return pull_front(lk);
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
+ {
+ if (empty(lk) && closed(lk)) {return queue_op_status::closed;}
+ wait_until_not_empty(lk);
+ pull_front(elem, lk);
+ return queue_op_status::success;
+ }
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return wait_pull_front(elem, lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
+ {
+ throw_if_closed(lk);
+ size_type in_p_1 = inc(in_);
+ if (in_p_1 == out_) // full()
+ {
+ return false;
+ }
+ push_at(elem, in_p_1, lk);
+ return true;
+ }
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::try_push(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_push(elem, lk);
+ }
+
+#endif
+
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ size_type in_p_1 = inc(in_);
+ if (in_p_1 == out_) // full()
+ {
+ return queue_op_status::full;
+ }
+ push_at(elem, in_p_1, lk);
+ return queue_op_status::success;
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::try_push_back(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_push_back(elem, lk);
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ push_at(elem, wait_until_not_full(lk), lk);
+ return queue_op_status::success;
+ }
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::wait_push_back(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return wait_push_back(elem, lk);
+ }
+
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock()) return false;
+ return try_push(elem, lk);
+ }
+#endif
+
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::nonblocking_push_back(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock()) return queue_op_status::busy;
+ return try_push_back(elem, lk);
+ }
+
+ template <typename ValueType>
+ typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::wait_until_not_full(unique_lock<mutex>& lk)
+ {
+ for (;;)
+ {
+ throw_if_closed(lk);
+ size_type in_p_1 = inc(in_);
+ if (in_p_1 != out_) // ! full()
+ {
+ return in_p_1;
+ }
+ ++waiting_full_;
+ not_full_.wait(lk);
+ }
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ void sync_bounded_queue<ValueType>::push(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ push_at(elem, wait_until_not_full(lk), lk);
+ }
+#endif
+ template <typename ValueType>
+ void sync_bounded_queue<ValueType>::push_back(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ push_at(elem, wait_until_not_full(lk), lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
+ {
+ throw_if_closed(lk);
+ size_type in_p_1 = inc(in_);
+ if (in_p_1 == out_) // full()
+ {
+ return false;
+ }
+ push_at(boost::move(elem), in_p_1, lk);
+ return true;
+ }
+
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_push(boost::move(elem), lk);
+ }
+#endif
+
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ size_type in_p_1 = inc(in_);
+ if (in_p_1 == out_) // full()
+ {
+ return queue_op_status::full;
+ }
+ push_at(boost::move(elem), in_p_1, lk);
+ return queue_op_status::success;
+ }
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_push_back(boost::move(elem), lk);
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ push_at(boost::move(elem), wait_until_not_full(lk), lk);
+ return queue_op_status::success;
+ }
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_push_back(boost::move(elem), lk);
+ }
+
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_bounded_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock())
+ {
+ return false;
+ }
+ return try_push(boost::move(elem), lk);
+ }
+#endif
+ template <typename ValueType>
+ queue_op_status sync_bounded_queue<ValueType>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock())
+ {
+ return queue_op_status::busy;
+ }
+ return try_push_back(boost::move(elem), lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ void sync_bounded_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ push_at(boost::move(elem), wait_until_not_full(lk), lk);
+ }
+#endif
+ template <typename ValueType>
+ void sync_bounded_queue<ValueType>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ push_at(boost::move(elem), wait_until_not_full(lk), lk);
+ }
+
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ sbq.push_back(boost::move(elem));
+ return sbq;
+ }
+
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, ValueType const&elem)
+ {
+ sbq.push_back(elem);
+ return sbq;
+ }
+
+ template <typename ValueType>
+ sync_bounded_queue<ValueType>& operator>>(sync_bounded_queue<ValueType>& sbq, ValueType &elem)
+ {
+ sbq.pull_front(elem);
+ return sbq;
+ }
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/sync_queue.hpp b/boost/thread/sync_queue.hpp
new file mode 100644
index 0000000000..5037e909ed
--- /dev/null
+++ b/boost/thread/sync_queue.hpp
@@ -0,0 +1,663 @@
+#ifndef BOOST_THREAD_SYNC_QUEUE_HPP
+#define BOOST_THREAD_SYNC_QUEUE_HPP
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Vicente J. Botet Escriba 2013-2014. 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)
+//
+// See http://www.boost.org/libs/thread for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/concurrent_queues/queue_op_status.hpp>
+
+#include <boost/throw_exception.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <boost/thread/csbl/deque.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ template <typename ValueType>
+ class sync_queue
+ {
+ public:
+ typedef ValueType value_type;
+ typedef csbl::deque<ValueType> underlying_queue_type;
+ typedef std::size_t size_type;
+ typedef queue_op_status op_status;
+
+ // Constructors/Assignment/Destructors
+ BOOST_THREAD_NO_COPYABLE(sync_queue)
+ inline sync_queue();
+ //template <typename Range>
+ //inline explicit sync_queue(Range range);
+ inline ~sync_queue();
+
+ // Observers
+ inline bool empty() const;
+ inline bool full() const;
+ inline size_type size() const;
+ inline bool closed() const;
+
+ // Modifiers
+ inline void close();
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ inline void push(const value_type& x);
+ inline bool try_push(const value_type& x);
+ inline bool try_push(no_block_tag, const value_type& x);
+ inline void push(BOOST_THREAD_RV_REF(value_type) x);
+ inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
+ inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
+#endif
+ inline void push_back(const value_type& x);
+ inline queue_op_status try_push_back(const value_type& x);
+ inline queue_op_status nonblocking_push_back(const value_type& x);
+ inline queue_op_status wait_push_back(const value_type& x);
+ inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
+ inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
+ inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
+ inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
+
+
+ // Observers/Modifiers
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ inline void pull(value_type&);
+ inline void pull(ValueType& elem, bool & closed);
+ // enable_if is_nothrow_copy_movable<value_type>
+ inline value_type pull();
+ inline shared_ptr<ValueType> ptr_pull();
+#endif
+ inline void pull_front(value_type&);
+ // enable_if is_nothrow_copy_movable<value_type>
+ inline value_type pull_front();
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ inline bool try_pull(value_type&);
+ inline bool try_pull(no_block_tag,value_type&);
+ inline shared_ptr<ValueType> try_pull();
+#endif
+ inline queue_op_status try_pull_front(value_type&);
+ inline queue_op_status nonblocking_pull_front(value_type&);
+ inline queue_op_status wait_pull_front(ValueType& elem);
+
+ inline underlying_queue_type underlying_queue() {
+ lock_guard<mutex> lk(mtx_);
+ waiting_empty_ = 0;
+ return boost::move(data_);
+ }
+
+ private:
+ mutable mutex mtx_;
+ condition_variable not_empty_;
+ size_type waiting_empty_;
+ underlying_queue_type data_;
+ bool closed_;
+
+ inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
+ {
+ return data_.empty();
+ }
+ inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
+ {
+ return data_.empty();
+ }
+
+ inline size_type size(lock_guard<mutex>& ) const BOOST_NOEXCEPT
+ {
+ return data_.size();
+ }
+
+ inline void throw_if_closed(unique_lock<mutex>&);
+ inline bool closed(unique_lock<mutex>& lk) const;
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
+ inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
+ inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
+ inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
+#endif
+ inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
+ inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
+ inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
+ inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
+ inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
+ inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
+
+ inline void wait_until_not_empty(unique_lock<mutex>& lk);
+ inline void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
+
+ inline void notify_not_empty_if_needed(unique_lock<mutex>& lk)
+ {
+ if (waiting_empty_ > 0)
+ {
+ --waiting_empty_;
+ lk.unlock();
+ not_empty_.notify_one();
+ }
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ inline void pull(value_type& elem, unique_lock<mutex>& )
+ {
+ elem = boost::move(data_.front());
+ data_.pop_front();
+ }
+ inline value_type pull(unique_lock<mutex>& )
+ {
+ value_type e = boost::move(data_.front());
+ data_.pop_front();
+ return boost::move(e);
+ }
+ inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& )
+ {
+ shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_.front()));
+ data_.pop_front();
+ return res;
+ }
+#endif
+ inline void pull_front(value_type& elem, unique_lock<mutex>& )
+ {
+ elem = boost::move(data_.front());
+ data_.pop_front();
+ }
+ inline value_type pull_front(unique_lock<mutex>& )
+ {
+ value_type e = boost::move(data_.front());
+ data_.pop_front();
+ return boost::move(e);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ inline void push(const value_type& elem, unique_lock<mutex>& lk)
+ {
+ data_.push_back(elem);
+ notify_not_empty_if_needed(lk);
+ }
+
+ inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
+ {
+ data_.push_back(boost::move(elem));
+ notify_not_empty_if_needed(lk);
+ }
+#endif
+ inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
+ {
+ data_.push_back(elem);
+ notify_not_empty_if_needed(lk);
+ }
+
+ inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
+ {
+ data_.push_back(boost::move(elem));
+ notify_not_empty_if_needed(lk);
+ }
+ };
+
+ template <typename ValueType>
+ sync_queue<ValueType>::sync_queue() :
+ waiting_empty_(0), data_(), closed_(false)
+ {
+ BOOST_ASSERT(data_.empty());
+ }
+
+// template <typename ValueType>
+// template <typename Range>
+// explicit sync_queue<ValueType>::sync_queue(Range range) :
+// waiting_empty_(0), data_(), closed_(false)
+// {
+// try
+// {
+// typedef typename Range::iterator iterator_t;
+// iterator_t first = boost::begin(range);
+// iterator_t end = boost::end(range);
+// for (iterator_t cur = first; cur != end; ++cur)
+// {
+// data_.push(boost::move(*cur));;
+// }
+// notify_not_empty_if_needed(lk);
+// }
+// catch (...)
+// {
+// delete[] data_;
+// }
+// }
+
+ template <typename ValueType>
+ sync_queue<ValueType>::~sync_queue()
+ {
+ }
+
+ template <typename ValueType>
+ void sync_queue<ValueType>::close()
+ {
+ {
+ lock_guard<mutex> lk(mtx_);
+ closed_ = true;
+ }
+ not_empty_.notify_all();
+ }
+
+ template <typename ValueType>
+ bool sync_queue<ValueType>::closed() const
+ {
+ lock_guard<mutex> lk(mtx_);
+ return closed_;
+ }
+ template <typename ValueType>
+ bool sync_queue<ValueType>::closed(unique_lock<mutex>&) const
+ {
+ return closed_;
+ }
+
+ template <typename ValueType>
+ bool sync_queue<ValueType>::empty() const
+ {
+ lock_guard<mutex> lk(mtx_);
+ return empty(lk);
+ }
+ template <typename ValueType>
+ bool sync_queue<ValueType>::full() const
+ {
+ return false;
+ }
+
+ template <typename ValueType>
+ typename sync_queue<ValueType>::size_type sync_queue<ValueType>::size() const
+ {
+ lock_guard<mutex> lk(mtx_);
+ return size(lk);
+ }
+
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
+ {
+ if (empty(lk))
+ {
+ throw_if_closed(lk);
+ return false;
+ }
+ pull(elem, lk);
+ return true;
+ }
+ template <typename ValueType>
+ shared_ptr<ValueType> sync_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
+ {
+ if (empty(lk))
+ {
+ throw_if_closed(lk);
+ return shared_ptr<ValueType>();
+ }
+ return ptr_pull(lk);
+ }
+#endif
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
+ {
+ if (empty(lk))
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ return queue_op_status::empty;
+ }
+ pull_front(elem, lk);
+ return queue_op_status::success;
+ }
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
+ {
+ if (empty(lk))
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ }
+ bool has_been_closed = false;
+ wait_until_not_empty(lk, has_been_closed);
+ if (has_been_closed) return queue_op_status::closed;
+ pull_front(elem, lk);
+ return queue_op_status::success;
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_queue<ValueType>::try_pull(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_pull(elem, lk);
+ }
+#endif
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_pull_front(elem, lk);
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return wait_pull_front(elem, lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock())
+ {
+ return false;
+ }
+ return try_pull(elem, lk);
+ }
+ template <typename ValueType>
+ boost::shared_ptr<ValueType> sync_queue<ValueType>::try_pull()
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_pull(lk);
+ }
+#endif
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::nonblocking_pull_front(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock())
+ {
+ return queue_op_status::busy;
+ }
+ return try_pull_front(elem, lk);
+ }
+
+ template <typename ValueType>
+ void sync_queue<ValueType>::throw_if_closed(unique_lock<mutex>&)
+ {
+ if (closed_)
+ {
+ BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
+ }
+ }
+
+ template <typename ValueType>
+ void sync_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk)
+ {
+ for (;;)
+ {
+ if (! empty(lk)) break;
+ throw_if_closed(lk);
+ ++waiting_empty_;
+ not_empty_.wait(lk);
+ }
+ }
+ template <typename ValueType>
+ void sync_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk, bool & closed)
+ {
+ for (;;)
+ {
+ if (! empty(lk)) break;
+ if (closed_) {closed=true; return;}
+ ++waiting_empty_;
+ not_empty_.wait(lk);
+ }
+ closed=false;
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ void sync_queue<ValueType>::pull(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk);
+ pull(elem, lk);
+ }
+ template <typename ValueType>
+ void sync_queue<ValueType>::pull(ValueType& elem, bool & closed)
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk, closed);
+ if (closed) {return;}
+ pull(elem, lk);
+ }
+
+ // enable if ValueType is nothrow movable
+ template <typename ValueType>
+ ValueType sync_queue<ValueType>::pull()
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk);
+ return pull(lk);
+ }
+ template <typename ValueType>
+ boost::shared_ptr<ValueType> sync_queue<ValueType>::ptr_pull()
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk);
+ return ptr_pull(lk);
+ }
+#endif
+
+ template <typename ValueType>
+ void sync_queue<ValueType>::pull_front(ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk);
+ pull_front(elem, lk);
+ }
+
+ // enable if ValueType is nothrow movable
+ template <typename ValueType>
+ ValueType sync_queue<ValueType>::pull_front()
+ {
+ unique_lock<mutex> lk(mtx_);
+ wait_until_not_empty(lk);
+ return pull_front(lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
+ {
+ throw_if_closed(lk);
+ push(elem, lk);
+ return true;
+ }
+
+ template <typename ValueType>
+ bool sync_queue<ValueType>::try_push(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_push(elem, lk);
+ }
+#endif
+
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ push_back(elem, lk);
+ return queue_op_status::success;
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_push_back(elem, lk);
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ push_back(elem, lk);
+ return queue_op_status::success;
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return wait_push_back(elem, lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock()) return false;
+ return try_push(elem, lk);
+ }
+#endif
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::nonblocking_push_back(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock()) return queue_op_status::busy;
+ return try_push_back(elem, lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ void sync_queue<ValueType>::push(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ throw_if_closed(lk);
+ push(elem, lk);
+ }
+#endif
+
+ template <typename ValueType>
+ void sync_queue<ValueType>::push_back(const ValueType& elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ throw_if_closed(lk);
+ push_back(elem, lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
+ {
+ throw_if_closed(lk);
+ push(boost::move(elem), lk);
+ return true;
+ }
+
+ template <typename ValueType>
+ bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_push(boost::move(elem), lk);
+ }
+#endif
+
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ push_back(boost::move(elem), lk);
+ return queue_op_status::success;
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return try_push_back(boost::move(elem), lk);
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
+ {
+ if (closed(lk)) return queue_op_status::closed;
+ push_back(boost::move(elem), lk);
+ return queue_op_status::success;
+ }
+
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ return wait_push_back(boost::move(elem), lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ bool sync_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock())
+ {
+ return false;
+ }
+ return try_push(boost::move(elem), lk);
+ }
+#endif
+
+ template <typename ValueType>
+ queue_op_status sync_queue<ValueType>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_, try_to_lock);
+ if (!lk.owns_lock())
+ {
+ return queue_op_status::busy;
+ }
+ return try_push_back(boost::move(elem), lk);
+ }
+
+#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
+ template <typename ValueType>
+ void sync_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ throw_if_closed(lk);
+ push(boost::move(elem), lk);
+ }
+#endif
+
+ template <typename ValueType>
+ void sync_queue<ValueType>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ unique_lock<mutex> lk(mtx_);
+ throw_if_closed(lk);
+ push_back(boost::move(elem), lk);
+ }
+
+ template <typename ValueType>
+ sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
+ {
+ sbq.push_back(boost::move(elem));
+ return sbq;
+ }
+
+ template <typename ValueType>
+ sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType const&elem)
+ {
+ sbq.push_back(elem);
+ return sbq;
+ }
+
+ template <typename ValueType>
+ sync_queue<ValueType>& operator>>(sync_queue<ValueType>& sbq, ValueType &elem)
+ {
+ sbq.pull_front(elem);
+ return sbq;
+ }
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/synchronized_value.hpp b/boost/thread/synchronized_value.hpp
new file mode 100644
index 0000000000..e161063040
--- /dev/null
+++ b/boost/thread/synchronized_value.hpp
@@ -0,0 +1,1068 @@
+// (C) Copyright 2010 Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
+// (C) Copyright 2012 Vicente J. Botet Escriba
+// 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)
+
+
+#ifndef BOOST_THREAD_SYNCHRONIZED_VALUE_HPP
+#define BOOST_THREAD_SYNCHRONIZED_VALUE_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/lock_types.hpp>
+#include <boost/thread/lock_guard.hpp>
+#include <boost/thread/lock_algorithms.hpp>
+#include <boost/thread/lock_factories.hpp>
+#include <boost/thread/strict_lock.hpp>
+#include <boost/core/swap.hpp>
+#include <boost/utility/declval.hpp>
+//#include <boost/type_traits.hpp>
+//#include <boost/thread/detail/is_nothrow_default_constructible.hpp>
+//#if ! defined BOOST_NO_CXX11_HDR_TYPE_TRAITS
+//#include <type_traits>
+//#endif
+
+#if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
+#include <tuple> // todo change to <boost/tuple.hpp> once Boost.Tuple or Boost.Fusion provides Move semantics on C++98 compilers.
+#include <functional>
+#endif
+
+#include <boost/utility/result_of.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ /**
+ * strict lock providing a const pointer access to the synchronized value type.
+ *
+ * @param T the value type.
+ * @param Lockable the mutex type protecting the value type.
+ */
+ template <typename T, typename Lockable = mutex>
+ class const_strict_lock_ptr
+ {
+ public:
+ typedef T value_type;
+ typedef Lockable mutex_type;
+ protected:
+
+ // this should be a strict_lock, but unique_lock is needed to be able to return it.
+ boost::unique_lock<mutex_type> lk_;
+ T const& value_;
+
+ public:
+ BOOST_THREAD_MOVABLE_ONLY( const_strict_lock_ptr )
+
+ /**
+ * @param value constant reference of the value to protect.
+ * @param mtx reference to the mutex used to protect the value.
+ * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value.
+ */
+ const_strict_lock_ptr(T const& val, Lockable & mtx) :
+ lk_(mtx), value_(val)
+ {
+ }
+ const_strict_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t tag) BOOST_NOEXCEPT :
+ lk_(mtx, tag), value_(val)
+ {
+ }
+ /**
+ * Move constructor.
+ * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other.
+ */
+ const_strict_lock_ptr(BOOST_THREAD_RV_REF(const_strict_lock_ptr) other) BOOST_NOEXCEPT
+ : lk_(boost::move(BOOST_THREAD_RV(other).lk_)),value_(BOOST_THREAD_RV(other).value_)
+ {
+ }
+
+ ~const_strict_lock_ptr()
+ {
+ }
+
+ /**
+ * @return a constant pointer to the protected value
+ */
+ const T* operator->() const
+ {
+ return &value_;
+ }
+
+ /**
+ * @return a constant reference to the protected value
+ */
+ const T& operator*() const
+ {
+ return value_;
+ }
+
+ };
+
+ /**
+ * strict lock providing a pointer access to the synchronized value type.
+ *
+ * @param T the value type.
+ * @param Lockable the mutex type protecting the value type.
+ */
+ template <typename T, typename Lockable = mutex>
+ class strict_lock_ptr : public const_strict_lock_ptr<T,Lockable>
+ {
+ typedef const_strict_lock_ptr<T,Lockable> base_type;
+ public:
+ BOOST_THREAD_MOVABLE_ONLY( strict_lock_ptr )
+
+ /**
+ * @param value reference of the value to protect.
+ * @param mtx reference to the mutex used to protect the value.
+ * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value.
+ */
+ strict_lock_ptr(T & val, Lockable & mtx) :
+ base_type(val, mtx)
+ {
+ }
+ strict_lock_ptr(T & val, Lockable & mtx, adopt_lock_t tag) :
+ base_type(val, mtx, tag)
+ {
+ }
+
+ /**
+ * Move constructor.
+ * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other.
+ */
+ strict_lock_ptr(BOOST_THREAD_RV_REF(strict_lock_ptr) other)
+ : base_type(boost::move(static_cast<base_type&>(other)))
+ {
+ }
+
+ ~strict_lock_ptr()
+ {
+ }
+
+ /**
+ * @return a pointer to the protected value
+ */
+ T* operator->()
+ {
+ return const_cast<T*>(&this->value_);
+ }
+
+ /**
+ * @return a reference to the protected value
+ */
+ T& operator*()
+ {
+ return const_cast<T&>(this->value_);
+ }
+
+ };
+
+ template <typename SV>
+ struct synchronized_value_strict_lock_ptr
+ {
+ typedef strict_lock_ptr<typename SV::value_type, typename SV::mutex_type> type;
+ };
+
+ template <typename SV>
+ struct synchronized_value_strict_lock_ptr<const SV>
+ {
+ typedef const_strict_lock_ptr<typename SV::value_type, typename SV::mutex_type> type;
+ };
+ /**
+ * unique_lock providing a const pointer access to the synchronized value type.
+ *
+ * An object of type const_unique_lock_ptr is a unique_lock that provides a const pointer access to the synchronized value type.
+ * As unique_lock controls the ownership of a lockable object within a scope.
+ * Ownership of the lockable object may be acquired at construction or after construction,
+ * and may be transferred, after acquisition, to another const_unique_lock_ptr object.
+ * Objects of type const_unique_lock_ptr are not copyable but are movable.
+ * The behavior of a program is undefined if the mutex and the value type
+ * pointed do not exist for the entire remaining lifetime of the const_unique_lock_ptr object.
+ * The supplied Mutex type shall meet the BasicLockable requirements.
+ *
+ * @note const_unique_lock_ptr<T, Lockable> meets the Lockable requirements.
+ * If Lockable meets the TimedLockable requirements, const_unique_lock_ptr<T,Lockable>
+ * also meets the TimedLockable requirements.
+ *
+ * @param T the value type.
+ * @param Lockable the mutex type protecting the value type.
+ */
+ template <typename T, typename Lockable = mutex>
+ class const_unique_lock_ptr : public unique_lock<Lockable>
+ {
+ typedef unique_lock<Lockable> base_type;
+ public:
+ typedef T value_type;
+ typedef Lockable mutex_type;
+ protected:
+ T const& value_;
+
+ public:
+ BOOST_THREAD_MOVABLE_ONLY(const_unique_lock_ptr)
+
+ /**
+ * @param value reference of the value to protect.
+ * @param mtx reference to the mutex used to protect the value.
+ *
+ * @requires If mutex_type is not a recursive mutex the calling thread does not own the mutex.
+ *
+ * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value.
+ */
+ const_unique_lock_ptr(T const& val, Lockable & mtx)
+ : base_type(mtx), value_(val)
+ {
+ }
+ /**
+ * @param value reference of the value to protect.
+ * @param mtx reference to the mutex used to protect the value.
+ * @param tag of type adopt_lock_t used to differentiate the constructor.
+ * @requires The calling thread own the mutex.
+ * @effects stores a reference to it and to the value type @c value taking ownership.
+ */
+ const_unique_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t) BOOST_NOEXCEPT
+ : base_type(mtx, adopt_lock), value_(val)
+ {
+ }
+ /**
+ * @param value reference of the value to protect.
+ * @param mtx reference to the mutex used to protect the value.
+ * @param tag of type defer_lock_t used to differentiate the constructor.
+ * @effects stores a reference to it and to the value type @c value c.
+ */
+ const_unique_lock_ptr(T const& val, Lockable & mtx, defer_lock_t) BOOST_NOEXCEPT
+ : base_type(mtx, defer_lock), value_(val)
+ {
+ }
+ /**
+ * @param value reference of the value to protect.
+ * @param mtx reference to the mutex used to protect the value.
+ * @param tag of type try_to_lock_t used to differentiate the constructor.
+ * @requires If mutex_type is not a recursive mutex the calling thread does not own the mutex.
+ * @effects try to lock the mutex @c mtx, stores a reference to it and to the value type @c value.
+ */
+ const_unique_lock_ptr(T const& val, Lockable & mtx, try_to_lock_t) BOOST_NOEXCEPT
+ : base_type(mtx, try_to_lock), value_(val)
+ {
+ }
+ /**
+ * Move constructor.
+ * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other.
+ */
+ const_unique_lock_ptr(BOOST_THREAD_RV_REF(const_unique_lock_ptr) other) BOOST_NOEXCEPT
+ : base_type(boost::move(static_cast<base_type&>(other))), value_(BOOST_THREAD_RV(other).value_)
+ {
+ }
+
+ /**
+ * @effects If owns calls unlock() on the owned mutex.
+ */
+ ~const_unique_lock_ptr()
+ {
+ }
+
+ /**
+ * @return a constant pointer to the protected value
+ */
+ const T* operator->() const
+ {
+ BOOST_ASSERT (this->owns_lock());
+ return &value_;
+ }
+
+ /**
+ * @return a constant reference to the protected value
+ */
+ const T& operator*() const
+ {
+ BOOST_ASSERT (this->owns_lock());
+ return value_;
+ }
+
+ };
+
+ /**
+ * unique lock providing a pointer access to the synchronized value type.
+ *
+ * @param T the value type.
+ * @param Lockable the mutex type protecting the value type.
+ */
+ template <typename T, typename Lockable = mutex>
+ class unique_lock_ptr : public const_unique_lock_ptr<T, Lockable>
+ {
+ typedef const_unique_lock_ptr<T, Lockable> base_type;
+ public:
+ typedef T value_type;
+ typedef Lockable mutex_type;
+
+ BOOST_THREAD_MOVABLE_ONLY(unique_lock_ptr)
+
+ /**
+ * @param value reference of the value to protect.
+ * @param mtx reference to the mutex used to protect the value.
+ * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value.
+ */
+ unique_lock_ptr(T & val, Lockable & mtx)
+ : base_type(val, mtx)
+ {
+ }
+ /**
+ * @param value reference of the value to protect.
+ * @param mtx reference to the mutex used to protect the value.
+ * @param tag of type adopt_lock_t used to differentiate the constructor.
+ * @effects stores a reference to it and to the value type @c value taking ownership.
+ */
+ unique_lock_ptr(T & value, Lockable & mtx, adopt_lock_t) BOOST_NOEXCEPT
+ : base_type(value, mtx, adopt_lock)
+ {
+ }
+ /**
+ * @param value reference of the value to protect.
+ * @param mtx reference to the mutex used to protect the value.
+ * @param tag of type defer_lock_t used to differentiate the constructor.
+ * @effects stores a reference to it and to the value type @c value c.
+ */
+ unique_lock_ptr(T & value, Lockable & mtx, defer_lock_t) BOOST_NOEXCEPT
+ : base_type(value, mtx, defer_lock)
+ {
+ }
+ /**
+ * @param value reference of the value to protect.
+ * @param mtx reference to the mutex used to protect the value.
+ * @param tag of type try_to_lock_t used to differentiate the constructor.
+ * @effects try to lock the mutex @c mtx, stores a reference to it and to the value type @c value.
+ */
+ unique_lock_ptr(T & value, Lockable & mtx, try_to_lock_t) BOOST_NOEXCEPT
+ : base_type(value, mtx, try_to_lock)
+ {
+ }
+ /**
+ * Move constructor.
+ * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other.
+ */
+ unique_lock_ptr(BOOST_THREAD_RV_REF(unique_lock_ptr) other) BOOST_NOEXCEPT
+ : base_type(boost::move(static_cast<base_type&>(other)))
+ {
+ }
+
+ ~unique_lock_ptr()
+ {
+ }
+
+ /**
+ * @return a pointer to the protected value
+ */
+ T* operator->()
+ {
+ BOOST_ASSERT (this->owns_lock());
+ return const_cast<T*>(&this->value_);
+ }
+
+ /**
+ * @return a reference to the protected value
+ */
+ T& operator*()
+ {
+ BOOST_ASSERT (this->owns_lock());
+ return const_cast<T&>(this->value_);
+ }
+
+
+ };
+
+ template <typename SV>
+ struct synchronized_value_unique_lock_ptr
+ {
+ typedef unique_lock_ptr<typename SV::value_type, typename SV::mutex_type> type;
+ };
+
+ template <typename SV>
+ struct synchronized_value_unique_lock_ptr<const SV>
+ {
+ typedef const_unique_lock_ptr<typename SV::value_type, typename SV::mutex_type> type;
+ };
+ /**
+ * cloaks a value type and the mutex used to protect it together.
+ * @param T the value type.
+ * @param Lockable the mutex type protecting the value type.
+ */
+ template <typename T, typename Lockable = mutex>
+ class synchronized_value
+ {
+
+#if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS)
+#if ! defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ template <typename ...SV>
+ friend std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> synchronize(SV& ...sv);
+#else
+ template <typename SV1, typename SV2>
+ friend std::tuple<
+ typename synchronized_value_strict_lock_ptr<SV1>::type,
+ typename synchronized_value_strict_lock_ptr<SV2>::type
+ >
+ synchronize(SV1& sv1, SV2& sv2);
+ template <typename SV1, typename SV2, typename SV3>
+ friend std::tuple<
+ typename synchronized_value_strict_lock_ptr<SV1>::type,
+ typename synchronized_value_strict_lock_ptr<SV2>::type,
+ typename synchronized_value_strict_lock_ptr<SV3>::type
+ >
+ synchronize(SV1& sv1, SV2& sv2, SV3& sv3);
+#endif
+#endif
+
+ public:
+ typedef T value_type;
+ typedef Lockable mutex_type;
+ private:
+ T value_;
+ mutable mutex_type mtx_;
+ public:
+ // construction/destruction
+ /**
+ * Default constructor.
+ *
+ * @Requires: T is DefaultConstructible
+ */
+ synchronized_value()
+ //BOOST_NOEXCEPT_IF(is_nothrow_default_constructible<T>::value)
+ : value_()
+ {
+ }
+
+ /**
+ * Constructor from copy constructible value.
+ *
+ * Requires: T is CopyConstructible
+ */
+ synchronized_value(T const& other)
+ //BOOST_NOEXCEPT_IF(is_nothrow_copy_constructible<T>::value)
+ : value_(other)
+ {
+ }
+
+ /**
+ * Move Constructor.
+ *
+ * Requires: T is CopyMovable
+ */
+ synchronized_value(BOOST_THREAD_RV_REF(T) other)
+ //BOOST_NOEXCEPT_IF(is_nothrow_move_constructible<T>::value)
+ : value_(boost::move(other))
+ {
+ }
+
+ /**
+ * Constructor from value type.
+ *
+ * Requires: T is DefaultConstructible and Assignable
+ * Effects: Assigns the value on a scope protected by the mutex of the rhs. The mutex is not copied.
+ */
+ synchronized_value(synchronized_value const& rhs)
+ {
+ strict_lock<mutex_type> lk(rhs.mtx_);
+ value_ = rhs.value_;
+ }
+
+ /**
+ * Move Constructor from movable value type
+ *
+ */
+ synchronized_value(BOOST_THREAD_RV_REF(synchronized_value) other)
+ {
+ strict_lock<mutex_type> lk(BOOST_THREAD_RV(other).mtx_);
+ value_= boost::move(BOOST_THREAD_RV(other).value_);
+ }
+
+ // mutation
+ /**
+ * Assignment operator.
+ *
+ * Effects: Copies the underlying value on a scope protected by the two mutexes.
+ * The mutex is not copied. The locks are acquired using lock, so deadlock is avoided.
+ * For example, there is no problem if one thread assigns a = b and the other assigns b = a.
+ *
+ * Return: *this
+ */
+
+ synchronized_value& operator=(synchronized_value const& rhs)
+ {
+ if(&rhs != this)
+ {
+ // auto _ = make_unique_locks(mtx_, rhs.mtx_);
+ unique_lock<mutex_type> lk1(mtx_, defer_lock);
+ unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
+ lock(lk1,lk2);
+
+ value_ = rhs.value_;
+ }
+ return *this;
+ }
+ /**
+ * Assignment operator from a T const&.
+ * Effects: The operator copies the value on a scope protected by the mutex.
+ * Return: *this
+ */
+ synchronized_value& operator=(value_type const& val)
+ {
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ value_ = val;
+ }
+ return *this;
+ }
+
+ //observers
+ /**
+ * Explicit conversion to value type.
+ *
+ * Requires: T is CopyConstructible
+ * Return: A copy of the protected value obtained on a scope protected by the mutex.
+ *
+ */
+ T get() const
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return value_;
+ }
+ /**
+ * Explicit conversion to value type.
+ *
+ * Requires: T is CopyConstructible
+ * Return: A copy of the protected value obtained on a scope protected by the mutex.
+ *
+ */
+#if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+ explicit operator T() const
+ {
+ return get();
+ }
+#endif
+
+ /**
+ * value type getter.
+ *
+ * Return: A constant reference to the protected value.
+ *
+ * Note: Not thread safe
+ *
+ */
+ T const& value() const
+ {
+ return value_;
+ }
+ /**
+ * mutex getter.
+ *
+ * Return: A constant reference to the protecting mutex.
+ *
+ * Note: Not thread safe
+ *
+ */
+ mutex_type const& mutex() const
+ {
+ return mtx_;
+ }
+ /**
+ * Swap
+ *
+ * Effects: Swaps the data. Again, locks are acquired using lock(). The mutexes are not swapped.
+ * A swap method accepts a T& and swaps the data inside a critical section.
+ * This is by far the preferred method of changing the guarded datum wholesale because it keeps the lock only
+ * for a short time, thus lowering the pressure on the mutex.
+ */
+ void swap(synchronized_value & rhs)
+ {
+ if (this == &rhs) {
+ return;
+ }
+ // auto _ = make_unique_locks(mtx_, rhs.mtx_);
+ unique_lock<mutex_type> lk1(mtx_, defer_lock);
+ unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
+ lock(lk1,lk2);
+ boost::swap(value_, rhs.value_);
+ }
+ /**
+ * Swap with the underlying value type
+ *
+ * Effects: Swaps the data on a scope protected by the mutex.
+ */
+ void swap(value_type & rhs)
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ boost::swap(value_, rhs);
+ }
+
+ /**
+ * Essentially calling a method obj->foo(x, y, z) calls the method foo(x, y, z) inside a critical section as
+ * long-lived as the call itself.
+ */
+ strict_lock_ptr<T,Lockable> operator->()
+ {
+ return BOOST_THREAD_MAKE_RV_REF((strict_lock_ptr<T,Lockable>(value_, mtx_)));
+ }
+ /**
+ * If the synchronized_value object involved is const-qualified, then you'll only be able to call const methods
+ * through operator->. So, for example, vec->push_back("xyz") won't work if vec were const-qualified.
+ * The locking mechanism capitalizes on the assumption that const methods don't modify their underlying data.
+ */
+ const_strict_lock_ptr<T,Lockable> operator->() const
+ {
+ return BOOST_THREAD_MAKE_RV_REF((const_strict_lock_ptr<T,Lockable>(value_, mtx_)));
+ }
+
+ /**
+ * Call function on a locked block.
+ *
+ * @requires fct(value_) is well formed.
+ *
+ * Example
+ * void fun(synchronized_value<vector<int>> & v) {
+ * v ( [](vector<int>> & vec)
+ * {
+ * vec.push_back(42);
+ * assert(vec.back() == 42);
+ * } );
+ * }
+ */
+ template <typename F>
+ inline
+ typename boost::result_of<F(value_type&)>::type
+ operator()(BOOST_THREAD_RV_REF(F) fct)
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+ template <typename F>
+ inline
+ typename boost::result_of<F(value_type const&)>::type
+ operator()(BOOST_THREAD_RV_REF(F) fct) const
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+
+
+#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <typename F>
+ inline
+ typename boost::result_of<F(value_type&)>::type
+ operator()(F const & fct)
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+ template <typename F>
+ inline
+ typename boost::result_of<F(value_type const&)>::type
+ operator()(F const & fct) const
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+
+ template <typename R>
+ inline
+ R operator()(R(*fct)(value_type&))
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+ template <typename R>
+ inline
+ R operator()(R(*fct)(value_type const&)) const
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+#endif
+
+
+ /**
+ * The synchronize() factory make easier to lock on a scope.
+ * As discussed, operator-> can only lock over the duration of a call, so it is insufficient for complex operations.
+ * With synchronize() you get to lock the object in a scoped and to directly access the object inside that scope.
+ *
+ * Example
+ * void fun(synchronized_value<vector<int>> & v) {
+ * auto&& vec=v.synchronize();
+ * vec.push_back(42);
+ * assert(vec.back() == 42);
+ * }
+ */
+ strict_lock_ptr<T,Lockable> synchronize()
+ {
+ return BOOST_THREAD_MAKE_RV_REF((strict_lock_ptr<T,Lockable>(value_, mtx_)));
+ }
+ const_strict_lock_ptr<T,Lockable> synchronize() const
+ {
+ return BOOST_THREAD_MAKE_RV_REF((const_strict_lock_ptr<T,Lockable>(value_, mtx_)));
+ }
+
+ unique_lock_ptr<T,Lockable> unique_synchronize()
+ {
+ return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr<T,Lockable>(value_, mtx_)));
+ }
+ const_unique_lock_ptr<T,Lockable> unique_synchronize() const
+ {
+ return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr<T,Lockable>(value_, mtx_)));
+ }
+ unique_lock_ptr<T,Lockable> unique_synchronize(defer_lock_t tag)
+ {
+ return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr<T,Lockable>(value_, mtx_, tag)));
+ }
+ const_unique_lock_ptr<T,Lockable> unique_synchronize(defer_lock_t tag) const
+ {
+ return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr<T,Lockable>(value_, mtx_, tag)));
+ }
+ unique_lock_ptr<T,Lockable> defer_synchronize() BOOST_NOEXCEPT
+ {
+ return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr<T,Lockable>(value_, mtx_, defer_lock)));
+ }
+ const_unique_lock_ptr<T,Lockable> defer_synchronize() const BOOST_NOEXCEPT
+ {
+ return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr<T,Lockable>(value_, mtx_, defer_lock)));
+ }
+ unique_lock_ptr<T,Lockable> try_to_synchronize() BOOST_NOEXCEPT
+ {
+ return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr<T,Lockable>(value_, mtx_, try_to_lock)));
+ }
+ const_unique_lock_ptr<T,Lockable> try_to_synchronize() const BOOST_NOEXCEPT
+ {
+ return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr<T,Lockable>(value_, mtx_, try_to_lock)));
+ }
+ unique_lock_ptr<T,Lockable> adopt_synchronize() BOOST_NOEXCEPT
+ {
+ return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr<T,Lockable>(value_, mtx_, adopt_lock)));
+ }
+ const_unique_lock_ptr<T,Lockable> adopt_synchronize() const BOOST_NOEXCEPT
+ {
+ return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr<T,Lockable>(value_, mtx_, adopt_lock)));
+ }
+
+
+#if ! defined __IBMCPP__
+ private:
+#endif
+ class deref_value
+ {
+ private:
+ friend class synchronized_value;
+
+ boost::unique_lock<mutex_type> lk_;
+ T& value_;
+
+ explicit deref_value(synchronized_value& outer):
+ lk_(outer.mtx_),value_(outer.value_)
+ {}
+
+ public:
+ BOOST_THREAD_MOVABLE_ONLY(deref_value)
+
+ deref_value(BOOST_THREAD_RV_REF(deref_value) other):
+ lk_(boost::move(BOOST_THREAD_RV(other).lk_)),value_(BOOST_THREAD_RV(other).value_)
+ {}
+ operator T&()
+ {
+ return value_;
+ }
+
+ deref_value& operator=(T const& newVal)
+ {
+ value_=newVal;
+ return *this;
+ }
+ };
+ class const_deref_value
+ {
+ private:
+ friend class synchronized_value;
+
+ boost::unique_lock<mutex_type> lk_;
+ const T& value_;
+
+ explicit const_deref_value(synchronized_value const& outer):
+ lk_(outer.mtx_), value_(outer.value_)
+ {}
+
+ public:
+ BOOST_THREAD_MOVABLE_ONLY(const_deref_value)
+
+ const_deref_value(BOOST_THREAD_RV_REF(const_deref_value) other):
+ lk_(boost::move(BOOST_THREAD_RV(other).lk_)), value_(BOOST_THREAD_RV(other).value_)
+ {}
+
+ operator const T&()
+ {
+ return value_;
+ }
+ };
+
+ public:
+ deref_value operator*()
+ {
+ return BOOST_THREAD_MAKE_RV_REF(deref_value(*this));
+ }
+
+ const_deref_value operator*() const
+ {
+ return BOOST_THREAD_MAKE_RV_REF(const_deref_value(*this));
+ }
+
+ // io functions
+ /**
+ * @requires T is OutputStreamable
+ * @effects saves the value type on the output stream @c os.
+ */
+ template <typename OStream>
+ void save(OStream& os) const
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ os << value_;
+ }
+ /**
+ * @requires T is InputStreamable
+ * @effects loads the value type from the input stream @c is.
+ */
+ template <typename IStream>
+ void load(IStream& is) const
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ is >> value_;
+ }
+
+ // relational operators
+ /**
+ * @requires T is EqualityComparable
+ *
+ */
+ bool operator==(synchronized_value const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_, defer_lock);
+ unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
+ lock(lk1,lk2);
+
+ return value_ == rhs.value_;
+ }
+ /**
+ * @requires T is LessThanComparable
+ *
+ */
+ bool operator<(synchronized_value const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_, defer_lock);
+ unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
+ lock(lk1,lk2);
+
+ return value_ < rhs.value_;
+ }
+ /**
+ * @requires T is GreaterThanComparable
+ *
+ */
+ bool operator>(synchronized_value const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_, defer_lock);
+ unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
+ lock(lk1,lk2);
+
+ return value_ > rhs.value_;
+ }
+ bool operator<=(synchronized_value const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_, defer_lock);
+ unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
+ lock(lk1,lk2);
+
+ return value_ <= rhs.value_;
+ }
+ bool operator>=(synchronized_value const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_, defer_lock);
+ unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
+ lock(lk1,lk2);
+
+ return value_ >= rhs.value_;
+ }
+ bool operator==(value_type const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_);
+
+ return value_ == rhs;
+ }
+ bool operator!=(value_type const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_);
+
+ return value_ != rhs;
+ }
+ bool operator<(value_type const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_);
+
+ return value_ < rhs;
+ }
+ bool operator<=(value_type const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_);
+
+ return value_ <= rhs;
+ }
+ bool operator>(value_type const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_);
+
+ return value_ > rhs;
+ }
+ bool operator>=(value_type const& rhs) const
+ {
+ unique_lock<mutex_type> lk1(mtx_);
+
+ return value_ >= rhs;
+ }
+
+ };
+
+ // Specialized algorithms
+ /**
+ *
+ */
+ template <typename T, typename L>
+ inline void swap(synchronized_value<T,L> & lhs, synchronized_value<T,L> & rhs)
+ {
+ lhs.swap(rhs);
+ }
+ template <typename T, typename L>
+ inline void swap(synchronized_value<T,L> & lhs, T & rhs)
+ {
+ lhs.swap(rhs);
+ }
+ template <typename T, typename L>
+ inline void swap(T & lhs, synchronized_value<T,L> & rhs)
+ {
+ rhs.swap(lhs);
+ }
+
+ //Hash support
+
+// template <class T> struct hash;
+// template <typename T, typename L>
+// struct hash<synchronized_value<T,L> >;
+
+ // Comparison with T
+ template <typename T, typename L>
+ bool operator!=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
+ {
+ return ! (lhs==rhs);
+ }
+
+ template <typename T, typename L>
+ bool operator==(T const& lhs, synchronized_value<T,L> const&rhs)
+ {
+ return rhs==lhs;
+ }
+ template <typename T, typename L>
+ bool operator!=(T const& lhs, synchronized_value<T,L> const&rhs)
+ {
+ return rhs!=lhs;
+ }
+ template <typename T, typename L>
+ bool operator<(T const& lhs, synchronized_value<T,L> const&rhs)
+ {
+ return rhs>=lhs;
+ }
+ template <typename T, typename L>
+ bool operator<=(T const& lhs, synchronized_value<T,L> const&rhs)
+ {
+ return rhs>lhs;
+ }
+ template <typename T, typename L>
+ bool operator>(T const& lhs, synchronized_value<T,L> const&rhs)
+ {
+ return rhs<=lhs;
+ }
+ template <typename T, typename L>
+ bool operator>=(T const& lhs, synchronized_value<T,L> const&rhs)
+ {
+ return rhs<lhs;
+ }
+
+ /**
+ *
+ */
+ template <typename OStream, typename T, typename L>
+ inline OStream& operator<<(OStream& os, synchronized_value<T,L> const& rhs)
+ {
+ rhs.save(os);
+ return os;
+ }
+ template <typename IStream, typename T, typename L>
+ inline IStream& operator>>(IStream& is, synchronized_value<T,L> const& rhs)
+ {
+ rhs.load(is);
+ return is;
+ }
+
+#if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
+#if ! defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+ template <typename ...SV>
+ std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> synchronize(SV& ...sv)
+ {
+ boost::lock(sv.mtx_ ...);
+ typedef std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> t_type;
+
+ return t_type(typename synchronized_value_strict_lock_ptr<SV>::type(sv.value_, sv.mtx_, adopt_lock) ...);
+ }
+#else
+
+ template <typename SV1, typename SV2>
+ std::tuple<
+ typename synchronized_value_strict_lock_ptr<SV1>::type,
+ typename synchronized_value_strict_lock_ptr<SV2>::type
+ >
+ synchronize(SV1& sv1, SV2& sv2)
+ {
+ boost::lock(sv1.mtx_, sv2.mtx_);
+ typedef std::tuple<
+ typename synchronized_value_strict_lock_ptr<SV1>::type,
+ typename synchronized_value_strict_lock_ptr<SV2>::type
+ > t_type;
+
+ return t_type(
+ typename synchronized_value_strict_lock_ptr<SV1>::type(sv1.value_, sv1.mtx_, adopt_lock),
+ typename synchronized_value_strict_lock_ptr<SV2>::type(sv2.value_, sv2.mtx_, adopt_lock)
+ );
+
+ }
+ template <typename SV1, typename SV2, typename SV3>
+ std::tuple<
+ typename synchronized_value_strict_lock_ptr<SV1>::type,
+ typename synchronized_value_strict_lock_ptr<SV2>::type,
+ typename synchronized_value_strict_lock_ptr<SV3>::type
+ >
+ synchronize(SV1& sv1, SV2& sv2, SV3& sv3)
+ {
+ boost::lock(sv1.mtx_, sv2.mtx_);
+ typedef std::tuple<
+ typename synchronized_value_strict_lock_ptr<SV1>::type,
+ typename synchronized_value_strict_lock_ptr<SV2>::type,
+ typename synchronized_value_strict_lock_ptr<SV3>::type
+ > t_type;
+
+ return t_type(
+ typename synchronized_value_strict_lock_ptr<SV1>::type(sv1.value_, sv1.mtx_, adopt_lock),
+ typename synchronized_value_strict_lock_ptr<SV2>::type(sv2.value_, sv2.mtx_, adopt_lock),
+ typename synchronized_value_strict_lock_ptr<SV3>::type(sv3.value_, sv3.mtx_, adopt_lock)
+ );
+
+ }
+#endif
+#endif
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // header
diff --git a/boost/thread/testable_mutex.hpp b/boost/thread/testable_mutex.hpp
new file mode 100644
index 0000000000..3c87f9349a
--- /dev/null
+++ b/boost/thread/testable_mutex.hpp
@@ -0,0 +1,152 @@
+// (C) Copyright 2012 Vicente J. Botet Escriba
+// 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)
+
+
+#ifndef BOOST_THREAD_TESTABLE_LOCKABLE_HPP
+#define BOOST_THREAD_TESTABLE_LOCKABLE_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#include <boost/thread/thread_only.hpp>
+
+#include <boost/atomic.hpp>
+#include <boost/assert.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+ /**
+ * Based on Associate Mutexes with Data to Prevent Races, By Herb Sutter, May 13, 2010
+ * http://www.drdobbs.com/windows/associate-mutexes-with-data-to-prevent-r/224701827?pgno=3
+ *
+ * Make our mutex testable if it isn't already.
+ *
+ * Many mutex services (including boost::mutex) don't provide a way to ask,
+ * "Do I already hold a lock on this mutex?"
+ * Sometimes it is needed to know if a method like is_locked to be available.
+ * This wrapper associates an arbitrary lockable type with a thread id that stores the ID of the thread that
+ * currently holds the lockable. The thread id initially holds an invalid value that means no threads own the mutex.
+ * When we acquire a lock, we set the thread id; and when we release a lock, we reset it back to its default no id state.
+ *
+ */
+ template <typename Lockable>
+ class testable_mutex
+ {
+ Lockable mtx_;
+ atomic<thread::id> id_;
+ public:
+ /// the type of the wrapped lockable
+ typedef Lockable lockable_type;
+
+ /// Non copyable
+ BOOST_THREAD_NO_COPYABLE(testable_mutex)
+
+ testable_mutex() : id_(thread::id()) {}
+
+ void lock()
+ {
+ BOOST_ASSERT(! is_locked_by_this_thread());
+ mtx_.lock();
+ id_ = this_thread::get_id();
+ }
+
+ void unlock()
+ {
+ BOOST_ASSERT(is_locked_by_this_thread());
+ id_ = thread::id();
+ mtx_.unlock();
+ }
+
+ bool try_lock()
+ {
+ BOOST_ASSERT(! is_locked_by_this_thread());
+ if (mtx_.try_lock())
+ {
+ id_ = this_thread::get_id();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ BOOST_ASSERT(! is_locked_by_this_thread());
+ if (mtx_.try_lock_for(rel_time))
+ {
+ id_ = this_thread::get_id();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ template <class Clock, class Duration>
+ bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
+ {
+ BOOST_ASSERT(! is_locked_by_this_thread());
+ if (mtx_.try_lock_until(abs_time))
+ {
+ id_ = this_thread::get_id();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+#endif
+
+ bool is_locked_by_this_thread() const
+ {
+ return this_thread::get_id() == id_;
+ }
+ bool is_locked() const
+ {
+ return ! (thread::id() == id_);
+ }
+
+ thread::id get_id() const
+ {
+ return id_;
+ }
+
+ // todo add the shared and upgrade mutex functions
+ };
+
+ template <typename Lockable>
+ struct is_testable_lockable : false_type
+ {};
+
+ template <typename Lockable>
+ struct is_testable_lockable<testable_mutex<Lockable> > : true_type
+ {};
+
+// /**
+// * Overloaded function used to check if the mutex is locked when it is testable and do nothing otherwise.
+// *
+// * This function is used usually to assert the pre-condition when the function can only be called when the mutex
+// * must be locked by the current thread.
+// */
+// template <typename Lockable>
+// bool is_locked_by_this_thread(testable_mutex<Lockable> const& mtx)
+// {
+// return mtx.is_locked();
+// }
+// template <typename Lockable>
+// bool is_locked_by_this_thread(Lockable const&)
+// {
+// return true;
+// }
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // header
diff --git a/boost/thread/thread.hpp b/boost/thread/thread.hpp
index ee15c6e365..3e63b42aaa 100644
--- a/boost/thread/thread.hpp
+++ b/boost/thread/thread.hpp
@@ -9,20 +9,8 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/thread/detail/platform.hpp>
-
-#if defined(BOOST_THREAD_PLATFORM_WIN32)
-#include <boost/thread/win32/thread_data.hpp>
-#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
-#include <boost/thread/pthread/thread_data.hpp>
-#else
-#error "Boost threads unavailable on this platform"
-#endif
-
-#include <boost/thread/detail/thread.hpp>
-#include <boost/thread/detail/thread_interruption.hpp>
+#include <boost/thread/thread_only.hpp>
#include <boost/thread/detail/thread_group.hpp>
-#include <boost/thread/v2/thread.hpp>
#endif
diff --git a/boost/thread/thread_functors.hpp b/boost/thread/thread_functors.hpp
new file mode 100644
index 0000000000..f7bd816b17
--- /dev/null
+++ b/boost/thread/thread_functors.hpp
@@ -0,0 +1,57 @@
+// 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)
+// (C) Copyright 2009-2012 Anthony Williams
+// (C) Copyright 2012 Vicente J. Botet Escriba
+
+// Based on the Anthony's idea of scoped_thread in CCiA
+
+#ifndef BOOST_THREAD_THREAD_FUNCTORS_HPP
+#define BOOST_THREAD_THREAD_FUNCTORS_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/thread_only.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ struct detach
+ {
+ void operator()(thread& t)
+ {
+ t.detach();
+ }
+ };
+
+ struct join_if_joinable
+ {
+ void operator()(thread& t)
+ {
+ if (t.joinable())
+ {
+ t.join();
+ }
+ }
+ };
+
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ struct interrupt_and_join_if_joinable
+ {
+ void operator()(thread& t)
+ {
+ t.interrupt();
+ if (t.joinable())
+ {
+ t.join();
+ }
+ }
+ };
+#endif
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/thread_guard.hpp b/boost/thread/thread_guard.hpp
new file mode 100644
index 0000000000..85157f101e
--- /dev/null
+++ b/boost/thread/thread_guard.hpp
@@ -0,0 +1,46 @@
+// 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)
+// (C) Copyright 2009-2012 Anthony Williams
+// (C) Copyright 2012 Vicente J. Botet Escriba
+
+// Based on the Anthony's idea of thread_joiner in CCiA
+
+#ifndef BOOST_THREAD_THREAD_GUARD_HPP
+#define BOOST_THREAD_THREAD_GUARD_HPP
+
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/thread_functors.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ /**
+ * Non-copyable RAII scoped thread guard joiner which join the thread if joinable when destroyed.
+ */
+ template <class CallableThread = join_if_joinable>
+ class thread_guard
+ {
+ thread& t_;
+ public:
+ BOOST_THREAD_NO_COPYABLE( thread_guard)
+
+ explicit thread_guard(thread& t) :
+ t_(t)
+ {
+ }
+ ~thread_guard()
+ {
+ CallableThread on_destructor;
+
+ on_destructor(t_);
+ }
+ };
+
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/thread_only.hpp b/boost/thread/thread_only.hpp
new file mode 100644
index 0000000000..0d0c07061f
--- /dev/null
+++ b/boost/thread/thread_only.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_THREAD_THREAD_ONLY_HPP
+#define BOOST_THREAD_THREAD_ONLY_HPP
+
+// thread.hpp
+//
+// (C) Copyright 2013 Vicente J. Botet Escriba
+//
+// 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/thread/detail/platform.hpp>
+
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+#include <boost/thread/win32/thread_data.hpp>
+#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
+#include <boost/thread/pthread/thread_data.hpp>
+#else
+#error "Boost threads unavailable on this platform"
+#endif
+
+#include <boost/thread/detail/thread.hpp>
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+#include <boost/thread/detail/thread_interruption.hpp>
+#endif
+#include <boost/thread/v2/thread.hpp>
+
+
+#endif
diff --git a/boost/thread/thread_pool.hpp b/boost/thread/thread_pool.hpp
new file mode 100644
index 0000000000..4d2dcbea3a
--- /dev/null
+++ b/boost/thread/thread_pool.hpp
@@ -0,0 +1,15 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/09 Vicente J. Botet Escriba
+// Adapt to boost from CCIA C++11 implementation
+// first implementation of a simple pool thread using a vector of threads and a sync_queue.
+
+#ifndef BOOST_THREAD_THREAD_POOL_HPP
+#define BOOST_THREAD_THREAD_POOL_HPP
+
+#include <boost/thread/executors/basic_thread_pool.hpp>
+
+#endif
diff --git a/boost/thread/tss.hpp b/boost/thread/tss.hpp
index c920024b0f..d798bef558 100644
--- a/boost/thread/tss.hpp
+++ b/boost/thread/tss.hpp
@@ -19,10 +19,10 @@ namespace boost
{
virtual ~tss_cleanup_function()
{}
-
+
virtual void operator()(void* data)=0;
};
-
+
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
BOOST_THREAD_DECL void* get_tss_data(void const* key);
}
@@ -42,16 +42,16 @@ namespace boost
delete static_cast<T*>(data);
}
};
-
+
struct run_custom_cleanup_function:
detail::tss_cleanup_function
{
void (*cleanup_function)(T*);
-
+
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
cleanup_function(cleanup_function_)
{}
-
+
void operator()(void* data)
{
cleanup_function(static_cast<T*>(data));
@@ -60,10 +60,10 @@ namespace boost
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
-
+
public:
typedef T element_type;
-
+
thread_specific_ptr():
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
{}
@@ -87,7 +87,7 @@ namespace boost
{
return get();
}
- T& operator*() const
+ typename boost::detail::sp_dereference< T >::type operator*() const
{
return *get();
}
diff --git a/boost/thread/user_scheduler.hpp b/boost/thread/user_scheduler.hpp
new file mode 100644
index 0000000000..6305b9e26c
--- /dev/null
+++ b/boost/thread/user_scheduler.hpp
@@ -0,0 +1,202 @@
+// Copyright (C) 2013 Vicente J. Botet Escriba
+//
+// 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)
+//
+// 2013/11 Vicente J. Botet Escriba
+// first implementation of a simple serial scheduler.
+
+#ifndef BOOST_THREAD_USER_SCHEDULER_HPP
+#define BOOST_THREAD_USER_SCHEDULER_HPP
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/sync_queue.hpp>
+#include <boost/thread/detail/work.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ class user_scheduler
+ {
+ /// type-erasure to store the works to do
+ typedef thread_detail::work work;
+
+ /// the thread safe work queue
+ sync_queue<work > work_queue;
+
+ public:
+ /**
+ * Effects: try to execute one task.
+ * Returns: whether a task has been executed.
+ * Throws: whatever the current task constructor throws or the task() throws.
+ */
+ bool try_executing_one()
+ {
+ work task;
+ try
+ {
+ if (work_queue.try_pull_front(task) == queue_op_status::success)
+ {
+ task();
+ return true;
+ }
+ return false;
+ }
+ catch (std::exception& )
+ {
+ return false;
+ }
+ catch (...)
+ {
+ 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();
+ }
+ }
+
+
+ /**
+ * The main loop of the worker thread
+ */
+ void worker_thread()
+ {
+ while (!closed())
+ {
+ schedule_one_or_yield();
+ }
+ while (try_executing_one())
+ {
+ }
+ }
+
+ public:
+ /// user_scheduler is not copyable.
+ BOOST_THREAD_NO_COPYABLE(user_scheduler)
+
+ /**
+ * \b Effects: creates a thread pool that runs closures using one of its closure-executing methods.
+ *
+ * \b Throws: Whatever exception is thrown while initializing the needed resources.
+ */
+ user_scheduler()
+ {
+ }
+ /**
+ * \b Effects: Destroys the thread pool.
+ *
+ * \b Synchronization: The completion of all the closures happen before the completion of the \c user_scheduler destructor.
+ */
+ ~user_scheduler()
+ {
+ // signal to all the worker thread that there will be no more submissions.
+ close();
+ }
+
+ /**
+ * loop
+ */
+ void loop() { worker_thread(); }
+ /**
+ * \b Effects: close the \c user_scheduler for submissions.
+ * The loop will work until there is no more closures to run.
+ */
+ void close()
+ {
+ work_queue.close();
+ }
+
+ /**
+ * \b Returns: whether the pool is closed for submissions.
+ */
+ bool closed()
+ {
+ return work_queue.closed();
+ }
+
+ /**
+ * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
+ *
+ * \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
+ * If invoked closure throws an exception the \c user_scheduler will call \c std::terminate, as is the case with threads.
+ *
+ * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
+ *
+ * \b Throws: \c sync_queue_is_closed if the thread pool is closed.
+ * Whatever exception that can be throw while storing the closure.
+ */
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename Closure>
+ void submit(Closure & closure)
+ {
+ work w ((closure));
+ work_queue.push_back(boost::move(w));
+ //work_queue.push(work(closure)); // todo check why this doesn't work
+ }
+#endif
+ void submit(void (*closure)())
+ {
+ work w ((closure));
+ work_queue.push_back(boost::move(w));
+ //work_queue.push_back(work(closure)); // todo check why this doesn't work
+ }
+
+ template <typename Closure>
+ void submit(BOOST_THREAD_RV_REF(Closure) closure)
+ {
+ work w =boost::move(closure);
+ work_queue.push_back(boost::move(w));
+ //work_queue.push_back(work(boost::move(closure))); // todo check why this doesn't work
+ }
+
+ /**
+ * \b Requires: This must be called from an scheduled task.
+ *
+ * \b Effects: reschedule functions until pred()
+ */
+ template <typename Pred>
+ bool reschedule_until(Pred const& pred)
+ {
+ do {
+ if ( ! try_executing_one())
+ {
+ return false;
+ }
+ } while (! pred());
+ return true;
+ }
+ /**
+ * run queued closures
+ */
+ void run_queued_closures()
+ {
+ sync_queue<work>::underlying_queue_type q = work_queue.underlying_queue();
+ while (q.empty())
+ {
+ work task = q.front();
+ q.pop_front();
+ task();
+ }
+ }
+
+ };
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/boost/thread/v2/shared_mutex.hpp b/boost/thread/v2/shared_mutex.hpp
new file mode 100755
index 0000000000..5acab4d8cd
--- /dev/null
+++ b/boost/thread/v2/shared_mutex.hpp
@@ -0,0 +1,1062 @@
+#ifndef BOOST_THREAD_V2_SHARED_MUTEX_HPP
+#define BOOST_THREAD_V2_SHARED_MUTEX_HPP
+
+// shared_mutex.hpp
+//
+// Copyright Howard Hinnant 2007-2010.
+// Copyright Vicente J. Botet Escriba 2012.
+//
+// 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)
+
+/*
+<shared_mutex> synopsis
+
+namespace boost
+{
+namespace thread_v2
+{
+
+class shared_mutex
+{
+public:
+
+ shared_mutex();
+ ~shared_mutex();
+
+ shared_mutex(const shared_mutex&) = delete;
+ shared_mutex& operator=(const shared_mutex&) = delete;
+
+ // Exclusive ownership
+
+ void lock();
+ bool try_lock();
+ template <class Rep, class Period>
+ bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
+ template <class Clock, class Duration>
+ bool
+ try_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ void unlock();
+
+ // Shared ownership
+
+ void lock_shared();
+ bool try_lock_shared();
+ template <class Rep, class Period>
+ bool
+ try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
+ template <class Clock, class Duration>
+ bool
+ try_lock_shared_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ void unlock_shared();
+};
+
+class upgrade_mutex
+{
+public:
+
+ upgrade_mutex();
+ ~upgrade_mutex();
+
+ upgrade_mutex(const upgrade_mutex&) = delete;
+ upgrade_mutex& operator=(const upgrade_mutex&) = delete;
+
+ // Exclusive ownership
+
+ void lock();
+ bool try_lock();
+ template <class Rep, class Period>
+ bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
+ template <class Clock, class Duration>
+ bool
+ try_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ void unlock();
+
+ // Shared ownership
+
+ void lock_shared();
+ bool try_lock_shared();
+ template <class Rep, class Period>
+ bool
+ try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
+ template <class Clock, class Duration>
+ bool
+ try_lock_shared_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ void unlock_shared();
+
+ // Upgrade ownership
+
+ void lock_upgrade();
+ bool try_lock_upgrade();
+ template <class Rep, class Period>
+ bool
+ try_lock_upgrade_for(
+ const boost::chrono::duration<Rep, Period>& rel_time);
+ template <class Clock, class Duration>
+ bool
+ try_lock_upgrade_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ void unlock_upgrade();
+
+ // Shared <-> Exclusive
+
+ bool try_unlock_shared_and_lock();
+ template <class Rep, class Period>
+ bool
+ try_unlock_shared_and_lock_for(
+ const boost::chrono::duration<Rep, Period>& rel_time);
+ template <class Clock, class Duration>
+ bool
+ try_unlock_shared_and_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ void unlock_and_lock_shared();
+
+ // Shared <-> Upgrade
+
+ bool try_unlock_shared_and_lock_upgrade();
+ template <class Rep, class Period>
+ bool
+ try_unlock_shared_and_lock_upgrade_for(
+ const boost::chrono::duration<Rep, Period>& rel_time);
+ template <class Clock, class Duration>
+ bool
+ try_unlock_shared_and_lock_upgrade_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ void unlock_upgrade_and_lock_shared();
+
+ // Upgrade <-> Exclusive
+
+ void unlock_upgrade_and_lock();
+ bool try_unlock_upgrade_and_lock();
+ template <class Rep, class Period>
+ bool
+ try_unlock_upgrade_and_lock_for(
+ const boost::chrono::duration<Rep, Period>& rel_time);
+ template <class Clock, class Duration>
+ bool
+ try_unlock_upgrade_and_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ void unlock_and_lock_upgrade();
+};
+
+} // thread_v2
+} // boost
+
+ */
+
+#include <boost/thread/detail/config.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/chrono.hpp>
+#include <climits>
+#include <boost/system/system_error.hpp>
+#define BOOST_THREAD_INLINE inline
+
+namespace boost {
+ namespace thread_v2 {
+
+ class shared_mutex
+ {
+ typedef ::boost::mutex mutex_t;
+ typedef ::boost::condition_variable cond_t;
+ typedef unsigned count_t;
+
+ mutex_t mut_;
+ cond_t gate1_;
+ cond_t gate2_;
+ count_t state_;
+
+ static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
+ static const count_t n_readers_ = ~write_entered_;
+
+ public:
+ BOOST_THREAD_INLINE shared_mutex();
+ BOOST_THREAD_INLINE ~shared_mutex();
+
+#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
+ shared_mutex(shared_mutex const&) = delete;
+ shared_mutex& operator=(shared_mutex const&) = delete;
+#else // BOOST_NO_CXX11_DELETED_FUNCTIONS
+ private:
+ shared_mutex(shared_mutex const&);
+ shared_mutex& operator=(shared_mutex const&);
+ public:
+#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
+
+ // Exclusive ownership
+
+ BOOST_THREAD_INLINE void lock();
+ BOOST_THREAD_INLINE bool try_lock();
+ template <class Rep, class Period>
+ bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_lock_until(boost::chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ BOOST_THREAD_INLINE void unlock();
+
+
+ // Shared ownership
+
+ BOOST_THREAD_INLINE void lock_shared();
+ BOOST_THREAD_INLINE bool try_lock_shared();
+ template <class Rep, class Period>
+ bool
+ try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_lock_shared_until(boost::chrono::steady_clock::now() +
+ rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_lock_shared_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ BOOST_THREAD_INLINE void unlock_shared();
+
+#if defined BOOST_THREAD_USES_DATETIME
+ bool timed_lock(system_time const& timeout);
+ template<typename TimeDuration>
+ bool timed_lock(TimeDuration const & relative_time)
+ {
+ return timed_lock(get_system_time()+relative_time);
+ }
+ bool timed_lock_shared(system_time const& timeout);
+ template<typename TimeDuration>
+ bool timed_lock_shared(TimeDuration const & relative_time)
+ {
+ return timed_lock_shared(get_system_time()+relative_time);
+ }
+#endif
+ };
+
+ template <class Clock, class Duration>
+ bool
+ shared_mutex::try_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (state_ & write_entered_)
+ {
+ while (true)
+ {
+ boost::cv_status status = gate1_.wait_until(lk, abs_time);
+ if ((state_ & write_entered_) == 0)
+ break;
+ if (status == boost::cv_status::timeout)
+ return false;
+ }
+ }
+ state_ |= write_entered_;
+ if (state_ & n_readers_)
+ {
+ while (true)
+ {
+ boost::cv_status status = gate2_.wait_until(lk, abs_time);
+ if ((state_ & n_readers_) == 0)
+ break;
+ if (status == boost::cv_status::timeout)
+ {
+ state_ &= ~write_entered_;
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ template <class Clock, class Duration>
+ bool
+ shared_mutex::try_lock_shared_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
+ {
+ while (true)
+ {
+ boost::cv_status status = gate1_.wait_until(lk, abs_time);
+ if ((state_ & write_entered_) == 0 &&
+ (state_ & n_readers_) < n_readers_)
+ break;
+ if (status == boost::cv_status::timeout)
+ return false;
+ }
+ }
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ return true;
+ }
+
+#if defined BOOST_THREAD_USES_DATETIME
+ bool shared_mutex::timed_lock(system_time const& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (state_ & write_entered_)
+ {
+ while (true)
+ {
+ bool status = gate1_.timed_wait(lk, abs_time);
+ if ((state_ & write_entered_) == 0)
+ break;
+ if (!status)
+ return false;
+ }
+ }
+ state_ |= write_entered_;
+ if (state_ & n_readers_)
+ {
+ while (true)
+ {
+ bool status = gate2_.timed_wait(lk, abs_time);
+ if ((state_ & n_readers_) == 0)
+ break;
+ if (!status)
+ {
+ state_ &= ~write_entered_;
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ bool shared_mutex::timed_lock_shared(system_time const& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (state_ & write_entered_)
+ {
+ while (true)
+ {
+ bool status = gate1_.timed_wait(lk, abs_time);
+ if ((state_ & write_entered_) == 0)
+ break;
+ if (!status )
+ return false;
+ }
+ }
+ state_ |= write_entered_;
+ if (state_ & n_readers_)
+ {
+ while (true)
+ {
+ bool status = gate2_.timed_wait(lk, abs_time);
+ if ((state_ & n_readers_) == 0)
+ break;
+ if (!status)
+ {
+ state_ &= ~write_entered_;
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+#endif
+ class upgrade_mutex
+ {
+ typedef boost::mutex mutex_t;
+ typedef boost::condition_variable cond_t;
+ typedef unsigned count_t;
+
+ mutex_t mut_;
+ cond_t gate1_;
+ cond_t gate2_;
+ count_t state_;
+
+ static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
+ static const unsigned upgradable_entered_ = write_entered_ >> 1;
+ static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_);
+
+ public:
+
+ BOOST_THREAD_INLINE upgrade_mutex();
+ BOOST_THREAD_INLINE ~upgrade_mutex();
+
+#ifndef BOOST_CXX11_NO_DELETED_FUNCTIONS
+ upgrade_mutex(const upgrade_mutex&) = delete;
+ upgrade_mutex& operator=(const upgrade_mutex&) = delete;
+#else // BOOST_CXX11_NO_DELETED_FUNCTIONS
+ private:
+ upgrade_mutex(const upgrade_mutex&);
+ upgrade_mutex& operator=(const upgrade_mutex&);
+ public:
+#endif // BOOST_CXX11_NO_DELETED_FUNCTIONS
+
+ // Exclusive ownership
+
+ BOOST_THREAD_INLINE void lock();
+ BOOST_THREAD_INLINE bool try_lock();
+ template <class Rep, class Period>
+ bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_lock_until(boost::chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ BOOST_THREAD_INLINE void unlock();
+
+ // Shared ownership
+
+ BOOST_THREAD_INLINE void lock_shared();
+ BOOST_THREAD_INLINE bool try_lock_shared();
+ template <class Rep, class Period>
+ bool
+ try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_lock_shared_until(boost::chrono::steady_clock::now() +
+ rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_lock_shared_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ BOOST_THREAD_INLINE void unlock_shared();
+
+ // Upgrade ownership
+
+ BOOST_THREAD_INLINE void lock_upgrade();
+ BOOST_THREAD_INLINE bool try_lock_upgrade();
+ template <class Rep, class Period>
+ bool
+ try_lock_upgrade_for(
+ const boost::chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_lock_upgrade_until(boost::chrono::steady_clock::now() +
+ rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_lock_upgrade_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ BOOST_THREAD_INLINE void unlock_upgrade();
+
+ // Shared <-> Exclusive
+
+ BOOST_THREAD_INLINE bool try_unlock_shared_and_lock();
+ template <class Rep, class Period>
+ bool
+ try_unlock_shared_and_lock_for(
+ const boost::chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_unlock_shared_and_lock_until(
+ boost::chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_unlock_shared_and_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ BOOST_THREAD_INLINE void unlock_and_lock_shared();
+
+ // Shared <-> Upgrade
+
+ BOOST_THREAD_INLINE bool try_unlock_shared_and_lock_upgrade();
+ template <class Rep, class Period>
+ bool
+ try_unlock_shared_and_lock_upgrade_for(
+ const boost::chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_unlock_shared_and_lock_upgrade_until(
+ boost::chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_unlock_shared_and_lock_upgrade_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ BOOST_THREAD_INLINE void unlock_upgrade_and_lock_shared();
+
+ // Upgrade <-> Exclusive
+
+ BOOST_THREAD_INLINE void unlock_upgrade_and_lock();
+ BOOST_THREAD_INLINE bool try_unlock_upgrade_and_lock();
+ template <class Rep, class Period>
+ bool
+ try_unlock_upgrade_and_lock_for(
+ const boost::chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_unlock_upgrade_and_lock_until(
+ boost::chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool
+ try_unlock_upgrade_and_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
+ BOOST_THREAD_INLINE void unlock_and_lock_upgrade();
+
+#if defined BOOST_THREAD_USES_DATETIME
+ inline bool timed_lock(system_time const& abs_time);
+ template<typename TimeDuration>
+ bool timed_lock(TimeDuration const & relative_time)
+ {
+ return timed_lock(get_system_time()+relative_time);
+ }
+ inline bool timed_lock_shared(system_time const& abs_time);
+ template<typename TimeDuration>
+ bool timed_lock_shared(TimeDuration const & relative_time)
+ {
+ return timed_lock_shared(get_system_time()+relative_time);
+ }
+ inline bool timed_lock_upgrade(system_time const& abs_time);
+ template<typename TimeDuration>
+ bool timed_lock_upgrade(TimeDuration const & relative_time)
+ {
+ return timed_lock_upgrade(get_system_time()+relative_time);
+ }
+#endif
+
+ };
+
+ template <class Clock, class Duration>
+ bool
+ upgrade_mutex::try_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (state_ & (write_entered_ | upgradable_entered_))
+ {
+ while (true)
+ {
+ boost::cv_status status = gate1_.wait_until(lk, abs_time);
+ if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
+ break;
+ if (status == boost::cv_status::timeout)
+ return false;
+ }
+ }
+ state_ |= write_entered_;
+ if (state_ & n_readers_)
+ {
+ while (true)
+ {
+ boost::cv_status status = gate2_.wait_until(lk, abs_time);
+ if ((state_ & n_readers_) == 0)
+ break;
+ if (status == boost::cv_status::timeout)
+ {
+ state_ &= ~write_entered_;
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ template <class Clock, class Duration>
+ bool
+ upgrade_mutex::try_lock_shared_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
+ {
+ while (true)
+ {
+ boost::cv_status status = gate1_.wait_until(lk, abs_time);
+ if ((state_ & write_entered_) == 0 &&
+ (state_ & n_readers_) < n_readers_)
+ break;
+ if (status == boost::cv_status::timeout)
+ return false;
+ }
+ }
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ return true;
+ }
+
+ template <class Clock, class Duration>
+ bool
+ upgrade_mutex::try_lock_upgrade_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if ((state_ & (write_entered_ | upgradable_entered_)) ||
+ (state_ & n_readers_) == n_readers_)
+ {
+ while (true)
+ {
+ boost::cv_status status = gate1_.wait_until(lk, abs_time);
+ if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
+ (state_ & n_readers_) < n_readers_)
+ break;
+ if (status == boost::cv_status::timeout)
+ return false;
+ }
+ }
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= upgradable_entered_ | num_readers;
+ return true;
+ }
+
+#if defined BOOST_THREAD_USES_DATETIME
+ bool upgrade_mutex::timed_lock(system_time const& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (state_ & (write_entered_ | upgradable_entered_))
+ {
+ while (true)
+ {
+ bool status = gate1_.timed_wait(lk, abs_time);
+ if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
+ break;
+ if (!status)
+ return false;
+ }
+ }
+ state_ |= write_entered_;
+ if (state_ & n_readers_)
+ {
+ while (true)
+ {
+ bool status = gate2_.timed_wait(lk, abs_time);
+ if ((state_ & n_readers_) == 0)
+ break;
+ if (!status)
+ {
+ state_ &= ~write_entered_;
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ bool upgrade_mutex::timed_lock_shared(system_time const& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
+ {
+ while (true)
+ {
+ bool status = gate1_.timed_wait(lk, abs_time);
+ if ((state_ & write_entered_) == 0 &&
+ (state_ & n_readers_) < n_readers_)
+ break;
+ if (!status)
+ return false;
+ }
+ }
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ return true;
+ }
+ bool upgrade_mutex::timed_lock_upgrade(system_time const& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if ((state_ & (write_entered_ | upgradable_entered_)) ||
+ (state_ & n_readers_) == n_readers_)
+ {
+ while (true)
+ {
+ bool status = gate1_.timed_wait(lk, abs_time);
+ if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
+ (state_ & n_readers_) < n_readers_)
+ break;
+ if (!status)
+ return false;
+ }
+ }
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= upgradable_entered_ | num_readers;
+ return true;
+ }
+
+#endif
+ template <class Clock, class Duration>
+ bool
+ upgrade_mutex::try_unlock_shared_and_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (state_ != 1)
+ {
+ while (true)
+ {
+ boost::cv_status status = gate2_.wait_until(lk, abs_time);
+ if (state_ == 1)
+ break;
+ if (status == boost::cv_status::timeout)
+ return false;
+ }
+ }
+ state_ = write_entered_;
+ return true;
+ }
+
+ template <class Clock, class Duration>
+ bool
+ upgrade_mutex::try_unlock_shared_and_lock_upgrade_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if ((state_ & (write_entered_ | upgradable_entered_)) != 0)
+ {
+ while (true)
+ {
+ boost::cv_status status = gate2_.wait_until(lk, abs_time);
+ if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
+ break;
+ if (status == boost::cv_status::timeout)
+ return false;
+ }
+ }
+ state_ |= upgradable_entered_;
+ return true;
+ }
+
+ template <class Clock, class Duration>
+ bool
+ upgrade_mutex::try_unlock_upgrade_and_lock_until(
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if ((state_ & n_readers_) != 1)
+ {
+ while (true)
+ {
+ boost::cv_status status = gate2_.wait_until(lk, abs_time);
+ if ((state_ & n_readers_) == 1)
+ break;
+ if (status == boost::cv_status::timeout)
+ return false;
+ }
+ }
+ state_ = write_entered_;
+ return true;
+ }
+
+ //////
+ // shared_mutex
+
+ shared_mutex::shared_mutex()
+ : state_(0)
+ {
+ }
+
+ shared_mutex::~shared_mutex()
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ }
+
+ // Exclusive ownership
+
+ void
+ shared_mutex::lock()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ while (state_ & write_entered_)
+ gate1_.wait(lk);
+ state_ |= write_entered_;
+ while (state_ & n_readers_)
+ gate2_.wait(lk);
+ }
+
+ bool
+ shared_mutex::try_lock()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (state_ == 0)
+ {
+ state_ = write_entered_;
+ return true;
+ }
+ return false;
+ }
+
+ void
+ shared_mutex::unlock()
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ state_ = 0;
+ gate1_.notify_all();
+ }
+
+ // Shared ownership
+
+ void
+ shared_mutex::lock_shared()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
+ gate1_.wait(lk);
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ }
+
+ bool
+ shared_mutex::try_lock_shared()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ count_t num_readers = state_ & n_readers_;
+ if (!(state_ & write_entered_) && num_readers != n_readers_)
+ {
+ ++num_readers;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ return true;
+ }
+ return false;
+ }
+
+ void
+ shared_mutex::unlock_shared()
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ count_t num_readers = (state_ & n_readers_) - 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ if (state_ & write_entered_)
+ {
+ if (num_readers == 0)
+ gate2_.notify_one();
+ }
+ else
+ {
+ if (num_readers == n_readers_ - 1)
+ gate1_.notify_one();
+ }
+ }
+
+ // upgrade_mutex
+
+ upgrade_mutex::upgrade_mutex()
+ : gate1_(),
+ gate2_(),
+ state_(0)
+ {
+ }
+
+ upgrade_mutex::~upgrade_mutex()
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ }
+
+ // Exclusive ownership
+
+ void
+ upgrade_mutex::lock()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ while (state_ & (write_entered_ | upgradable_entered_))
+ gate1_.wait(lk);
+ state_ |= write_entered_;
+ while (state_ & n_readers_)
+ gate2_.wait(lk);
+ }
+
+ bool
+ upgrade_mutex::try_lock()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (state_ == 0)
+ {
+ state_ = write_entered_;
+ return true;
+ }
+ return false;
+ }
+
+ void
+ upgrade_mutex::unlock()
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ state_ = 0;
+ gate1_.notify_all();
+ }
+
+ // Shared ownership
+
+ void
+ upgrade_mutex::lock_shared()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
+ gate1_.wait(lk);
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ }
+
+ bool
+ upgrade_mutex::try_lock_shared()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ count_t num_readers = state_ & n_readers_;
+ if (!(state_ & write_entered_) && num_readers != n_readers_)
+ {
+ ++num_readers;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ return true;
+ }
+ return false;
+ }
+
+ void
+ upgrade_mutex::unlock_shared()
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ count_t num_readers = (state_ & n_readers_) - 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ if (state_ & write_entered_)
+ {
+ if (num_readers == 0)
+ gate2_.notify_one();
+ }
+ else
+ {
+ if (num_readers == n_readers_ - 1)
+ gate1_.notify_one();
+ }
+ }
+
+ // Upgrade ownership
+
+ void
+ upgrade_mutex::lock_upgrade()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ while ((state_ & (write_entered_ | upgradable_entered_)) ||
+ (state_ & n_readers_) == n_readers_)
+ gate1_.wait(lk);
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= upgradable_entered_ | num_readers;
+ }
+
+ bool
+ upgrade_mutex::try_lock_upgrade()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ count_t num_readers = state_ & n_readers_;
+ if (!(state_ & (write_entered_ | upgradable_entered_))
+ && num_readers != n_readers_)
+ {
+ ++num_readers;
+ state_ &= ~n_readers_;
+ state_ |= upgradable_entered_ | num_readers;
+ return true;
+ }
+ return false;
+ }
+
+ void
+ upgrade_mutex::unlock_upgrade()
+ {
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ count_t num_readers = (state_ & n_readers_) - 1;
+ state_ &= ~(upgradable_entered_ | n_readers_);
+ state_ |= num_readers;
+ }
+ gate1_.notify_all();
+ }
+
+ // Shared <-> Exclusive
+
+ bool
+ upgrade_mutex::try_unlock_shared_and_lock()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (state_ == 1)
+ {
+ state_ = write_entered_;
+ return true;
+ }
+ return false;
+ }
+
+ void
+ upgrade_mutex::unlock_and_lock_shared()
+ {
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ state_ = 1;
+ }
+ gate1_.notify_all();
+ }
+
+ // Shared <-> Upgrade
+
+ bool
+ upgrade_mutex::try_unlock_shared_and_lock_upgrade()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (!(state_ & (write_entered_ | upgradable_entered_)))
+ {
+ state_ |= upgradable_entered_;
+ return true;
+ }
+ return false;
+ }
+
+ void
+ upgrade_mutex::unlock_upgrade_and_lock_shared()
+ {
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ state_ &= ~upgradable_entered_;
+ }
+ gate1_.notify_all();
+ }
+
+ // Upgrade <-> Exclusive
+
+ void
+ upgrade_mutex::unlock_upgrade_and_lock()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ count_t num_readers = (state_ & n_readers_) - 1;
+ state_ &= ~(upgradable_entered_ | n_readers_);
+ state_ |= write_entered_ | num_readers;
+ while (state_ & n_readers_)
+ gate2_.wait(lk);
+ }
+
+ bool
+ upgrade_mutex::try_unlock_upgrade_and_lock()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (state_ == (upgradable_entered_ | 1))
+ {
+ state_ = write_entered_;
+ return true;
+ }
+ return false;
+ }
+
+ void
+ upgrade_mutex::unlock_and_lock_upgrade()
+ {
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ state_ = upgradable_entered_ | 1;
+ }
+ gate1_.notify_all();
+ }
+
+ } // thread_v2
+} // boost
+
+namespace boost {
+ //using thread_v2::shared_mutex;
+ using thread_v2::upgrade_mutex;
+ typedef thread_v2::upgrade_mutex shared_mutex;
+}
+
+#endif
diff --git a/boost/thread/v2/thread.hpp b/boost/thread/v2/thread.hpp
index d686c5fe9b..181661a34e 100644
--- a/boost/thread/v2/thread.hpp
+++ b/boost/thread/v2/thread.hpp
@@ -9,26 +9,77 @@
#include <boost/thread/detail/config.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/condition_variable.hpp>
-#include <boost/thread/locks.hpp>
+#include <boost/thread/lock_types.hpp>
namespace boost
{
namespace this_thread
{
-
+ namespace no_interruption_point
+ {
#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Clock, class Duration>
+ void sleep_until(const chrono::time_point<Clock, Duration>& t)
+ {
+ using namespace chrono;
+ mutex mut;
+ condition_variable cv;
+ unique_lock<mutex> lk(mut);
+ while (Clock::now() < t)
+ cv.wait_until(lk, t);
+ }
+
+#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
+
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
- nanoseconds ns = duration_cast<nanoseconds> (d);
- if (ns < d) ++ns;
- sleep_for(ns);
+ if (d > duration<Rep, Period>::zero())
+ {
+ duration<long double> Max = nanoseconds::max BOOST_PREVENT_MACRO_SUBSTITUTION ();
+ nanoseconds ns;
+ if (d < Max)
+ {
+ ns = duration_cast<nanoseconds>(d);
+ if (ns < d)
+ ++ns;
+ }
+ else
+ ns = nanoseconds:: max BOOST_PREVENT_MACRO_SUBSTITUTION ();
+ sleep_for(ns);
+ }
}
+ template <class Duration>
+ inline BOOST_SYMBOL_VISIBLE
+ void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
+ {
+ using namespace chrono;
+ sleep_for(t - steady_clock::now());
+ }
+#else
+ template <class Rep, class Period>
+ void sleep_for(const chrono::duration<Rep, Period>& d)
+ {
+ using namespace chrono;
+ if (d > duration<Rep, Period>::zero())
+ {
+ steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d);
+ sleep_until(c_timeout);
+ }
+ }
+
+#endif
+
+#endif
+ }
+#ifdef BOOST_THREAD_USES_CHRONO
+
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& t)
{
@@ -40,6 +91,28 @@ namespace boost
cv.wait_until(lk, t);
}
+#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
+
+ template <class Rep, class Period>
+ void sleep_for(const chrono::duration<Rep, Period>& d)
+ {
+ using namespace chrono;
+ if (d > duration<Rep, Period>::zero())
+ {
+ duration<long double> Max = nanoseconds::max BOOST_PREVENT_MACRO_SUBSTITUTION ();
+ nanoseconds ns;
+ if (d < Max)
+ {
+ ns = duration_cast<nanoseconds>(d);
+ if (ns < d)
+ ++ns;
+ }
+ else
+ ns = nanoseconds:: max BOOST_PREVENT_MACRO_SUBSTITUTION ();
+ sleep_for(ns);
+ }
+ }
+
template <class Duration>
inline BOOST_SYMBOL_VISIBLE
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
@@ -47,6 +120,19 @@ namespace boost
using namespace chrono;
sleep_for(t - steady_clock::now());
}
+#else
+ template <class Rep, class Period>
+ void sleep_for(const chrono::duration<Rep, Period>& d)
+ {
+ using namespace chrono;
+ if (d > duration<Rep, Period>::zero())
+ {
+ steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d);
+ sleep_until(c_timeout);
+ }
+ }
+
+#endif
#endif
}
diff --git a/boost/thread/win32/basic_recursive_mutex.hpp b/boost/thread/win32/basic_recursive_mutex.hpp
index eb5ec8489d..cfdfa043a3 100644
--- a/boost/thread/win32/basic_recursive_mutex.hpp
+++ b/boost/thread/win32/basic_recursive_mutex.hpp
@@ -42,7 +42,7 @@ namespace boost
mutex.destroy();
}
- bool try_lock()
+ bool try_lock() BOOST_NOEXCEPT
{
long const current_thread_id=win32::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
@@ -58,6 +58,7 @@ namespace boost
recursion_count=1;
}
}
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(::boost::system_time const& target)
{
long const current_thread_id=win32::GetCurrentThreadId();
@@ -68,6 +69,7 @@ namespace boost
{
return timed_lock(get_system_time()+timeout);
}
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
@@ -93,7 +95,7 @@ namespace boost
}
private:
- bool try_recursive_lock(long current_thread_id)
+ bool try_recursive_lock(long current_thread_id) BOOST_NOEXCEPT
{
if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id)
{
@@ -103,7 +105,7 @@ namespace boost
return false;
}
- bool try_basic_lock(long current_thread_id)
+ bool try_basic_lock(long current_thread_id) BOOST_NOEXCEPT
{
if(mutex.try_lock())
{
@@ -114,6 +116,7 @@ namespace boost
return false;
}
+#if defined BOOST_THREAD_USES_DATETIME
bool try_timed_lock(long current_thread_id,::boost::system_time const& target)
{
if(mutex.timed_lock(target))
@@ -124,6 +127,7 @@ namespace boost
}
return false;
}
+#endif
template <typename TP>
bool try_timed_lock_until(long current_thread_id,TP const& target)
{
diff --git a/boost/thread/win32/basic_timed_mutex.hpp b/boost/thread/win32/basic_timed_mutex.hpp
index 30580e7c17..d20c6589e6 100644
--- a/boost/thread/win32/basic_timed_mutex.hpp
+++ b/boost/thread/win32/basic_timed_mutex.hpp
@@ -14,7 +14,9 @@
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/thread/thread_time.hpp>
+#if defined BOOST_THREAD_USES_DATETIME
#include <boost/thread/xtime.hpp>
+#endif
#include <boost/detail/interlocked.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
@@ -58,7 +60,7 @@ namespace boost
}
- bool try_lock()
+ bool try_lock() BOOST_NOEXCEPT
{
return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}
@@ -79,8 +81,10 @@ namespace boost
do
{
- BOOST_VERIFY(win32::WaitForSingleObject(
- sem,::boost::detail::win32::infinite)==0);
+ unsigned const retval(win32::WaitForSingleObjectEx(sem, ::boost::detail::win32::infinite,0));
+ BOOST_VERIFY(0 == retval || ::boost::detail::win32::wait_abandoned == retval);
+// BOOST_VERIFY(win32::WaitForSingleObject(
+// sem,::boost::detail::win32::infinite)==0);
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
}
@@ -91,10 +95,13 @@ namespace boost
{
for(;;)
{
- long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
+ bool const was_locked=(old_count&lock_flag_value) ? true : false;
+ long const new_count=was_locked?(old_count+1):(old_count|lock_flag_value);
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
+ if(was_locked)
+ old_count=new_count;
break;
}
old_count=current;
@@ -118,6 +125,7 @@ namespace boost
}
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(::boost::system_time const& wait_until)
{
if(try_lock())
@@ -134,7 +142,7 @@ namespace boost
do
{
- if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
+ if(win32::WaitForSingleObjectEx(sem,::boost::detail::get_milliseconds_until(wait_until),0)!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
@@ -147,7 +155,6 @@ namespace boost
return true;
}
-
template<typename Duration>
bool timed_lock(Duration const& timeout)
{
@@ -158,7 +165,7 @@ namespace boost
{
return timed_lock(system_time(timeout));
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
@@ -196,9 +203,14 @@ namespace boost
do
{
- chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
+ chrono::time_point<chrono::system_clock, chrono::system_clock::duration> now = chrono::system_clock::now();
+ if (tp<=now) {
+ BOOST_INTERLOCKED_DECREMENT(&active_count);
+ return false;
+ }
+ chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-now);
- if(win32::WaitForSingleObject(sem,static_cast<unsigned long>(rel_time.count()))!=0)
+ if(win32::WaitForSingleObjectEx(sem,static_cast<unsigned long>(rel_time.count()),0)!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
diff --git a/boost/thread/win32/condition_variable.hpp b/boost/thread/win32/condition_variable.hpp
index 63f830b186..14c23ce0e2 100644
--- a/boost/thread/win32/condition_variable.hpp
+++ b/boost/thread/win32/condition_variable.hpp
@@ -6,23 +6,31 @@
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
-#include <boost/thread/mutex.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
-#include <limits.h>
-#include <boost/assert.hpp>
-#include <algorithm>
-#include <boost/thread/cv_status.hpp>
#include <boost/thread/win32/thread_data.hpp>
-#include <boost/thread/thread_time.hpp>
+#include <boost/thread/win32/thread_data.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
+#include <boost/thread/cv_status.hpp>
+#if defined BOOST_THREAD_USES_DATETIME
#include <boost/thread/xtime.hpp>
-#include <vector>
+#endif
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/thread/lock_guard.hpp>
+#include <boost/thread/lock_types.hpp>
+
+#include <boost/assert.hpp>
#include <boost/intrusive_ptr.hpp>
+
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
+#include <limits.h>
+#include <algorithm>
+#include <vector>
+
#include <boost/config/abi_prefix.hpp>
namespace boost
@@ -88,7 +96,7 @@ namespace boost
bool woken()
{
- unsigned long const woken_result=detail::win32::WaitForSingleObject(wake_sem,0);
+ unsigned long const woken_result=detail::win32::WaitForSingleObjectEx(wake_sem,0,0);
BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
return woken_result==0;
}
@@ -183,14 +191,16 @@ namespace boost
struct entry_manager
{
entry_ptr const entry;
+ boost::mutex& internal_mutex;
BOOST_THREAD_NO_COPYABLE(entry_manager)
- entry_manager(entry_ptr const& entry_):
- entry(entry_)
+ entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
+ entry(entry_), internal_mutex(mutex_)
{}
~entry_manager()
{
+ boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
entry->remove_waiter();
}
@@ -207,7 +217,7 @@ namespace boost
{
relocker<lock_type> locker(lock);
- entry_manager entry(get_wait_entry());
+ entry_manager entry(get_wait_entry(), internal_mutex);
locker.unlock();
@@ -314,6 +324,7 @@ namespace boost
}
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time)
{
return do_wait(m,abs_time);
@@ -326,7 +337,16 @@ namespace boost
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
{
- return do_wait(m,wait_duration.total_milliseconds());
+ if (wait_duration.is_pos_infinity())
+ {
+ wait(m); // or do_wait(m,detail::timeout::sentinel());
+ return true;
+ }
+ if (wait_duration.is_special())
+ {
+ return true;
+ }
+ return do_wait(m,wait_duration.total_milliseconds());
}
template<typename predicate_type>
@@ -344,7 +364,7 @@ namespace boost
{
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration>
@@ -354,7 +374,11 @@ namespace boost
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
- do_wait(lock, ceil<milliseconds>(t-Clock::now()).count());
+ chrono::time_point<Clock, Duration> now = Clock::now();
+ if (t<=now) {
+ return cv_status::timeout;
+ }
+ do_wait(lock, ceil<milliseconds>(t-now).count());
return Clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
@@ -366,6 +390,10 @@ namespace boost
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
+ if (d<=chrono::duration<Rep, Period>::zero()) {
+ return cv_status::timeout;
+ }
+
steady_clock::time_point c_now = steady_clock::now();
do_wait(lock, ceil<milliseconds>(d).count());
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
@@ -393,7 +421,7 @@ namespace boost
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
- return wait_until(lock, chrono::steady_clock::now() + d, pred);
+ return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
}
#endif
};
@@ -421,6 +449,7 @@ namespace boost
while(!pred()) wait(m);
}
+#if defined BOOST_THREAD_USES_DATETIME
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& abs_time)
{
@@ -456,6 +485,7 @@ namespace boost
{
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type, class Clock, class Duration>
@@ -465,7 +495,11 @@ namespace boost
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
- do_wait(lock, ceil<milliseconds>(t-Clock::now()).count());
+ chrono::time_point<Clock, Duration> now = Clock::now();
+ if (t<=now) {
+ return cv_status::timeout;
+ }
+ do_wait(lock, ceil<milliseconds>(t-now).count());
return Clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
@@ -477,6 +511,9 @@ namespace boost
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
+ if (d<=chrono::duration<Rep, Period>::zero()) {
+ return cv_status::timeout;
+ }
steady_clock::time_point c_now = steady_clock::now();
do_wait(lock, ceil<milliseconds>(d).count());
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
@@ -505,11 +542,12 @@ namespace boost
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
- return wait_until(lock, chrono::steady_clock::now() + d, pred);
+ return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
}
#endif
};
+ BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
}
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/win32/interlocked_read.hpp b/boost/thread/win32/interlocked_read.hpp
index 133fb6f975..2ad3fe9017 100644
--- a/boost/thread/win32/interlocked_read.hpp
+++ b/boost/thread/win32/interlocked_read.hpp
@@ -3,46 +3,43 @@
// interlocked_read_win32.hpp
//
-// (C) Copyright 2005-8 Anthony Williams
+// (C) Copyright 2005-8 Anthony Williams
+// (C) Copyright 2012 Vicente J. Botet Escriba
//
// 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/detail/interlocked.hpp>
+#include <boost/thread/detail/config.hpp>
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_MSVC
-extern "C" void _ReadWriteBarrier(void);
-#pragma intrinsic(_ReadWriteBarrier)
-
namespace boost
{
namespace detail
{
- inline long interlocked_read_acquire(long volatile* x)
+ // Since VS2005 volatile reads always acquire
+ inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
{
long const res=*x;
- _ReadWriteBarrier();
return res;
}
- inline void* interlocked_read_acquire(void* volatile* x)
+ inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
{
void* const res=*x;
- _ReadWriteBarrier();
return res;
}
- inline void interlocked_write_release(long volatile* x,long value)
+ // Since VS2005 volatile writes always release
+ inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
{
- _ReadWriteBarrier();
*x=value;
}
- inline void interlocked_write_release(void* volatile* x,void* value)
+ inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
{
- _ReadWriteBarrier();
*x=value;
}
}
@@ -54,19 +51,19 @@ namespace boost
{
namespace detail
{
- inline long interlocked_read_acquire(long volatile* x)
+ inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0);
}
- inline void* interlocked_read_acquire(void* volatile* x)
+ inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
}
- inline void interlocked_write_release(long volatile* x,long value)
+ inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
{
BOOST_INTERLOCKED_EXCHANGE(x,value);
}
- inline void interlocked_write_release(void* volatile* x,void* value)
+ inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
{
BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
}
diff --git a/boost/thread/win32/mfc_thread_init.hpp b/boost/thread/win32/mfc_thread_init.hpp
new file mode 100644
index 0000000000..e866f8949f
--- /dev/null
+++ b/boost/thread/win32/mfc_thread_init.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_THREAD_WIN32_MFC_THREAD_INIT_HPP
+#define BOOST_THREAD_WIN32_MFC_THREAD_INIT_HPP
+// 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)
+// (C) Copyright 2008 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+
+
+// check if we use MFC
+#ifdef _AFXDLL
+# if defined(_AFXEXT)
+
+// can't use ExtRawDllMain from afxdllx.h as it also defines the symbol _pRawDllMain
+extern "C"
+inline BOOL WINAPI ExtRawDllMain(HINSTANCE, DWORD dwReason, LPVOID)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ // save critical data pointers before running the constructors
+ AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
+ pModuleState->m_pClassInit = pModuleState->m_classList;
+ pModuleState->m_pFactoryInit = pModuleState->m_factoryList;
+ pModuleState->m_classList.m_pHead = NULL;
+ pModuleState->m_factoryList.m_pHead = NULL;
+ }
+ return TRUE; // ok
+}
+
+extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &ExtRawDllMain;
+
+# elif defined(_USRDLL)
+
+extern "C" BOOL WINAPI RawDllMain(HANDLE, DWORD dwReason, LPVOID);
+extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &RawDllMain;
+
+# endif
+#endif
+
+#endif
diff --git a/boost/thread/win32/mutex.hpp b/boost/thread/win32/mutex.hpp
index 85a00e29f9..01544784b5 100644
--- a/boost/thread/win32/mutex.hpp
+++ b/boost/thread/win32/mutex.hpp
@@ -8,7 +8,10 @@
#include <boost/thread/win32/basic_timed_mutex.hpp>
#include <boost/thread/exceptions.hpp>
-#include <boost/thread/locks.hpp>
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+#include <boost/thread/lock_types.hpp>
+#endif
+#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -33,8 +36,10 @@ namespace boost
destroy();
}
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
typedef unique_lock<mutex> scoped_lock;
typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
+#endif
};
typedef mutex try_mutex;
@@ -54,9 +59,11 @@ namespace boost
destroy();
}
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
+#endif
};
}
diff --git a/boost/thread/win32/once.hpp b/boost/thread/win32/once.hpp
index 3066b50bc3..24eb0f29d0 100644
--- a/boost/thread/win32/once.hpp
+++ b/boost/thread/win32/once.hpp
@@ -5,7 +5,7 @@
//
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2005 John Maddock
-// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+// (C) Copyright 2011-2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -18,6 +18,11 @@
#include <boost/detail/interlocked.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/detail/invoke.hpp>
+
+#include <boost/bind.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -31,6 +36,16 @@ namespace std
namespace boost
{
+ struct once_flag;
+ namespace detail
+ {
+ struct once_context;
+
+ inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
+ inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
+ inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
+ }
+
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
struct once_flag
@@ -39,12 +54,12 @@ namespace boost
BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
: status(0), count(0)
{}
- private:
long status;
long count;
- template<typename Function>
- friend
- void call_once(once_flag& flag,Function f);
+ private:
+ friend inline bool enter_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
+ friend inline void commit_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
+ friend inline void rollback_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
};
#define BOOST_ONCE_INIT once_flag()
@@ -59,6 +74,17 @@ namespace boost
#define BOOST_ONCE_INIT {0,0}
#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
+#if defined BOOST_THREAD_PROVIDES_INVOKE
+#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL
+#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET
+#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void>
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL
+#else
+#define BOOST_THREAD_INVOKE_RET_VOID boost::bind
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL ()
+#endif
+
namespace detail
{
#ifdef BOOST_NO_ANSI_APIS
@@ -126,103 +152,934 @@ namespace boost
{
name_once_mutex(mutex_name,flag_address);
}
-#ifdef BOOST_NO_ANSI_APIS
- return ::boost::detail::win32::CreateEventW(
-#else
- return ::boost::detail::win32::CreateEventA(
-#endif
- 0,::boost::detail::win32::manual_reset_event,
- ::boost::detail::win32::event_initially_reset,
- mutex_name);
+
+ return ::boost::detail::win32::create_event(
+ mutex_name,
+ ::boost::detail::win32::manual_reset_event,
+ ::boost::detail::win32::event_initially_reset);
}
- }
+ struct once_context {
+ long const function_complete_flag_value;
+ long const running_value;
+ bool counted;
+ detail::win32::handle_manager event_handle;
+ detail::once_char_type mutex_name[once_mutex_name_length];
+ once_context() :
+ function_complete_flag_value(0xc15730e2),
+ running_value(0x7f0725e3),
+ counted(false)
+ {
+ mutex_name[0]=0;
+ }
+ };
+ enum once_action {try_, break_, continue_};
+ inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
+ {
+ long status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,ctx.running_value,0);
+ if(!status)
+ {
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag);
+ }
+ if(ctx.event_handle)
+ {
+ ::boost::detail::win32::ResetEvent(ctx.event_handle);
+ }
+ return true;
+ }
+ return false;
+ }
+ inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
+ {
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ }
+ BOOST_INTERLOCKED_EXCHANGE(&flag.status,ctx.function_complete_flag_value);
+ if(!ctx.event_handle &&
+ (::boost::detail::interlocked_read_acquire(&flag.count)>1))
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ }
+ if(ctx.event_handle)
+ {
+ ::boost::detail::win32::SetEvent(ctx.event_handle);
+ }
+ }
+ inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
+ {
+ BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag);
+ }
+ if(ctx.event_handle)
+ {
+ ::boost::detail::win32::SetEvent(ctx.event_handle);
+ }
+ }
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
+ inline void call_once(once_flag& flag, void (*f)())
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite, 0));
+ }
+ }
+//#endif
+ template<typename Function>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, class A, class ...ArgTypes>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(A) a, BOOST_THREAD_RV_REF(ArgTypes)... args)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<A>(a)),
+ thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+#else
+#if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL)
template<typename Function>
void call_once(once_flag& flag,Function f)
{
// Try for a quick win: if the procedure has already been called
// just skip through:
- long const function_complete_flag_value=0xc15730e2;
- long const running_value=0x7f0725e3;
- long status;
- bool counted=false;
- detail::win32::handle_manager event_handle;
- detail::once_char_type mutex_name[detail::once_mutex_name_length];
- mutex_name[0]=0;
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, typename T1>
+ void call_once(once_flag& flag,Function f, T1 p1)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, typename T1, typename T2>
+ void call_once(once_flag& flag,Function f, T1 p1, T2 p2)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, typename T1, typename T2, typename T3>
+ void call_once(once_flag& flag,Function f, T1 p1, T2 p2, T3 p3)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+#elif defined BOOST_NO_CXX11_RVALUE_REFERENCES
- while((status=::boost::detail::interlocked_read_acquire(&flag.status))
- !=function_complete_flag_value)
+ template<typename Function>
+ void call_once(once_flag& flag,Function const&f)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
{
- status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0);
- if(!status)
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
{
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, typename T1>
+ void call_once(once_flag& flag,Function const&f, T1 const&p1)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, typename T1, typename T2>
+ void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, typename T1, typename T2, typename T3>
+ void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2, T3 const&p3)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
#endif
+#if 1
+#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
+ inline void call_once(once_flag& flag, void (*f)())
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
{
- if(!event_handle)
+ BOOST_TRY
{
- event_handle=detail::open_once_event(mutex_name,&flag);
+ f();
}
- if(event_handle)
+ BOOST_CATCH(...)
{
- ::boost::detail::win32::ResetEvent(event_handle);
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
}
- f();
- if(!counted)
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
{
- BOOST_INTERLOCKED_INCREMENT(&flag.count);
- counted=true;
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
}
- BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value);
- if(!event_handle &&
- (::boost::detail::interlocked_read_acquire(&flag.count)>1))
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename T1>
+ void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1)), BOOST_THREAD_RV_REF(T1) p1)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f(
+ thread_detail::decay_copy(boost::forward<T1>(p1))
+ );
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, typename T1, typename T2>
+ void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1),BOOST_THREAD_RV_REF(T2)), BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
{
- event_handle=detail::create_once_event(mutex_name,&flag);
+ f(
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T2>(p2))
+ );
}
- if(event_handle)
+ BOOST_CATCH(...)
{
- ::boost::detail::win32::SetEvent(event_handle);
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
}
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
break;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ if(!ctx.counted)
{
- BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
- if(!event_handle)
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
{
- event_handle=detail::open_once_event(mutex_name,&flag);
+ break;
}
- if(event_handle)
+ if(!ctx.event_handle)
{
- ::boost::detail::win32::SetEvent(event_handle);
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
}
- throw; // BOOST_NO_EXCEPTIONS protected
}
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, typename T1, typename T2, typename T3>
+ void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1),BOOST_THREAD_RV_REF(T2)), BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f(
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T2>(p2)),
+ thread_detail::decay_copy(boost::forward<T3>(p3))
+ );
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
#endif
+ template<typename Function>
+ void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+
+ template<typename Function, typename T1>
+ void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, typename T1, typename T2>
+ void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T2>(p2))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
}
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
+ }
+ }
+ template<typename Function, typename T1, typename T2, typename T3>
+ void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T2>(p2)),
+ thread_detail::decay_copy(boost::forward<T3>(p3))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
- if(!counted)
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
{
BOOST_INTERLOCKED_INCREMENT(&flag.count);
- counted=true;
- status=::boost::detail::interlocked_read_acquire(&flag.status);
- if(status==function_complete_flag_value)
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
{
break;
}
- if(!event_handle)
+ if(!ctx.event_handle)
{
- event_handle=detail::create_once_event(mutex_name,&flag);
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
continue;
}
}
- BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
- event_handle,::boost::detail::win32::infinite));
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
+ ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
+
+#endif
+#endif
}
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/win32/recursive_mutex.hpp b/boost/thread/win32/recursive_mutex.hpp
index 5144e77aa7..1f0f7f5e5f 100644
--- a/boost/thread/win32/recursive_mutex.hpp
+++ b/boost/thread/win32/recursive_mutex.hpp
@@ -12,7 +12,10 @@
#include <boost/thread/win32/basic_recursive_mutex.hpp>
#include <boost/thread/exceptions.hpp>
-#include <boost/thread/locks.hpp>
+#include <boost/thread/detail/delete.hpp>
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
+#include <boost/thread/lock_types.hpp>
+#endif
#include <boost/config/abi_prefix.hpp>
@@ -32,8 +35,10 @@ namespace boost
::boost::detail::basic_recursive_mutex::destroy();
}
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
typedef unique_lock<recursive_mutex> scoped_lock;
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
+#endif
};
typedef recursive_mutex recursive_try_mutex;
@@ -52,9 +57,11 @@ namespace boost
::boost::detail::basic_recursive_timed_mutex::destroy();
}
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
+#endif
};
}
diff --git a/boost/thread/win32/shared_mutex.hpp b/boost/thread/win32/shared_mutex.hpp
index fef2d5badd..fff97b7355 100644
--- a/boost/thread/win32/shared_mutex.hpp
+++ b/boost/thread/win32/shared_mutex.hpp
@@ -75,7 +75,13 @@ namespace boost
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
}
}
-
+ void release_shared_waiters(state_data old_state)
+ {
+ if(old_state.shared_waiting || old_state.exclusive_waiting)
+ {
+ BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
+ }
+ }
public:
BOOST_THREAD_NO_COPYABLE(shared_mutex)
@@ -95,7 +101,7 @@ namespace boost
detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX);
boost::throw_exception(thread_resource_error());
}
- state_data state_={0};
+ state_data state_={0,0,0,0,0,0};
state=state_;
}
@@ -133,15 +139,19 @@ namespace boost
void lock_shared()
{
+#if defined BOOST_THREAD_USES_DATETIME
BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
+#else
+ BOOST_VERIFY(try_lock_shared_until(chrono::steady_clock::now()));
+#endif
}
+#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
{
return timed_lock_shared(get_system_time()+relative_time);
}
-
bool timed_lock_shared(boost::system_time const& wait_until)
{
for(;;)
@@ -180,7 +190,7 @@ namespace boost
return true;
}
- unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until));
+ unsigned long const res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0);
if(res==detail::win32::timeout)
{
for(;;)
@@ -220,6 +230,7 @@ namespace boost
BOOST_ASSERT(res==0);
}
}
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
@@ -284,8 +295,8 @@ namespace boost
unsigned long res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n);
- res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],
- static_cast<unsigned long>(rel_time.count()));
+ res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],
+ static_cast<unsigned long>(rel_time.count()), 0);
} else {
res=detail::win32::timeout;
}
@@ -378,14 +389,20 @@ namespace boost
void lock()
{
+#if defined BOOST_THREAD_USES_DATETIME
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
+#else
+ BOOST_VERIFY(try_lock_until(chrono::steady_clock::now()));
+#endif
}
+#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
+#endif
bool try_lock()
{
@@ -413,6 +430,7 @@ namespace boost
}
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(boost::system_time const& wait_until)
{
for(;;)
@@ -454,11 +472,12 @@ namespace boost
#else
const bool wait_all = false;
#endif
- unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until));
+ unsigned long const wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0);
if(wait_res==detail::win32::timeout)
{
for(;;)
{
+ bool must_notify = false;
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
@@ -467,6 +486,7 @@ namespace boost
if(!--new_state.exclusive_waiting)
{
new_state.exclusive_waiting_blocked=false;
+ must_notify = true;
}
}
}
@@ -476,6 +496,11 @@ namespace boost
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if (must_notify)
+ {
+ BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
+ }
+
if(current_state==old_state)
{
break;
@@ -491,7 +516,7 @@ namespace boost
BOOST_ASSERT(wait_res<2);
}
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
@@ -559,8 +584,8 @@ namespace boost
unsigned long wait_res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
- wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,
- static_cast<unsigned long>(rel_time.count()));
+ wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,
+ static_cast<unsigned long>(rel_time.count()), 0);
} else {
wait_res=detail::win32::timeout;
}
@@ -568,6 +593,7 @@ namespace boost
{
for(;;)
{
+ bool must_notify = false;
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
@@ -576,6 +602,7 @@ namespace boost
if(!--new_state.exclusive_waiting)
{
new_state.exclusive_waiting_blocked=false;
+ must_notify = true;
}
}
}
@@ -585,6 +612,10 @@ namespace boost
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
+ if (must_notify)
+ {
+ BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
+ }
if(current_state==old_state)
{
break;
@@ -665,7 +696,7 @@ namespace boost
return;
}
- BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite));
+ BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],detail::win32::infinite, 0));
}
}
@@ -724,9 +755,14 @@ namespace boost
if(last_reader)
{
release_waiters(old_state);
- } else {
- release_waiters(old_state);
}
+ else {
+ release_shared_waiters(old_state);
+ }
+ // #7720
+ //else {
+ // release_waiters(old_state);
+ //}
break;
}
old_state=current_state;
@@ -752,7 +788,7 @@ namespace boost
{
if(!last_reader)
{
- BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite));
+ BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0));
}
break;
}
diff --git a/boost/thread/win32/thread_data.hpp b/boost/thread/win32/thread_data.hpp
index 5af4fd3ed3..51f6273f43 100644
--- a/boost/thread/win32/thread_data.hpp
+++ b/boost/thread/win32/thread_data.hpp
@@ -7,17 +7,33 @@
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
-#include <boost/intrusive_ptr.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/thread_heap_alloc.hpp>
+
+#include <boost/predef/platform.h>
+
+#include <boost/intrusive_ptr.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#endif
+
+#include <map>
+#include <vector>
+#include <utility>
+
#include <boost/config/abi_prefix.hpp>
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4251)
+#endif
+
namespace boost
{
+ class condition_variable;
+ class mutex;
+
class thread_attributes {
public:
thread_attributes() BOOST_NOEXCEPT {
@@ -58,32 +74,68 @@ namespace boost
namespace detail
{
+ struct shared_state_base;
+ struct tss_cleanup_function;
struct thread_exit_callback_node;
- struct tss_data_node;
+ struct tss_data_node
+ {
+ boost::shared_ptr<boost::detail::tss_cleanup_function> func;
+ void* value;
+
+ tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
+ void* value_):
+ func(func_),value(value_)
+ {}
+ };
struct thread_data_base;
void intrusive_ptr_add_ref(thread_data_base * p);
void intrusive_ptr_release(thread_data_base * p);
- struct BOOST_SYMBOL_VISIBLE thread_data_base
+ struct BOOST_THREAD_DECL thread_data_base
{
long count;
+
+ // Win32 threading APIs are not available in store apps so
+ // use abstraction on top of Windows::System::Threading.
+#if BOOST_PLAT_WINDOWS_RUNTIME
+ detail::win32::scoped_winrt_thread thread_handle;
+#else
detail::win32::handle_manager thread_handle;
- detail::win32::handle_manager interruption_handle;
+#endif
+
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
- boost::detail::tss_data_node* tss_data;
- bool interruption_enabled;
unsigned id;
+ std::map<void const*,boost::detail::tss_data_node> tss_data;
+ typedef std::vector<std::pair<condition_variable*, mutex*>
+ //, hidden_allocator<std::pair<condition_variable*, mutex*> >
+ > notify_list_t;
+ notify_list_t notify;
+
+ typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
+ async_states_t async_states_;
+//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ // These data must be at the end so that the access to the other fields doesn't change
+ // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined
+ // Another option is to have them always
+ detail::win32::handle_manager interruption_handle;
+ bool interruption_enabled;
+//#endif
thread_data_base():
- count(0),thread_handle(detail::win32::invalid_handle_value),
- interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)),
- thread_exit_callbacks(0),tss_data(0),
- interruption_enabled(true),
- id(0)
- {}
- virtual ~thread_data_base()
+ count(0),
+ thread_handle(),
+ thread_exit_callbacks(0),
+ id(0),
+ tss_data(),
+ notify(),
+ async_states_()
+//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ , interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset))
+ , interruption_enabled(true)
+//#endif
{}
+ virtual ~thread_data_base();
friend void intrusive_ptr_add_ref(thread_data_base * p)
{
@@ -98,21 +150,34 @@ namespace boost
}
}
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
void interrupt()
{
BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
}
-
+#endif
typedef detail::win32::handle native_handle_type;
virtual void run()=0;
+
+ virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
+ {
+ notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
+ }
+
+ void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
+ {
+ async_states_.push_back(as);
+ }
+
};
+ BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
struct BOOST_SYMBOL_VISIBLE timeout
{
- unsigned long start;
+ win32::ticks_type start;
uintmax_t milliseconds;
bool relative;
boost::system_time abs_time;
@@ -120,14 +185,15 @@ namespace boost
static unsigned long const max_non_infinite_wait=0xfffffffe;
timeout(uintmax_t milliseconds_):
- start(win32::GetTickCount()),
+ start(win32::GetTickCount64_()()),
milliseconds(milliseconds_),
- relative(true),
- abs_time(boost::get_system_time())
+ relative(true)
+ //,
+ // abs_time(boost::get_system_time())
{}
timeout(boost::system_time const& abs_time_):
- start(win32::GetTickCount()),
+ start(win32::GetTickCount64_()()),
milliseconds(0),
relative(false),
abs_time(abs_time_)
@@ -152,8 +218,8 @@ namespace boost
}
else if(relative)
{
- unsigned long const now=win32::GetTickCount();
- unsigned long const elapsed=now-start;
+ win32::ticks_type const now=win32::GetTickCount64_()();
+ win32::ticks_type const elapsed=now-start;
return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
}
else
@@ -205,7 +271,6 @@ namespace boost
{
interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}
-
template<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
@@ -221,10 +286,41 @@ namespace boost
interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
}
#endif
+ namespace no_interruption_point
+ {
+ bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
+ inline void non_interruptible_wait(uintmax_t milliseconds)
+ {
+ non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
+ }
+ inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time)
+ {
+ non_interruptible_wait(detail::win32::invalid_handle_value,abs_time);
+ }
+ template<typename TimeDuration>
+ inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
+ {
+ non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
+ }
+ inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
+ {
+ non_interruptible_wait(abs_time);
+ }
+#ifdef BOOST_THREAD_USES_CHRONO
+ inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
+ {
+ non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
+ }
+#endif
+ }
}
}
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
#include <boost/config/abi_suffix.hpp>
#endif
diff --git a/boost/thread/win32/thread_heap_alloc.hpp b/boost/thread/win32/thread_heap_alloc.hpp
index 843e46b532..610fe3263e 100644
--- a/boost/thread/win32/thread_heap_alloc.hpp
+++ b/boost/thread/win32/thread_heap_alloc.hpp
@@ -5,10 +5,12 @@
#ifndef THREAD_HEAP_ALLOC_HPP
#define THREAD_HEAP_ALLOC_HPP
#include <new>
+#include <boost/thread/detail/config.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
+#include <boost/core/no_exceptions_support.hpp>
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
@@ -75,180 +77,153 @@ namespace boost
inline T* heap_new()
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
-#endif
+ BOOST_TRY
{
T* const data=new (heap_memory) T();
return data;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
- throw; // BOOST_NO_EXCEPTIONS protected
+ BOOST_RETHROW
}
-#endif
+ BOOST_CATCH_END
}
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
-#endif
+ BOOST_TRY
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1));
return data;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
- throw; // BOOST_NO_EXCEPTIONS protected
+ BOOST_RETHROW
}
-#endif
+ BOOST_CATCH_END
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1&& a1,A2&& a2)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
-#endif
+ BOOST_TRY
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2));
return data;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
- throw; // BOOST_NO_EXCEPTIONS protected
+ BOOST_RETHROW
}
-#endif
+ BOOST_CATCH_END
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
-#endif
+ BOOST_TRY
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3));
return data;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
- throw; // BOOST_NO_EXCEPTIONS protected
+ BOOST_RETHROW
}
-#endif
+ BOOST_CATCH_END
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
-#endif
+ BOOST_TRY
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3),static_cast<A4&&>(a4));
return data;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
- throw; // BOOST_NO_EXCEPTIONS protected
+ BOOST_RETHROW
}
-#endif
+ BOOST_CATCH_END
}
#else
template<typename T,typename A1>
inline T* heap_new_impl(A1 a1)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
-#endif
+ BOOST_TRY
{
T* const data=new (heap_memory) T(a1);
return data;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
- throw; // BOOST_NO_EXCEPTIONS protected
+ BOOST_RETHROW
}
-#endif
+ BOOST_CATCH_END
}
template<typename T,typename A1,typename A2>
inline T* heap_new_impl(A1 a1,A2 a2)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
-#endif
+ BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2);
return data;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
- throw; // BOOST_NO_EXCEPTIONS protected
+ BOOST_RETHROW
}
-#endif
+ BOOST_CATCH_END
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
-#endif
+ BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2,a3);
return data;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
- throw; // BOOST_NO_EXCEPTIONS protected
+ BOOST_RETHROW
}
-#endif
+ BOOST_CATCH_END
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
-#endif
+ BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2,a3,a4);
return data;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
- throw; // BOOST_NO_EXCEPTIONS protected
+ BOOST_RETHROW
}
-#endif
+ BOOST_CATCH_END
}
diff --git a/boost/thread/win32/thread_primitives.hpp b/boost/thread/win32/thread_primitives.hpp
index 294e42ee9b..2960822f65 100644
--- a/boost/thread/win32/thread_primitives.hpp
+++ b/boost/thread/win32/thread_primitives.hpp
@@ -10,13 +10,19 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/config.hpp>
+#include <boost/thread/detail/config.hpp>
+#include <boost/predef/platform.h>
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/detail/interlocked.hpp>
+//#include <boost/detail/winapi/synchronization.hpp>
#include <algorithm>
+#if BOOST_PLAT_WINDOWS_RUNTIME
+#include <thread>
+#endif
+
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
@@ -26,41 +32,61 @@ namespace boost
{
namespace win32
{
- typedef ULONG_PTR ulong_ptr;
typedef HANDLE handle;
+ typedef SYSTEM_INFO system_info;
+ typedef unsigned __int64 ticks_type;
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;
+ unsigned const create_event_initial_set = 0x00000002;
+ unsigned const create_event_manual_reset = 0x00000001;
+ unsigned const event_all_access = EVENT_ALL_ACCESS;
+ unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS;
+
# ifdef BOOST_NO_ANSI_APIS
+# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
using ::CreateMutexW;
using ::CreateEventW;
- using ::OpenEventW;
using ::CreateSemaphoreW;
# else
+ using ::CreateMutexExW;
+ using ::CreateEventExW;
+ using ::CreateSemaphoreExW;
+# endif
+ using ::OpenEventW;
+# else
using ::CreateMutexA;
using ::CreateEventA;
using ::OpenEventA;
using ::CreateSemaphoreA;
# endif
+#if BOOST_PLAT_WINDOWS_RUNTIME
+ using ::GetNativeSystemInfo;
+ using ::GetTickCount64;
+#else
+ using ::GetSystemInfo;
+#endif
using ::CloseHandle;
using ::ReleaseMutex;
using ::ReleaseSemaphore;
using ::SetEvent;
using ::ResetEvent;
- using ::WaitForMultipleObjects;
- using ::WaitForSingleObject;
+ using ::WaitForMultipleObjectsEx;
+ using ::WaitForSingleObjectEx;
using ::GetCurrentProcessId;
using ::GetCurrentThreadId;
using ::GetCurrentThread;
using ::GetCurrentProcess;
using ::DuplicateHandle;
+#if !BOOST_PLAT_WINDOWS_RUNTIME
using ::SleepEx;
using ::Sleep;
using ::QueueUserAPC;
- using ::GetTickCount;
+#endif
}
}
}
@@ -81,39 +107,58 @@ extern "C" {
typedef int BOOL;
typedef unsigned long DWORD;
typedef void* HANDLE;
-
# include <kfuncs.h>
# ifdef __cplusplus
}
# endif
# endif
+# ifdef __cplusplus
+extern "C" {
+# endif
+struct _SYSTEM_INFO;
+# ifdef __cplusplus
+}
+#endif
+
namespace boost
{
namespace detail
{
namespace win32
{
-
# ifdef _WIN64
typedef unsigned __int64 ulong_ptr;
# else
typedef unsigned long ulong_ptr;
# endif
typedef void* handle;
+ typedef _SYSTEM_INFO system_info;
+ typedef unsigned __int64 ticks_type;
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;
+ unsigned const wait_abandoned=0x00000080u;
+ unsigned const create_event_initial_set = 0x00000002;
+ unsigned const create_event_manual_reset = 0x00000001;
+ unsigned const event_all_access = 0x1F0003;
+ unsigned const semaphore_all_access = 0x1F0003;
extern "C"
{
struct _SECURITY_ATTRIBUTES;
# ifdef BOOST_NO_ANSI_APIS
+# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
__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*);
+# else
+ __declspec(dllimport) void* __stdcall CreateMutexExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
+ __declspec(dllimport) void* __stdcall CreateEventExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
+ __declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long);
+# endif
__declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
# else
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
@@ -121,18 +166,24 @@ namespace boost
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
__declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
# endif
+#if BOOST_PLAT_WINDOWS_RUNTIME
+ __declspec(dllimport) void __stdcall GetNativeSystemInfo(_SYSTEM_INFO*);
+ __declspec(dllimport) ticks_type __stdcall GetTickCount64();
+#else
+ __declspec(dllimport) void __stdcall GetSystemInfo(_SYSTEM_INFO*);
+#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) unsigned long __stdcall WaitForSingleObjectEx(void*,unsigned long,int);
+ __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjectsEx(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds,int bAlertable);
__declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
__declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
+#if !BOOST_PLAT_WINDOWS_RUNTIME
__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();
+#endif
# ifndef UNDER_CE
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
@@ -165,6 +216,103 @@ namespace boost
{
namespace win32
{
+ namespace detail { typedef int (__stdcall *farproc_t)(); typedef ticks_type (__stdcall *gettickcount64_t)(); }
+#if !BOOST_PLAT_WINDOWS_RUNTIME
+ 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
+ __declspec(dllimport) unsigned long __stdcall GetTickCount();
+#ifdef _MSC_VER
+ long _InterlockedCompareExchange(long volatile *, long, long);
+#pragma intrinsic(_InterlockedCompareExchange)
+#elif defined(__MINGW64_VERSION_MAJOR)
+ long _InterlockedCompareExchange(long volatile *, long, long);
+#else
+ // Mingw doesn't provide intrinsics
+#define _InterlockedCompareExchange InterlockedCompareExchange
+#endif
+ }
+ // 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;
+ }
+#else
+#endif
+ inline detail::gettickcount64_t GetTickCount64_()
+ {
+ static detail::gettickcount64_t gettickcount64impl;
+ if(gettickcount64impl)
+ return gettickcount64impl;
+
+ // GetTickCount and GetModuleHandle are not allowed in the Windows Runtime,
+ // and kernel32 isn't used in Windows Phone.
+#if BOOST_PLAT_WINDOWS_RUNTIME
+ gettickcount64impl = &GetTickCount64;
+#else
+ 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;
+#endif
+ return gettickcount64impl;
+ }
+
enum event_type
{
auto_reset_event=false,
@@ -177,13 +325,32 @@ namespace boost
event_initially_set=true
};
- inline handle create_anonymous_event(event_type type,initial_event_state state)
+ inline handle create_event(
+#if !defined(BOOST_NO_ANSI_APIS)
+ const char *mutex_name,
+#else
+ const wchar_t *mutex_name,
+#endif
+ event_type type,
+ initial_event_state state)
{
#if !defined(BOOST_NO_ANSI_APIS)
- handle const res=win32::CreateEventA(0,type,state,0);
+ handle const res = win32::CreateEventA(0, type, state, mutex_name);
+#elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
+ handle const res = win32::CreateEventW(0, type, state, mutex_name);
#else
- handle const res=win32::CreateEventW(0,type,state,0);
+ handle const res = win32::CreateEventExW(
+ 0,
+ mutex_name,
+ type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0,
+ event_all_access);
#endif
+ return res;
+ }
+
+ inline handle create_anonymous_event(event_type type,initial_event_state state)
+ {
+ handle const res = create_event(0, type, state);
if(!res)
{
boost::throw_exception(thread_resource_error());
@@ -191,28 +358,29 @@ namespace boost
return res;
}
- inline handle create_anonymous_semaphore(long initial_count,long max_count)
+ inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
{
#if !defined(BOOST_NO_ANSI_APIS)
- handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
+ handle const res=win32::CreateSemaphoreA(0,initial_count,max_count,0);
#else
- handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
+#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
+ handle const res=win32::CreateSemaphoreEx(0,initial_count,max_count,0,0);
+#else
+ handle const res=win32::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
+#endif
#endif
+ return res;
+ }
+
+ inline handle create_anonymous_semaphore(long initial_count,long max_count)
+ {
+ handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count);
if(!res)
{
boost::throw_exception(thread_resource_error());
}
return res;
}
- inline handle create_anonymous_semaphore_nothrow(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
- return res;
- }
inline handle duplicate_handle(handle source)
{
@@ -231,8 +399,65 @@ namespace boost
{
BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
}
+
+ inline void get_system_info(system_info *info)
+ {
+#if BOOST_PLAT_WINDOWS_RUNTIME
+ win32::GetNativeSystemInfo(info);
+#else
+ win32::GetSystemInfo(info);
+#endif
+ }
+
+ inline void sleep(unsigned long milliseconds)
+ {
+ if(milliseconds == 0)
+ {
+#if BOOST_PLAT_WINDOWS_RUNTIME
+ std::this_thread::yield();
+#else
+ ::boost::detail::win32::Sleep(0);
+#endif
+ }
+ else
+ {
+#if BOOST_PLAT_WINDOWS_RUNTIME
+ ::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0);
+#else
+ ::boost::detail::win32::Sleep(milliseconds);
+#endif
+ }
+ }
+
+#if BOOST_PLAT_WINDOWS_RUNTIME
+ class BOOST_THREAD_DECL scoped_winrt_thread
+ {
+ public:
+ scoped_winrt_thread() : m_completionHandle(invalid_handle_value)
+ {}
+
+ ~scoped_winrt_thread()
+ {
+ if (m_completionHandle != ::boost::detail::win32::invalid_handle_value)
+ {
+ CloseHandle(m_completionHandle);
+ }
+ }
+
+ typedef unsigned(__stdcall * thread_func)(void *);
+ bool start(thread_func address, void *parameter, unsigned int *thrdId);
+
+ handle waitable_handle() const
+ {
+ BOOST_ASSERT(m_completionHandle != ::boost::detail::win32::invalid_handle_value);
+ return m_completionHandle;
+ }
- class handle_manager
+ private:
+ handle m_completionHandle;
+ };
+#endif
+ class BOOST_THREAD_DECL handle_manager
{
private:
handle handle_to_manage;
@@ -294,7 +519,6 @@ namespace boost
cleanup();
}
};
-
}
}
}
@@ -341,7 +565,7 @@ namespace boost
{
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
-#if 0
+#ifndef BOOST_INTEL_CXX_VERSION
__asm {
mov eax,bit;
mov edx,x;
@@ -351,7 +575,11 @@ namespace boost
#else
bool ret;
__asm {
- mov eax,bit; mov edx,x; lock bts [edx],eax; setc al; mov ret, al
+ mov eax,bit
+ mov edx,x
+ lock bts [edx],eax
+ setc al
+ mov ret, al
};
return ret;
@@ -360,7 +588,7 @@ namespace boost
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
-#if 0
+#ifndef BOOST_INTEL_CXX_VERSION
__asm {
mov eax,bit;
mov edx,x;
@@ -368,11 +596,13 @@ namespace boost
setc al;
};
#else
-
-
bool ret;
__asm {
- mov eax,bit; mov edx,x; lock btr [edx],eax; setc al; mov ret, al
+ mov eax,bit
+ mov edx,x
+ lock btr [edx],eax
+ setc al
+ mov ret, al
};
return ret;
diff --git a/boost/thread/with_lock_guard.hpp b/boost/thread/with_lock_guard.hpp
new file mode 100644
index 0000000000..5d99b36f2e
--- /dev/null
+++ b/boost/thread/with_lock_guard.hpp
@@ -0,0 +1,234 @@
+// (C) Copyright 2013 Ruslan Baratov
+// Copyright (C) 2014 Vicente J. Botet Escriba
+//
+// 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)
+
+// See www.boost.org/libs/thread for documentation.
+
+#ifndef BOOST_THREAD_WITH_LOCK_GUARD_HPP
+#define BOOST_THREAD_WITH_LOCK_GUARD_HPP
+
+#include <boost/thread/lock_guard.hpp>
+#include <boost/utility/result_of.hpp>
+//#include <boost/thread/detail/invoke.hpp>
+
+namespace boost {
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_DECLTYPE) && \
+ !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
+
+/**
+ * Utility to run functions in scope protected by mutex.
+ *
+ * Examples:
+ *
+ * int func(int, int&);
+ * boost::mutex m;
+ * int a;
+ * int result = boost::with_lock_guard(m, func, 1, boost::ref(a));
+ *
+ * // using boost::bind
+ * int result = boost::with_lock_guard(
+ * m, boost::bind(func, 2, boost::ref(a))
+ * );
+ *
+ * // using lambda
+ * int a;
+ * int result = boost::with_lock_guard(
+ * m,
+ * [&a](int x) {
+ * a = 3;
+ * return x + 4;
+ * },
+ * 5
+ * );
+ */
+template <class Lockable, class Function, class... Args>
+typename boost::result_of<Function(Args...)>::type with_lock_guard(
+ Lockable& m,
+ BOOST_FWD_REF(Function) func,
+ BOOST_FWD_REF(Args)... args
+) //-> decltype(func(boost::forward<Args>(args)...))
+{
+ boost::lock_guard<Lockable> lock(m);
+ return func(boost::forward<Args>(args)...);
+}
+
+#else
+
+// Workaround versions for compilers without c++11 variadic templates support.
+// (function arguments limit: 4)
+// (for lambda support define BOOST_RESULT_OF_USE_DECLTYPE may be needed)
+
+template <class Lockable, class Func>
+typename boost::result_of<Func()>::type with_lock_guard(
+ Lockable& m,
+ BOOST_FWD_REF(Func) func
+) {
+ boost::lock_guard<Lockable> lock(m);
+ return func();
+}
+
+template <class Lockable, class Func, class Arg>
+typename boost::result_of<Func(Arg)>::type with_lock_guard(
+ Lockable& m,
+ BOOST_FWD_REF(Func) func,
+ BOOST_FWD_REF(Arg) arg
+) {
+ boost::lock_guard<Lockable> lock(m);
+ return func(
+ boost::forward<Arg>(arg)
+ );
+}
+
+template <class Lockable, class Func, class Arg1, class Arg2>
+typename boost::result_of<Func(Arg1, Arg2)>::type with_lock_guard(
+ Lockable& m,
+ BOOST_FWD_REF(Func) func,
+ BOOST_FWD_REF(Arg1) arg1,
+ BOOST_FWD_REF(Arg2) arg2
+) {
+ boost::lock_guard<Lockable> lock(m);
+ return func(
+ boost::forward<Arg1>(arg1),
+ boost::forward<Arg2>(arg2)
+ );
+}
+
+template <class Lockable, class Func, class Arg1, class Arg2, class Arg3>
+typename boost::result_of<Func(Arg1, Arg2, Arg3)>::type with_lock_guard(
+ Lockable& m,
+ BOOST_FWD_REF(Func) func,
+ BOOST_FWD_REF(Arg1) arg1,
+ BOOST_FWD_REF(Arg2) arg2,
+ BOOST_FWD_REF(Arg3) arg3
+) {
+ boost::lock_guard<Lockable> lock(m);
+ return func(
+ boost::forward<Arg1>(arg1),
+ boost::forward<Arg2>(arg2),
+ boost::forward<Arg3>(arg3)
+ );
+}
+
+template <
+ class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4
+>
+typename boost::result_of<Func(Arg1, Arg2, Arg3, Arg4)>::type with_lock_guard(
+ Lockable& m,
+ BOOST_FWD_REF(Func) func,
+ BOOST_FWD_REF(Arg1) arg1,
+ BOOST_FWD_REF(Arg2) arg2,
+ BOOST_FWD_REF(Arg3) arg3,
+ BOOST_FWD_REF(Arg4) arg4
+) {
+ boost::lock_guard<Lockable> lock(m);
+ return func(
+ boost::forward<Arg1>(arg1),
+ boost::forward<Arg2>(arg2),
+ boost::forward<Arg3>(arg3),
+ boost::forward<Arg4>(arg4)
+ );
+}
+
+// overloads for function pointer
+// (if argument is not function pointer, static assert will trigger)
+template <class Lockable, class Func>
+typename boost::result_of<
+ typename boost::add_pointer<Func>::type()
+>::type with_lock_guard(
+ Lockable& m,
+ Func* func
+) {
+ BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
+
+ boost::lock_guard<Lockable> lock(m);
+ return func();
+}
+
+template <class Lockable, class Func, class Arg>
+typename boost::result_of<
+ typename boost::add_pointer<Func>::type(Arg)
+>::type with_lock_guard(
+ Lockable& m,
+ Func* func,
+ BOOST_FWD_REF(Arg) arg
+) {
+ BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
+
+ boost::lock_guard<Lockable> lock(m);
+ return func(
+ boost::forward<Arg>(arg)
+ );
+}
+
+template <class Lockable, class Func, class Arg1, class Arg2>
+typename boost::result_of<
+ typename boost::add_pointer<Func>::type(Arg1, Arg2)
+>::type with_lock_guard(
+ Lockable& m,
+ Func* func,
+ BOOST_FWD_REF(Arg1) arg1,
+ BOOST_FWD_REF(Arg2) arg2
+) {
+ BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
+
+ boost::lock_guard<Lockable> lock(m);
+ return func(
+ boost::forward<Arg1>(arg1),
+ boost::forward<Arg2>(arg2)
+ );
+}
+
+template <class Lockable, class Func, class Arg1, class Arg2, class Arg3>
+typename boost::result_of<
+ typename boost::add_pointer<Func>::type(Arg1, Arg2, Arg3)
+>::type with_lock_guard(
+ Lockable& m,
+ Func* func,
+ BOOST_FWD_REF(Arg1) arg1,
+ BOOST_FWD_REF(Arg2) arg2,
+ BOOST_FWD_REF(Arg3) arg3
+) {
+ BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
+
+ boost::lock_guard<Lockable> lock(m);
+ return func(
+ boost::forward<Arg1>(arg1),
+ boost::forward<Arg2>(arg2),
+ boost::forward<Arg3>(arg3)
+ );
+}
+
+template <
+ class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4
+>
+typename boost::result_of<
+ typename boost::add_pointer<Func>::type(Arg1, Arg2, Arg3, Arg4)
+>::type with_lock_guard(
+ Lockable& m,
+ Func* func,
+ BOOST_FWD_REF(Arg1) arg1,
+ BOOST_FWD_REF(Arg2) arg2,
+ BOOST_FWD_REF(Arg3) arg3,
+ BOOST_FWD_REF(Arg4) arg4
+) {
+ BOOST_STATIC_ASSERT(boost::is_function<Func>::value);
+
+ boost::lock_guard<Lockable> lock(m);
+ return func(
+ boost::forward<Arg1>(arg1),
+ boost::forward<Arg2>(arg2),
+ boost::forward<Arg3>(arg3),
+ boost::forward<Arg4>(arg4)
+ );
+}
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_THREAD_WITH_LOCK_GUARD_HPP
+
diff --git a/boost/thread/xtime.hpp b/boost/thread/xtime.hpp
index 1ca996fa0c..9c6a359640 100644
--- a/boost/thread/xtime.hpp
+++ b/boost/thread/xtime.hpp
@@ -9,6 +9,7 @@
#define BOOST_XTIME_WEK070601_HPP
#include <boost/thread/detail/config.hpp>
+#if defined BOOST_THREAD_USES_DATETIME
#include <boost/cstdint.hpp>
#include <boost/thread/thread_time.hpp>
@@ -88,5 +89,5 @@ inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
} // namespace boost
#include <boost/config/abi_suffix.hpp>
-
+#endif
#endif //BOOST_XTIME_WEK070601_HPP