diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2016-03-31 15:09:29 -0400 |
---|---|---|
committer | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2016-03-31 15:09:29 -0400 |
commit | 869912de45bfec53f8fd15c4f716b49ac2ca7aa4 (patch) | |
tree | 97934f62054ebb1f1c78812196f7c7bded1fc1b3 /src/third_party/boost-1.60.0/boost/thread | |
parent | 319e895cc28b4aade6fa843583e0fd2ea96cd7a0 (diff) | |
download | mongo-869912de45bfec53f8fd15c4f716b49ac2ca7aa4.tar.gz |
SERVER-17294 Boost 1.60
Diffstat (limited to 'src/third_party/boost-1.60.0/boost/thread')
161 files changed, 37372 insertions, 0 deletions
diff --git a/src/third_party/boost-1.60.0/boost/thread/barrier.hpp b/src/third_party/boost-1.60.0/boost/thread/barrier.hpp new file mode 100644 index 00000000000..47daf07b352 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/barrier.hpp @@ -0,0 +1,254 @@ +// 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) + +#ifndef BOOST_BARRIER_JDM030602_HPP +#define BOOST_BARRIER_JDM030602_HPP + +#include <boost/thread/detail/config.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) + {} + + 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 + { + 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 + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/caller_context.hpp b/src/third_party/boost-1.60.0/boost/thread/caller_context.hpp new file mode 100644 index 00000000000..dc50a05f975 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/caller_context.hpp @@ -0,0 +1,59 @@ +// (C) Copyright 2013,2015 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 <boost/io/ios_state.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 << std::setw(50) << ctx.filename << "[" + << std::setw(4) << std::right << std::dec<< ctx.lineno << "] "; +#if defined BOOST_THREAD_USES_LOG_CURRENT_FUNCTION + os << ctx.func << " " ; +#endif + } + return os; + } +} + +#include <boost/config/abi_suffix.hpp> + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/completion_latch.hpp b/src/third_party/boost-1.60.0/boost/thread/completion_latch.hpp new file mode 100644 index 00000000000..ea76474276c --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_adaptor.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_adaptor.hpp new file mode 100644 index 00000000000..a8f45f863f4 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_adaptor.hpp @@ -0,0 +1,209 @@ +#ifndef BOOST_THREAD_CONCURRENT_DEQUE_ADAPTOR_HPP +#define BOOST_THREAD_CONCURRENT_DEQUE_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/deque_base.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + + template <typename Queue> + class deque_adaptor_copyable_only : + public boost::deque_base<typename Queue::value_type, typename Queue::size_type> + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + deque_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 deque_adaptor_movable_only : + public boost::deque_base<typename Queue::value_type, typename Queue::size_type> + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + + deque_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 deque_adaptor_copyable_and_movable : + public boost::deque_base<typename Queue::value_type, typename Queue::size_type> + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + + deque_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__ && ! defined __clang__ +#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 deque_adaptor; + + template <class Q, class T> + struct deque_adaptor<Q, T, true, true> { + typedef deque_adaptor_copyable_and_movable<Q> type; + }; + template <class Q, class T> + struct deque_adaptor<Q, T, true, false> { + typedef deque_adaptor_copyable_only<Q> type; + }; + template <class Q, class T> + struct deque_adaptor<Q, T, false, true> { + typedef deque_adaptor_movable_only<Q> type; + }; + +} + + template <typename Queue> + class deque_adaptor : + public detail::deque_adaptor<Queue, typename Queue::value_type>::type + { + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + // Constructors/Assignment/Destructors + virtual ~deque_adaptor() {}; + }; +} +using concurrent::deque_adaptor; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_base.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_base.hpp new file mode 100644 index 00000000000..f76e8a761dd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_base.hpp @@ -0,0 +1,202 @@ +#ifndef BOOST_THREAD_CONCURRENT_DEQUE_BASE_HPP +#define BOOST_THREAD_CONCURRENT_DEQUE_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 SizeType> + class deque_base_copyable_only + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + + // Constructors/Assignment/Destructors + virtual ~deque_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(value_type& elem) = 0; + + }; + + template <typename ValueType, class SizeType> + class deque_base_movable_only + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + // Constructors/Assignment/Destructors + virtual ~deque_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(value_type& 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 SizeType> + class deque_base_copyable_and_movable + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + // Constructors/Assignment/Destructors + virtual ~deque_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(value_type& 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, class ST, +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES +#if defined __GNUC__ && ! defined __clang__ +#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 deque_base; + + template <class T, class ST> + struct deque_base<T, ST, true, true> { + typedef deque_base_copyable_and_movable<T, ST> type; + }; + template <class T, class ST> + struct deque_base<T, ST, true, false> { + typedef deque_base_copyable_only<T, ST> type; + }; + template <class T, class ST> + struct deque_base<T, ST, false, true> { + typedef deque_base_movable_only<T, ST> type; + }; + +} + + template <class ValueType, class SizeType=std::size_t> + class deque_base : + public detail::deque_base<ValueType, SizeType>::type + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + // Constructors/Assignment/Destructors + virtual ~deque_base() {}; + }; + +} +using concurrent::deque_base; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_views.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_views.hpp new file mode 100644 index 00000000000..5715fb88cff --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_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/deque_base.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +namespace concurrent +{ + + template <typename Queue> + class deque_back_view + { + Queue* queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + deque_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 deque_front_view + { + Queue* queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + deque_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 deque_back = deque_back_view<deque_base<T> > ; + template <class T> + using deque_front = deque_front_view<deque_base<T> > ; + +#else + + template <class T> + struct deque_back : deque_back_view<deque_base<T> > + { + typedef deque_back_view<deque_base<T> > base_type; + deque_back(deque_base<T>& q) BOOST_NOEXCEPT : base_type(q) {} + }; + template <class T> + struct deque_front : deque_front_view<deque_base<T> > + { + typedef deque_front_view<deque_base<T> > base_type; + deque_front(deque_base<T>& q) BOOST_NOEXCEPT : base_type(q) {} + + }; + +#endif + +// template <class Queue> +// deque_back_view<Queue> back(Queue & q) { return deque_back_view<Queue>(q); } +// template <class Queue> +// deque_front_view<Queue> front(Queue & q) { return deque_front_view<Queue>(q); } +//#if 0 +// template <class T> +// deque_back<T> back(deque_base<T> & q) { return deque_back<T>(q); } +// template <class T> +// deque_front<T> front(deque_base<T> & q) { return deque_front<T>(q); } +//#else +// template <class T> +// typename deque_back<T>::type back(deque_base<T> & q) { return typename deque_back<T>::type(q); } +// template <class T> +// typename deque_front<T>::type front(deque_base<T> & q) { return typename deque_front<T>::type(q); } +//#endif +} + +using concurrent::deque_back_view; +using concurrent::deque_front_view; +using concurrent::deque_back; +using concurrent::deque_front; +//using concurrent::back; +//using concurrent::front; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_deque_base.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_deque_base.hpp new file mode 100644 index 00000000000..877e1e2eb40 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_deque_base.hpp @@ -0,0 +1,223 @@ +#ifndef BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_DEQUE_BASE_HPP +#define BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_DEQUE_BASE_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/detail/move.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/concurrent_queues/queue_op_status.hpp> + +#include <boost/chrono/duration.hpp> +#include <boost/chrono/time_point.hpp> +#include <boost/chrono/system_clocks.hpp> +#include <boost/throw_exception.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + + template <class ValueType, class Queue> + class sync_deque_base + { + public: + typedef ValueType value_type; + typedef Queue underlying_queue_type; + typedef typename Queue::size_type size_type; + typedef queue_op_status op_status; + + typedef typename chrono::steady_clock clock; + typedef typename clock::duration duration; + typedef typename clock::time_point time_point; + + // Constructors/Assignment/Destructors + BOOST_THREAD_NO_COPYABLE(sync_deque_base) + inline sync_deque_base(); + //template <typename Range> + //inline explicit sync_deque(Range range); + inline ~sync_deque_base(); + + // Observers + inline bool empty() const; + inline bool full() const; + inline size_type size() const; + inline bool closed() const; + + // Modifiers + inline void close(); + + inline underlying_queue_type underlying_queue() { + lock_guard<mutex> lk(mtx_); + return boost::move(data_); + } + + protected: + mutable mutex mtx_; + condition_variable not_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 bool closed(unique_lock<mutex>& lk) const; + inline bool closed(lock_guard<mutex>& lk) const; + + inline void throw_if_closed(unique_lock<mutex>&); + inline void throw_if_closed(lock_guard<mutex>&); + + inline void wait_until_not_empty(unique_lock<mutex>& lk); + inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk); + inline queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&); + + inline void notify_not_empty_if_needed(unique_lock<mutex>& ) + { + not_empty_.notify_one(); + } + inline void notify_not_empty_if_needed(lock_guard<mutex>& ) + { + not_empty_.notify_one(); + } + + }; + + template <class ValueType, class Queue> + sync_deque_base<ValueType, Queue>::sync_deque_base() : + data_(), closed_(false) + { + BOOST_ASSERT(data_.empty()); + } + + template <class ValueType, class Queue> + sync_deque_base<ValueType, Queue>::~sync_deque_base() + { + } + + template <class ValueType, class Queue> + void sync_deque_base<ValueType, Queue>::close() + { + { + lock_guard<mutex> lk(mtx_); + closed_ = true; + } + not_empty_.notify_all(); + } + + template <class ValueType, class Queue> + bool sync_deque_base<ValueType, Queue>::closed() const + { + lock_guard<mutex> lk(mtx_); + return closed(lk); + } + template <class ValueType, class Queue> + bool sync_deque_base<ValueType, Queue>::closed(unique_lock<mutex>&) const + { + return closed_; + } + template <class ValueType, class Queue> + bool sync_deque_base<ValueType, Queue>::closed(lock_guard<mutex>&) const + { + return closed_; + } + + template <class ValueType, class Queue> + bool sync_deque_base<ValueType, Queue>::empty() const + { + lock_guard<mutex> lk(mtx_); + return empty(lk); + } + template <class ValueType, class Queue> + bool sync_deque_base<ValueType, Queue>::full() const + { + return false; + } + + template <class ValueType, class Queue> + typename sync_deque_base<ValueType, Queue>::size_type sync_deque_base<ValueType, Queue>::size() const + { + lock_guard<mutex> lk(mtx_); + return size(lk); + } + + template <class ValueType, class Queue> + void sync_deque_base<ValueType, Queue>::throw_if_closed(unique_lock<mutex>& lk) + { + if (closed(lk)) + { + BOOST_THROW_EXCEPTION( sync_deque_is_closed() ); + } + } + template <class ValueType, class Queue> + void sync_deque_base<ValueType, Queue>::throw_if_closed(lock_guard<mutex>& lk) + { + if (closed(lk)) + { + BOOST_THROW_EXCEPTION( sync_deque_is_closed() ); + } + } + + template <class ValueType, class Queue> + void sync_deque_base<ValueType, Queue>::wait_until_not_empty(unique_lock<mutex>& lk) + { + for (;;) + { + if (! empty(lk)) break; + throw_if_closed(lk); + not_empty_.wait(lk); + } + } + template <class ValueType, class Queue> + bool sync_deque_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk) + { + for (;;) + { + if (! empty(lk)) break; + if (closed(lk)) return true; + not_empty_.wait(lk); + } + return false; + } + + template <class ValueType, class Queue> + queue_op_status sync_deque_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&tp) + { + for (;;) + { + if (! empty(lk)) return queue_op_status::success; + throw_if_closed(lk); + if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout; + } + } + + +} // detail +} // concurrent +} // boost + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_queue_base.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_queue_base.hpp new file mode 100644 index 00000000000..653e273f8b8 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_queue_base.hpp @@ -0,0 +1,223 @@ +#ifndef BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_QUEUE_BASE_HPP +#define BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_QUEUE_BASE_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/detail/move.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/concurrent_queues/queue_op_status.hpp> + +#include <boost/chrono/duration.hpp> +#include <boost/chrono/time_point.hpp> +#include <boost/chrono/system_clocks.hpp> +#include <boost/throw_exception.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + + template <class ValueType, class Queue> + class sync_queue_base + { + public: + typedef ValueType value_type; + typedef Queue underlying_queue_type; + typedef typename Queue::size_type size_type; + typedef queue_op_status op_status; + + typedef typename chrono::steady_clock clock; + typedef typename clock::duration duration; + typedef typename clock::time_point time_point; + + // Constructors/Assignment/Destructors + BOOST_THREAD_NO_COPYABLE(sync_queue_base) + inline sync_queue_base(); + //template <typename Range> + //inline explicit sync_queue(Range range); + inline ~sync_queue_base(); + + // Observers + inline bool empty() const; + inline bool full() const; + inline size_type size() const; + inline bool closed() const; + + // Modifiers + inline void close(); + + inline underlying_queue_type underlying_queue() { + lock_guard<mutex> lk(mtx_); + return boost::move(data_); + } + + protected: + mutable mutex mtx_; + condition_variable not_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 bool closed(unique_lock<mutex>& lk) const; + inline bool closed(lock_guard<mutex>& lk) const; + + inline void throw_if_closed(unique_lock<mutex>&); + inline void throw_if_closed(lock_guard<mutex>&); + + inline void wait_until_not_empty(unique_lock<mutex>& lk); + inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk); + inline queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&); + + inline void notify_not_empty_if_needed(unique_lock<mutex>& ) + { + not_empty_.notify_one(); + } + inline void notify_not_empty_if_needed(lock_guard<mutex>& ) + { + not_empty_.notify_one(); + } + + }; + + template <class ValueType, class Queue> + sync_queue_base<ValueType, Queue>::sync_queue_base() : + data_(), closed_(false) + { + BOOST_ASSERT(data_.empty()); + } + + template <class ValueType, class Queue> + sync_queue_base<ValueType, Queue>::~sync_queue_base() + { + } + + template <class ValueType, class Queue> + void sync_queue_base<ValueType, Queue>::close() + { + { + lock_guard<mutex> lk(mtx_); + closed_ = true; + } + not_empty_.notify_all(); + } + + template <class ValueType, class Queue> + bool sync_queue_base<ValueType, Queue>::closed() const + { + lock_guard<mutex> lk(mtx_); + return closed(lk); + } + template <class ValueType, class Queue> + bool sync_queue_base<ValueType, Queue>::closed(unique_lock<mutex>&) const + { + return closed_; + } + template <class ValueType, class Queue> + bool sync_queue_base<ValueType, Queue>::closed(lock_guard<mutex>&) const + { + return closed_; + } + + template <class ValueType, class Queue> + bool sync_queue_base<ValueType, Queue>::empty() const + { + lock_guard<mutex> lk(mtx_); + return empty(lk); + } + template <class ValueType, class Queue> + bool sync_queue_base<ValueType, Queue>::full() const + { + return false; + } + + template <class ValueType, class Queue> + typename sync_queue_base<ValueType, Queue>::size_type sync_queue_base<ValueType, Queue>::size() const + { + lock_guard<mutex> lk(mtx_); + return size(lk); + } + + template <class ValueType, class Queue> + void sync_queue_base<ValueType, Queue>::throw_if_closed(unique_lock<mutex>& lk) + { + if (closed(lk)) + { + BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + } + template <class ValueType, class Queue> + void sync_queue_base<ValueType, Queue>::throw_if_closed(lock_guard<mutex>& lk) + { + if (closed(lk)) + { + BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + } + + template <class ValueType, class Queue> + void sync_queue_base<ValueType, Queue>::wait_until_not_empty(unique_lock<mutex>& lk) + { + for (;;) + { + if (! empty(lk)) break; + throw_if_closed(lk); + not_empty_.wait(lk); + } + } + template <class ValueType, class Queue> + bool sync_queue_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk) + { + for (;;) + { + if (! empty(lk)) break; + if (closed(lk)) return true; + not_empty_.wait(lk); + } + return false; + } + + template <class ValueType, class Queue> + queue_op_status sync_queue_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&tp) + { + for (;;) + { + if (! empty(lk)) return queue_op_status::success; + throw_if_closed(lk); + if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout; + } + } + + +} // detail +} // concurrent +} // boost + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_adaptor.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_adaptor.hpp new file mode 100644 index 00000000000..f04e0354f75 --- /dev/null +++ b/src/third_party/boost-1.60.0/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, typename Queue::size_type> + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type 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(const value_type& x) { queue.push(x); } + + void pull(value_type& x) { queue.pull(x); }; + value_type pull() { return queue.pull(); } + + queue_op_status try_push(const value_type& x) { return queue.try_push(x); } + queue_op_status try_pull(value_type& x) { return queue.try_pull(x); } + + queue_op_status nonblocking_push(const value_type& x) { return queue.nonblocking_push(x); } + queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); } + + queue_op_status wait_push(const value_type& x) { return queue.wait_push(x); } + queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); } + + }; + template <typename Queue> + class queue_adaptor_movable_only : + public boost::queue_base<typename Queue::value_type, typename Queue::size_type> + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type 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(value_type& x) { queue.pull(x); }; + // enable_if is_nothrow_copy_movable<value_type> + value_type pull() { return queue.pull(); } + + queue_op_status try_pull(value_type& x) { return queue.try_pull(x); } + + queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); } + + queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); } + + void push(BOOST_THREAD_RV_REF(value_type) x) { queue.push(boost::move(x)); } + queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push(boost::move(x)); } + queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push(boost::move(x)); } + queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push(boost::move(x)); } + }; + + template <typename Queue> + class queue_adaptor_copyable_and_movable : + public boost::queue_base<typename Queue::value_type, typename Queue::size_type> + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type 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(const value_type& x) { queue.push(x); } + + void pull(value_type& x) { queue.pull(x); }; + // enable_if is_nothrow_copy_movable<value_type> + value_type pull() { return queue.pull(); } + + queue_op_status try_push(const value_type& x) { return queue.try_push(x); } + queue_op_status try_pull(value_type& x) { return queue.try_pull(x); } + + queue_op_status nonblocking_push(const value_type& x) { return queue.nonblocking_push(x); } + queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); } + + queue_op_status wait_push(const value_type& x) { return queue.wait_push(x); } + queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); } + + void push(BOOST_THREAD_RV_REF(value_type) x) { queue.push(boost::move(x)); } + queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push(boost::move(x)); } + queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push(boost::move(x)); } + queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push(boost::move(x)); } + }; + + + template <class Q, class T, +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES +#if defined __GNUC__ && ! defined __clang__ +#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 typename Queue::size_type size_type; + // Constructors/Assignment/Destructors + virtual ~queue_adaptor() {}; + }; +} +using concurrent::queue_adaptor; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_base.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_base.hpp new file mode 100755 index 00000000000..0d42839158e --- /dev/null +++ b/src/third_party/boost-1.60.0/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 SizeType> + class queue_base_copyable_only + { + public: + typedef ValueType value_type; + typedef SizeType 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(const value_type& x) = 0; + + virtual void pull(value_type&) = 0; + virtual value_type pull() = 0; + + virtual queue_op_status try_push(const value_type& x) = 0; + virtual queue_op_status try_pull(value_type&) = 0; + + virtual queue_op_status nonblocking_push(const value_type& x) = 0; + virtual queue_op_status nonblocking_pull(value_type&) = 0; + + virtual queue_op_status wait_push(const value_type& x) = 0; + virtual queue_op_status wait_pull(ValueType& elem) = 0; + + }; + + template <typename ValueType, class SizeType> + class queue_base_movable_only + { + public: + typedef ValueType value_type; + typedef SizeType 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(value_type&) = 0; + // enable_if is_nothrow_movable<value_type> + virtual value_type pull() = 0; + + virtual queue_op_status try_pull(value_type&) = 0; + + virtual queue_op_status nonblocking_pull(value_type&) = 0; + + virtual queue_op_status wait_pull(value_type& elem) = 0; + + virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + }; + + + template <typename ValueType, class SizeType> + class queue_base_copyable_and_movable + { + public: + typedef ValueType value_type; + typedef SizeType 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(const value_type& x) = 0; + + virtual void pull(value_type&) = 0; + // enable_if is_nothrow_copy_movable<value_type> + virtual value_type pull() = 0; + + virtual queue_op_status try_push(const value_type& x) = 0; + virtual queue_op_status try_pull(value_type&) = 0; + + virtual queue_op_status nonblocking_push(const value_type& x) = 0; + virtual queue_op_status nonblocking_pull(value_type&) = 0; + + virtual queue_op_status wait_push(const value_type& x) = 0; + virtual queue_op_status wait_pull(value_type& elem) = 0; + + virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + }; + + template <class T, class ST, +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES +#if defined __GNUC__ && ! defined __clang__ +#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, class ST> + struct queue_base<T, ST, true, true> { + typedef queue_base_copyable_and_movable<T, ST> type; + }; + template <class T, class ST> + struct queue_base<T, ST, true, false> { + typedef queue_base_copyable_only<T, ST> type; + }; + template <class T, class ST> + struct queue_base<T, ST, false, true> { + typedef queue_base_movable_only<T, ST> type; + }; + +} + + template <typename ValueType, class SizeType=std::size_t> + class queue_base : + public detail::queue_base<ValueType, SizeType>::type + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + // Constructors/Assignment/Destructors + virtual ~queue_base() {}; + }; + +} +using concurrent::queue_base; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_op_status.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_op_status.hpp new file mode 100644 index 00000000000..197650d0521 --- /dev/null +++ b/src/third_party/boost-1.60.0/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, timeout, not_ready } + 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/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_views.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_views.hpp new file mode 100644 index 00000000000..5a4512dd6ed --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_views.hpp @@ -0,0 +1,155 @@ +#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(x); } + + queue_op_status try_push(const value_type& x) { return queue->try_push(x); } + + queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push(x); } + queue_op_status wait_push(const value_type& x) { return queue->wait_push(x); } + + void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push(boost::move(x)); } + queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push(boost::move(x)); } + queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push(boost::move(x)); } + queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push(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(x); }; + // enable_if is_nothrow_copy_movable<value_type> + value_type pull() { return queue->pull(); } + + 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(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(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(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/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_bounded_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_bounded_queue.hpp new file mode 100644 index 00000000000..e34fa56f37f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_bounded_queue.hpp @@ -0,0 +1,725 @@ +#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_BOUNDED_QUEUE_HPP +#define BOOST_THREAD_CONCURRENT_QUEUES_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 +{ +namespace concurrent +{ + 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; + } +} +using concurrent::sync_bounded_queue; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_deque.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_deque.hpp new file mode 100644 index 00000000000..c84dae022ac --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_deque.hpp @@ -0,0 +1,327 @@ +#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP +#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_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/concurrent_queues/detail/sync_queue_base.hpp> +#include <boost/thread/concurrent_queues/queue_op_status.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/csbl/devector.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/mutex.hpp> + +#include <boost/throw_exception.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +namespace concurrent +{ + template <class ValueType, class Container = csbl::devector<ValueType> > + class sync_deque + : public detail::sync_queue_base<ValueType, Container > + { + typedef detail::sync_queue_base<ValueType, Container > super; + + public: + typedef ValueType value_type; + //typedef typename super::value_type value_type; // fixme + typedef typename super::underlying_queue_type underlying_queue_type; + typedef typename super::size_type size_type; + typedef typename super::op_status op_status; + + // Constructors/Assignment/Destructors + BOOST_THREAD_NO_COPYABLE(sync_deque) + inline sync_deque(); + //template <typename Range> + //inline explicit sync_deque(Range range); + inline ~sync_deque(); + + // Modifiers + 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 + 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: + + 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 pull_front(value_type& elem, unique_lock<mutex>& ) + { + elem = boost::move(super::data_.front()); + super::data_.pop_front(); + } + inline value_type pull_front(unique_lock<mutex>& ) + { + value_type e = boost::move(super::data_.front()); + super::data_.pop_front(); + return boost::move(e); + } + + inline void push_back(const value_type& elem, unique_lock<mutex>& lk) + { + super::data_.push_back(elem); + super::notify_not_empty_if_needed(lk); + } + + inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk) + { + super::data_.push_back(boost::move(elem)); + super::notify_not_empty_if_needed(lk); + } + }; + + template <class ValueType, class Container> + sync_deque<ValueType, Container>::sync_deque() : + super() + { + } + +// template <class ValueType, class Container> +// template <class Range> +// explicit sync_deque<ValueType, Container>::sync_deque(Range range) : +// 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 <class ValueType, class Container> + sync_deque<ValueType, Container>::~sync_deque() + { + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + pull_front(elem, lk); + return queue_op_status::success; + } + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + } + bool has_been_closed = super::wait_until_not_empty_or_closed(lk); + if (has_been_closed) return queue_op_status::closed; + pull_front(elem, lk); + return queue_op_status::success; + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::try_pull_front(ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + return try_pull_front(elem, lk); + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + return wait_pull_front(elem, lk); + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::nonblocking_pull_front(ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return queue_op_status::busy; + } + return try_pull_front(elem, lk); + } + + template <class ValueType, class Container> + void sync_deque<ValueType, Container>::pull_front(ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + super::wait_until_not_empty(lk); + pull_front(elem, lk); + } + + // enable if ValueType is nothrow movable + template <class ValueType, class Container> + ValueType sync_deque<ValueType, Container>::pull_front() + { + unique_lock<mutex> lk(super::mtx_); + super::wait_until_not_empty(lk); + return pull_front(lk); + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push_back(elem, lk); + return queue_op_status::success; + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::try_push_back(const ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + return try_push_back(elem, lk); + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push_back(elem, lk); + return queue_op_status::success; + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::wait_push_back(const ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + return wait_push_back(elem, lk); + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::nonblocking_push_back(const ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) return queue_op_status::busy; + return try_push_back(elem, lk); + } + + template <class ValueType, class Container> + void sync_deque<ValueType, Container>::push_back(const ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + super::throw_if_closed(lk); + push_back(elem, lk); + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push_back(boost::move(elem), lk); + return queue_op_status::success; + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock<mutex> lk(super::mtx_); + return try_push_back(boost::move(elem), lk); + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push_back(boost::move(elem), lk); + return queue_op_status::success; + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock<mutex> lk(super::mtx_); + return wait_push_back(boost::move(elem), lk); + } + + template <class ValueType, class Container> + queue_op_status sync_deque<ValueType, Container>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock<mutex> lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return queue_op_status::busy; + } + return try_push_back(boost::move(elem), lk); + } + + template <class ValueType, class Container> + void sync_deque<ValueType, Container>::push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock<mutex> lk(super::mtx_); + super::throw_if_closed(lk); + push_back(boost::move(elem), lk); + } + + template <class ValueType, class Container> + sync_deque<ValueType, Container>& operator<<(sync_deque<ValueType, Container>& sbq, BOOST_THREAD_RV_REF(ValueType) elem) + { + sbq.push_back(boost::move(elem)); + return sbq; + } + + template <class ValueType, class Container> + sync_deque<ValueType, Container>& operator<<(sync_deque<ValueType, Container>& sbq, ValueType const&elem) + { + sbq.push_back(elem); + return sbq; + } + + template <class ValueType, class Container> + sync_deque<ValueType, Container>& operator>>(sync_deque<ValueType, Container>& sbq, ValueType &elem) + { + sbq.pull_front(elem); + return sbq; + } + +} +using concurrent::sync_deque; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_priority_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_priority_queue.hpp new file mode 100644 index 00000000000..d604faa7423 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_priority_queue.hpp @@ -0,0 +1,369 @@ +// Copyright (C) 2014 Ian Forbed +// 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_SYNC_PRIORITY_QUEUE +#define BOOST_THREAD_SYNC_PRIORITY_QUEUE + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp> +#include <boost/thread/concurrent_queues/queue_op_status.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/csbl/vector.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/mutex.hpp> + +#include <boost/atomic.hpp> +#include <boost/chrono/duration.hpp> +#include <boost/chrono/time_point.hpp> + +#include <exception> +#include <queue> +#include <utility> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +namespace detail { + + template < + class Type, + class Container = csbl::vector<Type>, + class Compare = std::less<Type> + > + class priority_queue + { + private: + Container _elements; + Compare _compare; + public: + typedef Type value_type; + typedef typename Container::size_type size_type; + + explicit priority_queue(const Compare& compare = Compare()) + : _elements(), _compare(compare) + { } + + size_type size() const + { + return _elements.size(); + } + + bool empty() const + { + return _elements.empty(); + } + + void push(Type const& element) + { + _elements.push_back(element); + std::push_heap(_elements.begin(), _elements.end(), _compare); + } + void push(BOOST_RV_REF(Type) element) + { + _elements.push_back(boost::move(element)); + std::push_heap(_elements.begin(), _elements.end(), _compare); + } + + void pop() + { + std::pop_heap(_elements.begin(), _elements.end(), _compare); + _elements.pop_back(); + } + Type pull() + { + Type result = boost::move(_elements.front()); + pop(); + return boost::move(result); + } + + Type const& top() + { + return _elements.front(); + } + }; +} + +namespace concurrent +{ + template <class ValueType, + class Container = csbl::vector<ValueType>, + class Compare = std::less<typename Container::value_type> > + class sync_priority_queue + : public detail::sync_queue_base<ValueType, boost::detail::priority_queue<ValueType,Container,Compare> > + { + typedef detail::sync_queue_base<ValueType, boost::detail::priority_queue<ValueType,Container,Compare> > super; + + public: + typedef ValueType value_type; + //typedef typename super::value_type value_type; // fixme + typedef typename super::underlying_queue_type underlying_queue_type; + typedef typename super::size_type size_type; + typedef typename super::op_status op_status; + + typedef chrono::steady_clock clock; + protected: + + public: + sync_priority_queue() {} + + ~sync_priority_queue() + { + if(!super::closed()) + { + super::close(); + } + } + + void push(const ValueType& elem); + void push(BOOST_THREAD_RV_REF(ValueType) elem); + + queue_op_status try_push(const ValueType& elem); + queue_op_status try_push(BOOST_THREAD_RV_REF(ValueType) elem); + + ValueType pull(); + + void pull(ValueType&); + + queue_op_status pull_until(const clock::time_point&, ValueType&); + queue_op_status pull_for(const clock::duration&, ValueType&); + + queue_op_status try_pull(ValueType& elem); + queue_op_status wait_pull(ValueType& elem); + queue_op_status nonblocking_pull(ValueType&); + + private: + void push(unique_lock<mutex>&, const ValueType& elem); + void push(lock_guard<mutex>&, const ValueType& elem); + void push(unique_lock<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem); + void push(lock_guard<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem); + + queue_op_status try_push(unique_lock<mutex>&, const ValueType& elem); + queue_op_status try_push(unique_lock<mutex>&, BOOST_THREAD_RV_REF(ValueType) elem); + + ValueType pull(unique_lock<mutex>&); + ValueType pull(lock_guard<mutex>&); + + void pull(unique_lock<mutex>&, ValueType&); + void pull(lock_guard<mutex>&, ValueType&); + + queue_op_status try_pull(lock_guard<mutex>& lk, ValueType& elem); + queue_op_status try_pull(unique_lock<mutex>& lk, ValueType& elem); + + queue_op_status wait_pull(unique_lock<mutex>& lk, ValueType& elem); + + queue_op_status nonblocking_pull(unique_lock<mutex>& lk, ValueType&); + + sync_priority_queue(const sync_priority_queue&); + sync_priority_queue& operator= (const sync_priority_queue&); + sync_priority_queue(BOOST_THREAD_RV_REF(sync_priority_queue)); + sync_priority_queue& operator= (BOOST_THREAD_RV_REF(sync_priority_queue)); + }; //end class + + + ////////////////////// + template <class T, class Container,class Cmp> + void sync_priority_queue<T,Container,Cmp>::push(unique_lock<mutex>& lk, const T& elem) + { + super::throw_if_closed(lk); + super::data_.push(elem); + super::notify_not_empty_if_needed(lk); + } + template <class T, class Container,class Cmp> + void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, const T& elem) + { + super::throw_if_closed(lk); + super::data_.push(elem); + super::notify_not_empty_if_needed(lk); + } + template <class T, class Container,class Cmp> + void sync_priority_queue<T,Container,Cmp>::push(const T& elem) + { + lock_guard<mutex> lk(super::mtx_); + push(lk, elem); + } + + ////////////////////// + template <class T, class Container,class Cmp> + void sync_priority_queue<T,Container,Cmp>::push(unique_lock<mutex>& lk, BOOST_THREAD_RV_REF(T) elem) + { + super::throw_if_closed(lk); + super::data_.push(boost::move(elem)); + super::notify_not_empty_if_needed(lk); + } + template <class T, class Container,class Cmp> + void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, BOOST_THREAD_RV_REF(T) elem) + { + super::throw_if_closed(lk); + super::data_.push(boost::move(elem)); + super::notify_not_empty_if_needed(lk); + } + template <class T, class Container,class Cmp> + void sync_priority_queue<T,Container,Cmp>::push(BOOST_THREAD_RV_REF(T) elem) + { + lock_guard<mutex> lk(super::mtx_); + push(lk, boost::move(elem)); + } + + ////////////////////// + template <class T, class Container,class Cmp> + queue_op_status sync_priority_queue<T,Container,Cmp>::try_push(const T& elem) + { + lock_guard<mutex> lk(super::mtx_); + if (super::closed(lk)) return queue_op_status::closed; + push(lk, elem); + return queue_op_status::success; + } + + ////////////////////// + template <class T, class Container,class Cmp> + queue_op_status sync_priority_queue<T,Container,Cmp>::try_push(BOOST_THREAD_RV_REF(T) elem) + { + lock_guard<mutex> lk(super::mtx_); + if (super::closed(lk)) return queue_op_status::closed; + push(lk, boost::move(elem)); + + return queue_op_status::success; + } + + ////////////////////// + template <class T,class Container, class Cmp> + T sync_priority_queue<T,Container,Cmp>::pull(unique_lock<mutex>&) + { + return super::data_.pull(); + } + template <class T,class Container, class Cmp> + T sync_priority_queue<T,Container,Cmp>::pull(lock_guard<mutex>&) + { + return super::data_.pull(); + } + + template <class T,class Container, class Cmp> + T sync_priority_queue<T,Container,Cmp>::pull() + { + unique_lock<mutex> lk(super::mtx_); + super::wait_until_not_empty(lk); + return pull(lk); + } + + ////////////////////// + template <class T,class Container, class Cmp> + void sync_priority_queue<T,Container,Cmp>::pull(unique_lock<mutex>&, T& elem) + { + elem = super::data_.pull(); + } + template <class T,class Container, class Cmp> + void sync_priority_queue<T,Container,Cmp>::pull(lock_guard<mutex>&, T& elem) + { + elem = super::data_.pull(); + } + + template <class T,class Container, class Cmp> + void sync_priority_queue<T,Container,Cmp>::pull(T& elem) + { + unique_lock<mutex> lk(super::mtx_); + super::wait_until_not_empty(lk); + pull(lk, elem); + } + + ////////////////////// + template <class T, class Cont,class Cmp> + queue_op_status + sync_priority_queue<T,Cont,Cmp>::pull_until(const clock::time_point& tp, T& elem) + { + unique_lock<mutex> lk(super::mtx_); + if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp)) + return queue_op_status::timeout; + pull(lk, elem); + return queue_op_status::success; + } + + ////////////////////// + template <class T, class Cont,class Cmp> + queue_op_status + sync_priority_queue<T,Cont,Cmp>::pull_for(const clock::duration& dura, T& elem) + { + return pull_until(clock::now() + dura, elem); + } + + ////////////////////// + template <class T, class Container,class Cmp> + queue_op_status + sync_priority_queue<T,Container,Cmp>::try_pull(unique_lock<mutex>& lk, T& elem) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + pull(lk, elem); + return queue_op_status::success; + } + + template <class T, class Container,class Cmp> + queue_op_status + sync_priority_queue<T,Container,Cmp>::try_pull(lock_guard<mutex>& lk, T& elem) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + pull(lk, elem); + return queue_op_status::success; + } + + template <class T, class Container,class Cmp> + queue_op_status + sync_priority_queue<T,Container,Cmp>::try_pull(T& elem) + { + lock_guard<mutex> lk(super::mtx_); + return try_pull(lk, elem); + } + + ////////////////////// + template <class T,class Container, class Cmp> + queue_op_status sync_priority_queue<T,Container,Cmp>::wait_pull(unique_lock<mutex>& lk, T& elem) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + } + bool has_been_closed = super::wait_until_not_empty_or_closed(lk); + if (has_been_closed) return queue_op_status::closed; + pull(lk, elem); + return queue_op_status::success; + } + + template <class T,class Container, class Cmp> + queue_op_status sync_priority_queue<T,Container,Cmp>::wait_pull(T& elem) + { + unique_lock<mutex> lk(super::mtx_); + return wait_pull(lk, elem); + } + + ////////////////////// + + template <class T,class Container, class Cmp> + queue_op_status sync_priority_queue<T,Container,Cmp>::nonblocking_pull(T& elem) + { + unique_lock<mutex> lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) return queue_op_status::busy; + return try_pull(lk, elem); + } + + + +} //end concurrent namespace + +using concurrent::sync_priority_queue; + +} //end boost namespace +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_queue.hpp new file mode 100644 index 00000000000..1dbbef05dd3 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_queue.hpp @@ -0,0 +1,335 @@ +#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_QUEUE_HPP +#define BOOST_THREAD_CONCURRENT_QUEUES_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 <iostream> + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp> +#include <boost/thread/concurrent_queues/queue_op_status.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/csbl/devector.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/mutex.hpp> + +#include <boost/throw_exception.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +namespace concurrent +{ + template <class ValueType, class Container = csbl::devector<ValueType> > + class sync_queue + : public detail::sync_queue_base<ValueType, Container > + { + typedef detail::sync_queue_base<ValueType, Container > super; + + public: + typedef ValueType value_type; + //typedef typename super::value_type value_type; // fixme + typedef typename super::underlying_queue_type underlying_queue_type; + typedef typename super::size_type size_type; + typedef typename super::op_status op_status; + + // Constructors/Assignment/Destructors + BOOST_THREAD_NO_COPYABLE(sync_queue) + inline sync_queue(); + //template <class Range> + //inline explicit sync_queue(Range range); + inline ~sync_queue(); + + // Modifiers + + inline void push(const value_type& x); + inline queue_op_status try_push(const value_type& x); + inline queue_op_status nonblocking_push(const value_type& x); + inline queue_op_status wait_push(const value_type& x); + inline void push(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x); + + // Observers/Modifiers + inline void pull(value_type&); + // enable_if is_nothrow_copy_movable<value_type> + inline value_type pull(); + + inline queue_op_status try_pull(value_type&); + inline queue_op_status nonblocking_pull(value_type&); + inline queue_op_status wait_pull(ValueType& elem); + + private: + + inline queue_op_status try_pull(value_type& x, unique_lock<mutex>& lk); + inline queue_op_status wait_pull(value_type& x, unique_lock<mutex>& lk); + inline queue_op_status try_push(const value_type& x, unique_lock<mutex>& lk); + inline queue_op_status wait_push(const value_type& x, unique_lock<mutex>& lk); + inline queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk); + inline queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk); + + inline void pull(value_type& elem, unique_lock<mutex>& ) + { + elem = boost::move(super::data_.front()); + super::data_.pop_front(); + } + inline value_type pull(unique_lock<mutex>& ) + { + value_type e = boost::move(super::data_.front()); + super::data_.pop_front(); + return boost::move(e); + } + + inline void push(const value_type& elem, unique_lock<mutex>& lk) + { + super::data_.push_back(elem); + super::notify_not_empty_if_needed(lk); + } + + inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk) + { + super::data_.push_back(boost::move(elem)); + super::notify_not_empty_if_needed(lk); + } + }; + + template <class ValueType, class Container> + sync_queue<ValueType, Container>::sync_queue() : + super() + { + } + +// template <class ValueType, class Container> +// template <class Range> +// explicit sync_queue<ValueType, Container>::sync_queue(Range range) : +// 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 <class ValueType, class Container> + sync_queue<ValueType, Container>::~sync_queue() + { + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::try_pull(ValueType& elem, unique_lock<mutex>& lk) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + pull(elem, lk); + return queue_op_status::success; + } + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem, unique_lock<mutex>& lk) + { + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + if (super::empty(lk)) + { + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + if (super::closed(lk)) return queue_op_status::closed; + } + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + bool has_been_closed = super::wait_until_not_empty_or_closed(lk); + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + if (has_been_closed) return queue_op_status::closed; + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + pull(elem, lk); + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + return queue_op_status::success; + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::try_pull(ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + return try_pull(elem, lk); + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + return wait_pull(elem, lk); + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::nonblocking_pull(ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return queue_op_status::busy; + } + return try_pull(elem, lk); + } + + template <class ValueType, class Container> + void sync_queue<ValueType, Container>::pull(ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + super::wait_until_not_empty(lk); + pull(elem, lk); + } + + // enable if ValueType is nothrow movable + template <class ValueType, class Container> + ValueType sync_queue<ValueType, Container>::pull() + { + unique_lock<mutex> lk(super::mtx_); + super::wait_until_not_empty(lk); + return pull(lk); + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::try_push(const ValueType& elem, unique_lock<mutex>& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push(elem, lk); + return queue_op_status::success; + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::try_push(const ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + return try_push(elem, lk); + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::wait_push(const ValueType& elem, unique_lock<mutex>& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push(elem, lk); + return queue_op_status::success; + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::wait_push(const ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + return wait_push(elem, lk); + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::nonblocking_push(const ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) return queue_op_status::busy; + return try_push(elem, lk); + } + + template <class ValueType, class Container> + void sync_queue<ValueType, Container>::push(const ValueType& elem) + { + unique_lock<mutex> lk(super::mtx_); + super::throw_if_closed(lk); + push(elem, lk); + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push(boost::move(elem), lk); + return queue_op_status::success; + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::try_push(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock<mutex> lk(super::mtx_); + return try_push(boost::move(elem), lk); + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::wait_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push(boost::move(elem), lk); + return queue_op_status::success; + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::wait_push(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock<mutex> lk(super::mtx_); + return wait_push(boost::move(elem), lk); + } + + template <class ValueType, class Container> + queue_op_status sync_queue<ValueType, Container>::nonblocking_push(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock<mutex> lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return queue_op_status::busy; + } + return try_push(boost::move(elem), lk); + } + + template <class ValueType, class Container> + void sync_queue<ValueType, Container>::push(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock<mutex> lk(super::mtx_); + super::throw_if_closed(lk); + push(boost::move(elem), lk); + } + + template <class ValueType, class Container> + sync_queue<ValueType, Container>& operator<<(sync_queue<ValueType, Container>& sbq, BOOST_THREAD_RV_REF(ValueType) elem) + { + sbq.push(boost::move(elem)); + return sbq; + } + + template <class ValueType, class Container> + sync_queue<ValueType, Container>& operator<<(sync_queue<ValueType, Container>& sbq, ValueType const&elem) + { + sbq.push(elem); + return sbq; + } + + template <class ValueType, class Container> + sync_queue<ValueType, Container>& operator>>(sync_queue<ValueType, Container>& sbq, ValueType &elem) + { + sbq.pull(elem); + return sbq; + } + +} +using concurrent::sync_queue; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_timed_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_timed_queue.hpp new file mode 100644 index 00000000000..36223d87152 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_timed_queue.hpp @@ -0,0 +1,466 @@ +// Copyright (C) 2014 Ian Forbed +// 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_SYNC_TIMED_QUEUE_HPP +#define BOOST_THREAD_SYNC_TIMED_QUEUE_HPP + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/concurrent_queues/sync_priority_queue.hpp> +#include <boost/chrono/duration.hpp> +#include <boost/chrono/time_point.hpp> +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/chrono_io.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + template <class T, class Clock = chrono::steady_clock> + struct scheduled_type + { + typedef T value_type; + typedef Clock clock; + typedef typename clock::time_point time_point; + T data; + time_point time; + + BOOST_THREAD_COPYABLE_AND_MOVABLE(scheduled_type) + + scheduled_type(T const& pdata, time_point tp) : data(pdata), time(tp) {} + scheduled_type(BOOST_THREAD_RV_REF(T) pdata, time_point tp) : data(boost::move(pdata)), time(tp) {} + + scheduled_type(scheduled_type const& other) : data(other.data), time(other.time) {} + scheduled_type& operator=(BOOST_THREAD_COPY_ASSIGN_REF(scheduled_type) other) { + data = other.data; + time = other.time; + return *this; + } + + scheduled_type(BOOST_THREAD_RV_REF(scheduled_type) other) : data(boost::move(other.data)), time(other.time) {} + scheduled_type& operator=(BOOST_THREAD_RV_REF(scheduled_type) other) { + data = boost::move(other.data); + time = other.time; + return *this; + } + + bool time_not_reached() const + { + return time > clock::now(); + } + + bool operator <(const scheduled_type<T> other) const + { + return this->time > other.time; + } + }; //end struct + +} //end detail namespace + + template <class T, class Clock = chrono::steady_clock> + class sync_timed_queue + : private sync_priority_queue<detail::scheduled_type<T, Clock> > + { + typedef detail::scheduled_type<T> stype; + typedef sync_priority_queue<stype> super; + public: + typedef T value_type; + typedef Clock clock; + typedef typename clock::duration duration; + typedef typename clock::time_point time_point; + typedef typename super::underlying_queue_type underlying_queue_type; + typedef typename super::size_type size_type; + typedef typename super::op_status op_status; + + sync_timed_queue() : super() {}; + ~sync_timed_queue() {} + + using super::size; + using super::empty; + using super::full; + using super::close; + using super::closed; + + T pull(); + void pull(T& elem); + + template <class Duration> + queue_op_status pull_until(chrono::time_point<clock,Duration> const& tp, T& elem); + template <class Rep, class Period> + queue_op_status pull_for(chrono::duration<Rep,Period> const& dura, T& elem); + + queue_op_status try_pull(T& elem); + queue_op_status wait_pull(T& elem); + queue_op_status nonblocking_pull(T& elem); + + template <class Duration> + void push(const T& elem, chrono::time_point<clock,Duration> const& tp); + template <class Rep, class Period> + void push(const T& elem, chrono::duration<Rep,Period> const& dura); + + template <class Duration> + void push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp); + template <class Rep, class Period> + void push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura); + + template <class Duration> + queue_op_status try_push(const T& elem, chrono::time_point<clock,Duration> const& tp); + template <class Rep, class Period> + queue_op_status try_push(const T& elem, chrono::duration<Rep,Period> const& dura); + + template <class Duration> + queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp); + template <class Rep, class Period> + queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura); + + private: + T pull(unique_lock<mutex>&); + T pull(lock_guard<mutex>&); + + void pull(unique_lock<mutex>&, T& elem); + void pull(lock_guard<mutex>&, T& elem); + + queue_op_status try_pull(unique_lock<mutex>&, T& elem); + queue_op_status try_pull(lock_guard<mutex>&, T& elem); + + queue_op_status wait_pull(unique_lock<mutex>& lk, T& elem); + + bool wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>&); + T pull_when_time_reached(unique_lock<mutex>&); + template <class Duration> + queue_op_status pull_when_time_reached_until(unique_lock<mutex>&, chrono::time_point<clock,Duration> const& tp, T& elem); + bool time_not_reached(unique_lock<mutex>&); + bool time_not_reached(lock_guard<mutex>&); + bool empty_or_time_not_reached(unique_lock<mutex>&); + bool empty_or_time_not_reached(lock_guard<mutex>&); + + sync_timed_queue(const sync_timed_queue&); + sync_timed_queue& operator=(const sync_timed_queue&); + sync_timed_queue(BOOST_THREAD_RV_REF(sync_timed_queue)); + sync_timed_queue& operator=(BOOST_THREAD_RV_REF(sync_timed_queue)); + }; //end class + + + template <class T, class Clock> + template <class Duration> + void sync_timed_queue<T, Clock>::push(const T& elem, chrono::time_point<clock,Duration> const& tp) + { + super::push(stype(elem,tp)); + } + + template <class T, class Clock> + template <class Rep, class Period> + void sync_timed_queue<T, Clock>::push(const T& elem, chrono::duration<Rep,Period> const& dura) + { + push(elem, clock::now() + dura); + } + + template <class T, class Clock> + template <class Duration> + void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp) + { + super::push(stype(boost::move(elem),tp)); + } + + template <class T, class Clock> + template <class Rep, class Period> + void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura) + { + push(boost::move(elem), clock::now() + dura); + } + + + + template <class T, class Clock> + template <class Duration> + queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp) + { + return super::try_push(stype(elem,tp)); + } + + template <class T, class Clock> + template <class Rep, class Period> + queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::duration<Rep,Period> const& dura) + { + return try_push(elem,clock::now() + dura); + } + + template <class T, class Clock> + template <class Duration> + queue_op_status sync_timed_queue<T, Clock>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp) + { + return super::try_push(stype(boost::move(elem), tp)); + } + + template <class T, class Clock> + template <class Rep, class Period> + queue_op_status sync_timed_queue<T, Clock>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura) + { + return try_push(boost::move(elem), clock::now() + dura); + } + + /////////////////////////// + template <class T, class Clock> + bool sync_timed_queue<T, Clock>::time_not_reached(unique_lock<mutex>&) + { + return super::data_.top().time_not_reached(); + } + + template <class T, class Clock> + bool sync_timed_queue<T, Clock>::time_not_reached(lock_guard<mutex>&) + { + return super::data_.top().time_not_reached(); + } + + /////////////////////////// + template <class T, class Clock> + bool sync_timed_queue<T, Clock>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk) + { + for (;;) + { + if (super::closed(lk)) return true; + while (! super::empty(lk)) { + if (! time_not_reached(lk)) return false; + super::not_empty_.wait_until(lk, super::data_.top().time); + if (super::closed(lk)) return true; + } + if (super::closed(lk)) return true; + super::not_empty_.wait(lk); + } + //return false; + } + + /////////////////////////// + template <class T, class Clock> + T sync_timed_queue<T, Clock>::pull_when_time_reached(unique_lock<mutex>& lk) + { + while (time_not_reached(lk)) + { + super::throw_if_closed(lk); + super::not_empty_.wait_until(lk,super::data_.top().time); + super::wait_until_not_empty(lk); + } + return pull(lk); + } + + template <class T, class Clock> + template <class Duration> + queue_op_status + sync_timed_queue<T, Clock>::pull_when_time_reached_until(unique_lock<mutex>& lk, chrono::time_point<clock,Duration> const& tp, T& elem) + { + chrono::time_point<clock,Duration> tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time; + while (time_not_reached(lk)) + { + super::throw_if_closed(lk); + if (queue_op_status::timeout == super::not_empty_.wait_until(lk, tpmin)) { + if (time_not_reached(lk)) return queue_op_status::not_ready; + return queue_op_status::timeout; + } + } + pull(lk, elem); + return queue_op_status::success; + } + + /////////////////////////// + template <class T, class Clock> + bool sync_timed_queue<T, Clock>::empty_or_time_not_reached(unique_lock<mutex>& lk) + { + if ( super::empty(lk) ) return true; + if ( time_not_reached(lk) ) return true; + return false; + } + template <class T, class Clock> + bool sync_timed_queue<T, Clock>::empty_or_time_not_reached(lock_guard<mutex>& lk) + { + if ( super::empty(lk) ) return true; + if ( time_not_reached(lk) ) return true; + return false; + } + + /////////////////////////// + template <class T, class Clock> + T sync_timed_queue<T, Clock>::pull(unique_lock<mutex>&) + { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + return boost::move(super::data_.pull().data); +#else + return super::data_.pull().data; +#endif + } + + template <class T, class Clock> + T sync_timed_queue<T, Clock>::pull(lock_guard<mutex>&) + { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + return boost::move(super::data_.pull().data); +#else + return super::data_.pull().data; +#endif + } + template <class T, class Clock> + T sync_timed_queue<T, Clock>::pull() + { + unique_lock<mutex> lk(super::mtx_); + super::wait_until_not_empty(lk); + return pull_when_time_reached(lk); + } + + /////////////////////////// + template <class T, class Clock> + void sync_timed_queue<T, Clock>::pull(unique_lock<mutex>&, T& elem) + { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + elem = boost::move(super::data_.pull().data); +#else + elem = super::data_.pull().data; +#endif + } + + template <class T, class Clock> + void sync_timed_queue<T, Clock>::pull(lock_guard<mutex>&, T& elem) + { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + elem = boost::move(super::data_.pull().data); +#else + elem = super::data_.pull().data; +#endif + } + + template <class T, class Clock> + void sync_timed_queue<T, Clock>::pull(T& elem) + { + unique_lock<mutex> lk(super::mtx_); + super::wait_until_not_empty(lk); + elem = pull_when_time_reached(lk); + } + + ////////////////////// + template <class T, class Clock> + template <class Duration> + queue_op_status + sync_timed_queue<T, Clock>::pull_until(chrono::time_point<clock,Duration> const& tp, T& elem) + { + unique_lock<mutex> lk(super::mtx_); + + if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp)) + return queue_op_status::timeout; + return pull_when_time_reached_until(lk, tp, elem); + } + + ////////////////////// + template <class T, class Clock> + template <class Rep, class Period> + queue_op_status + sync_timed_queue<T, Clock>::pull_for(chrono::duration<Rep,Period> const& dura, T& elem) + { + return pull_until(clock::now() + dura, elem); + } + + /////////////////////////// + template <class T, class Clock> + queue_op_status sync_timed_queue<T, Clock>::try_pull(unique_lock<mutex>& lk, T& elem) + { + if ( super::empty(lk) ) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + if ( time_not_reached(lk) ) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::not_ready; + } + + pull(lk, elem); + return queue_op_status::success; + } + template <class T, class Clock> + queue_op_status sync_timed_queue<T, Clock>::try_pull(lock_guard<mutex>& lk, T& elem) + { + if ( super::empty(lk) ) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + if ( time_not_reached(lk) ) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::not_ready; + } + pull(lk, elem); + return queue_op_status::success; + } + + template <class T, class Clock> + queue_op_status sync_timed_queue<T, Clock>::try_pull(T& elem) + { + lock_guard<mutex> lk(super::mtx_); + return try_pull(lk, elem); + } + + /////////////////////////// + template <class T, class Clock> + queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex>& lk, T& elem) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + } + bool has_been_closed = wait_until_not_empty_time_reached_or_closed(lk); + if (has_been_closed) return queue_op_status::closed; + pull(lk, elem); + return queue_op_status::success; + } + + template <class T, class Clock> + queue_op_status sync_timed_queue<T, Clock>::wait_pull(T& elem) + { + unique_lock<mutex> lk(super::mtx_); + return wait_pull(lk, elem); + } + +// /////////////////////////// +// template <class T, class Clock> +// queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex> &lk, T& elem) +// { +// if (super::empty(lk)) +// { +// if (super::closed(lk)) return queue_op_status::closed; +// } +// bool has_been_closed = super::wait_until_not_empty_or_closed(lk); +// if (has_been_closed) return queue_op_status::closed; +// pull(lk, elem); +// return queue_op_status::success; +// } +// template <class T> +// queue_op_status sync_timed_queue<T, Clock>::wait_pull(T& elem) +// { +// unique_lock<mutex> lk(super::mtx_); +// return wait_pull(lk, elem); +// } + + /////////////////////////// + template <class T, class Clock> + queue_op_status sync_timed_queue<T, Clock>::nonblocking_pull(T& elem) + { + unique_lock<mutex> lk(super::mtx_, try_to_lock); + if (! lk.owns_lock()) return queue_op_status::busy; + return try_pull(lk, elem); + } + +} //end concurrent namespace + +using concurrent::sync_timed_queue; + +} //end boost namespace +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/condition.hpp b/src/third_party/boost-1.60.0/boost/thread/condition.hpp new file mode 100644 index 00000000000..9567df98251 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/condition.hpp @@ -0,0 +1,21 @@ +#ifndef BOOST_THREAD_CONDITION_HPP +#define BOOST_THREAD_CONDITION_HPP +// (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 +{ + typedef condition_variable_any condition; +} + +#endif +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/condition_variable.hpp b/src/third_party/boost-1.60.0/boost/thread/condition_variable.hpp new file mode 100644 index 00000000000..8f8e9f2ed65 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/condition_variable.hpp @@ -0,0 +1,21 @@ +#ifndef BOOST_THREAD_CONDITION_VARIABLE_HPP +#define BOOST_THREAD_CONDITION_VARIABLE_HPP + +// condition_variable.hpp +// +// (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/platform.hpp> +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include <boost/thread/win32/condition_variable.hpp> +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include <boost/thread/pthread/condition_variable.hpp> +#else +#error "Boost threads unavailable on this platform" +#endif + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/deque.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/deque.hpp new file mode 100644 index 00000000000..2b26a46e1ac --- /dev/null +++ b/src/third_party/boost-1.60.0/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_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/src/third_party/boost-1.60.0/boost/thread/csbl/devector.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/devector.hpp new file mode 100644 index 00000000000..c2bc0bbe992 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/devector.hpp @@ -0,0 +1,102 @@ +// 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_DEVECTOR_HPP +#define BOOST_CSBL_DEVECTOR_HPP + +#include <boost/config.hpp> + +#include <boost/thread/csbl/vector.hpp> +#include <boost/move/detail/move_helpers.hpp> + +namespace boost +{ + namespace csbl + { + template <class T> + class devector + { + typedef csbl::vector<T> vector_type; + vector_type data_; + std::size_t front_index_; + + BOOST_COPYABLE_AND_MOVABLE(devector) + + template <class U> + void priv_push_back(BOOST_FWD_REF(U) x) + { data_.push_back(boost::forward<U>(x)); } + + public: + typedef typename vector_type::size_type size_type; + typedef typename vector_type::reference reference; + typedef typename vector_type::const_reference const_reference; + + + devector() : front_index_(0) {} + devector(devector const& x) BOOST_NOEXCEPT + : data_(x.data_), + front_index_(x.front_index_) + {} + devector(BOOST_RV_REF(devector) x) BOOST_NOEXCEPT + : data_(boost::move(x.data_)), + front_index_(x.front_index_) + {} + + devector& operator=(BOOST_COPY_ASSIGN_REF(devector) x) + { + if (&x != this) + { + data_ = x.data_; + front_index_ = x.front_index_; + } + return *this; + } + + devector& operator=(BOOST_RV_REF(devector) x) +#if defined BOOST_THREAD_USES_BOOST_VECTOR + BOOST_NOEXCEPT_IF(vector_type::allocator_traits_type::propagate_on_container_move_assignment::value) +#endif + { + data_ = boost::move(x.data_); + front_index_ = x.front_index_; + return *this; + } + + bool empty() const BOOST_NOEXCEPT + { return data_.size() == front_index_; } + + size_type size() const BOOST_NOEXCEPT + { return data_.size() - front_index_; } + + reference front() BOOST_NOEXCEPT + { return data_[front_index_]; } + + const_reference front() const BOOST_NOEXCEPT + { return data_[front_index_]; } + + reference back() BOOST_NOEXCEPT + { return data_.back(); } + + const_reference back() const BOOST_NOEXCEPT + { return data_.back(); } + + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back) + + void pop_front() + { + ++front_index_; + if (empty()) { + data_.clear(); + front_index_=0; + } + } + + }; + } +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/functional.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/functional.hpp new file mode 100644 index 00000000000..7a7e928b70f --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/list.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/list.hpp new file mode 100644 index 00000000000..52ff45d3497 --- /dev/null +++ b/src/third_party/boost-1.60.0/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_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/src/third_party/boost-1.60.0/boost/thread/csbl/memory.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory.hpp new file mode 100644 index 00000000000..e076f11ad30 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_arg.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_arg.hpp new file mode 100644 index 00000000000..354cdaee885 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_traits.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_traits.hpp new file mode 100644 index 00000000000..3737cd85def --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/memory/config.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/config.hpp new file mode 100644 index 00000000000..7b0596ac490 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/memory/default_delete.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/default_delete.hpp new file mode 100644 index 00000000000..d20153b3096 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/memory/pointer_traits.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/pointer_traits.hpp new file mode 100644 index 00000000000..320f8e9e774 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/memory/scoped_allocator.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/scoped_allocator.hpp new file mode 100644 index 00000000000..a92f3d85146 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/memory/shared_ptr.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/shared_ptr.hpp new file mode 100644 index 00000000000..e9a9383723a --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/memory/unique_ptr.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/unique_ptr.hpp new file mode 100644 index 00000000000..17abf54e92a --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/queue.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/queue.hpp new file mode 100644 index 00000000000..1aa645d18fb --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/queue.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2015 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_QUEUE_HPP +#define BOOST_CSBL_QUEUE_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_QUEUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827) +#ifndef BOOST_THREAD_USES_BOOST_QUEUE +#define BOOST_THREAD_USES_BOOST_QUEUE +#endif +#include <boost/container/queue.hpp> +#else +#include <queue> +#endif + +namespace boost +{ + namespace csbl + { +#if defined BOOST_THREAD_USES_BOOST_QUEUE + using ::boost::container::queue; + +#else + using ::std::queue; + +#endif + + } +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/tuple.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/tuple.hpp new file mode 100644 index 00000000000..860229ebe0b --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/csbl/vector.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/vector.hpp new file mode 100644 index 00000000000..c77a5b143bb --- /dev/null +++ b/src/third_party/boost-1.60.0/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_RVALUE_REFERENCES || defined BOOST_MSVC +#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/src/third_party/boost-1.60.0/boost/thread/cv_status.hpp b/src/third_party/boost-1.60.0/boost/thread/cv_status.hpp new file mode 100644 index 00000000000..e52de4a5220 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/cv_status.hpp @@ -0,0 +1,26 @@ +// cv_status.hpp +// +// Copyright (C) 2011 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_CV_STATUS_HPP +#define BOOST_THREAD_CV_STATUS_HPP + +#include <boost/core/scoped_enum.hpp> + +namespace boost +{ + + // enum class cv_status; + BOOST_SCOPED_ENUM_DECLARE_BEGIN(cv_status) + { + no_timeout, + timeout + } + BOOST_SCOPED_ENUM_DECLARE_END(cv_status) +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/config.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/config.hpp new file mode 100644 index 00000000000..475dadbaaa0 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/config.hpp @@ -0,0 +1,465 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// 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) + +#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP +#define BOOST_THREAD_CONFIG_WEK01032003_HPP + +#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) \ + && ! 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) \ + && ! 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 \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS +#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS +#endif + +#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_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 + +/// 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 && BOOST_THREAD_VERSION!=4 +#error "BOOST_THREAD_VERSION must be 2, 3 or 4" +#endif +#endif + +// 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 + +#if ! defined BOOST_THREAD_DONT_USE_ATOMIC \ + && ! defined BOOST_THREAD_USES_ATOMIC +#define BOOST_THREAD_USES_ATOMIC +//#define BOOST_THREAD_DONT_USE_ATOMIC +#endif + +#if defined BOOST_THREAD_USES_ATOMIC +// Andrey Semashev +#define BOOST_THREAD_ONCE_ATOMIC +#else +//#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 + +// PROVIDE_PROMISE_LAZY +#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY \ + && ! defined BOOST_THREAD_PROVIDES_PROMISE_LAZY +#define BOOST_THREAD_PROVIDES_PROMISE_LAZY +#endif + +// 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 + +// 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 + +// 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 + +// 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 + +// PROVIDE_FUTURE +#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE \ + && ! defined BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_PROVIDES_FUTURE +#endif + +// 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 + +// 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 + +// 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 + +// 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 + +// 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 \ +&& ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#endif + +// 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_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) +# pragma warn -8008 // Condition always true/false +# pragma warn -8080 // Identifier declared but never used +# pragma warn -8057 // Parameter never used +# pragma warn -8066 // Unreachable code +#endif + +#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) && ! 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 +# if !defined(BOOST_THREAD_USE_DLL) +# define BOOST_THREAD_USE_DLL +# endif +#endif + +#if defined(BOOST_THREAD_BUILD_DLL) //Build dll +#elif defined(BOOST_THREAD_BUILD_LIB) //Build lib +#elif defined(BOOST_THREAD_USE_DLL) //Use dll +#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) \ + || 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 + //For compilers not yet supporting auto-tss cleanup + //with Boost.Threads lib, use Boost.Threads dll +# define BOOST_THREAD_USE_DLL +# endif +# else +# define BOOST_THREAD_USE_LIB +# endif +#endif + +#if defined(BOOST_HAS_DECLSPEC) +# if defined(BOOST_THREAD_BUILD_DLL) //Build dll +# define BOOST_THREAD_DECL BOOST_SYMBOL_EXPORT +//# define BOOST_THREAD_DECL __declspec(dllexport) + +# elif defined(BOOST_THREAD_USE_DLL) //Use dll +# define BOOST_THREAD_DECL BOOST_SYMBOL_IMPORT +//# define BOOST_THREAD_DECL __declspec(dllimport) +# else +# define BOOST_THREAD_DECL +# endif +#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# define BOOST_THREAD_DECL BOOST_SYMBOL_VISIBLE + +#else +# define BOOST_THREAD_DECL +#endif // BOOST_HAS_DECLSPEC + +// +// Automatically link to the correct build variant where possible. +// +#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB) +// +// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#if defined(BOOST_THREAD_USE_DLL) +# define BOOST_DYN_LINK +#endif +// +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#if defined(BOOST_THREAD_LIB_NAME) +# define BOOST_LIB_NAME BOOST_THREAD_LIB_NAME +#else +# define BOOST_LIB_NAME boost_thread +#endif +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +// And include the header that does the work: +// +#include <boost/config/auto_link.hpp> +#endif // auto-linking disabled + +#endif // BOOST_THREAD_CONFIG_WEK1032003_HPP + +// Change Log: +// 22 Jan 05 Roland Schwarz (speedsnail) +// Usage of BOOST_HAS_DECLSPEC macro. +// Default again is static lib usage. +// BOOST_DYN_LINK only defined when autolink included. diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/counter.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/counter.hpp new file mode 100644 index 00000000000..38e1597c574 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/detail/delete.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/delete.hpp new file mode 100644 index 00000000000..8f8113f4e87 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/delete.hpp @@ -0,0 +1,58 @@ +// 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_DELETE_HPP +#define BOOST_THREAD_DETAIL_DELETE_HPP + +#include <boost/config.hpp> + +/** + * BOOST_THREAD_DELETE_COPY_CTOR deletes the copy constructor when the compiler supports it or + * makes it private. + * + * BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or + * makes it private. + */ + +#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_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&); \ + public: + +#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \ + private: \ + CLASS& operator=(CLASS&); \ + public: +#endif +#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS + +/** + * BOOST_THREAD_NO_COPYABLE deletes the copy constructor and assignment when the compiler supports it or + * makes them private. + */ +#define BOOST_THREAD_NO_COPYABLE(CLASS) \ + BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \ + BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) + +#endif // BOOST_THREAD_DETAIL_DELETE_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/force_cast.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/force_cast.hpp new file mode 100644 index 00000000000..d5d15adc1a7 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/force_cast.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2001-2003 +// Mac Murrett +// +// 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 for most recent version including documentation. + +#ifndef BOOST_FORCE_CAST_MJM012402_HPP +#define BOOST_FORCE_CAST_MJM012402_HPP + +#include <boost/thread/detail/config.hpp> + +namespace boost { +namespace detail { +namespace thread { + +// force_cast will convert anything to anything. + +// general case +template<class Return_Type, class Argument_Type> +inline Return_Type &force_cast(Argument_Type &rSrc) +{ + return(*reinterpret_cast<Return_Type *>(&rSrc)); +} + +// specialization for const +template<class Return_Type, class Argument_Type> +inline const Return_Type &force_cast(const Argument_Type &rSrc) +{ + return(*reinterpret_cast<const Return_Type *>(&rSrc)); +} + +} // namespace thread +} // namespace detail +} // namespace boost + +#endif // BOOST_FORCE_CAST_MJM012402_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/function_wrapper.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/function_wrapper.hpp new file mode 100644 index 00000000000..355f726762b --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/detail/invoke.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/invoke.hpp new file mode 100644 index 00000000000..e772da29ee9 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/detail/invoker.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/invoker.hpp new file mode 100644 index 00000000000..9f38e9798dd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/invoker.hpp @@ -0,0 +1,762 @@ +// 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) + { + if (this != &f) + { + f_ = boost::move(BOOST_THREAD_RV(f).f_); + } + return *this; + } + + BOOST_SYMBOL_VISIBLE + invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f) + { + if (this != &f) + { + f_ = f.f_; + } + return *this; + } + + 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 detail::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 detail::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 && defined(BOOST_THREAD_PROVIDES_INVOKE) + +#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 detail::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 detail::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 detail::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 detail::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 detail::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 detail::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 detail::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 detail::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 detail::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 detail::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/src/third_party/boost-1.60.0/boost/thread/detail/is_convertible.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/is_convertible.hpp new file mode 100644 index 00000000000..b77620cf179 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/detail/lockable_wrapper.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/lockable_wrapper.hpp new file mode 100644 index 00000000000..8dc5a6cc786 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/detail/log.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/log.hpp new file mode 100644 index 00000000000..84dcc8cb41f --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/detail/make_tuple_indices.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/make_tuple_indices.hpp new file mode 100644 index 00000000000..73d54f11f81 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/detail/memory.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/memory.hpp new file mode 100644 index 00000000000..51ce84f40bc --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/memory.hpp @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////////////// +// +// 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_MEMORY_HPP +#define BOOST_THREAD_DETAIL_MEMORY_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 + { + template <class _Alloc> + class allocator_destructor + { + 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_; + size_type s_; + public: + allocator_destructor(_Alloc& a, size_type s)BOOST_NOEXCEPT + : alloc_(a), s_(s) + {} + void operator()(pointer p)BOOST_NOEXCEPT + { + alloc_traits::destroy(alloc_, p); + alloc_traits::deallocate(alloc_, p, s_); + } + }; + } //namespace thread_detail +} +#endif // BOOST_THREAD_DETAIL_MEMORY_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/move.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/move.hpp new file mode 100644 index 00000000000..26e4f9dc6dd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/move.hpp @@ -0,0 +1,374 @@ +// 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-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_MOVE_HPP +#define BOOST_THREAD_MOVE_HPP + +#include <boost/thread/detail/config.hpp> +#ifndef BOOST_NO_SFINAE +#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/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 enable_move_utility_emulation_dummy_specialization; + template<typename T> + struct thread_move_t + { + T& t; + explicit thread_move_t(T& t_): + t(t_) + {} + + T& operator*() const + { + return t; + } + + T* operator->() const + { + return &t; + } + private: + void operator=(thread_move_t&); + }; + } + +#if !defined BOOST_THREAD_USES_MOVE + +#ifndef BOOST_NO_SFINAE + template<typename T> + typename enable_if<boost::is_convertible<T&,boost::detail::thread_move_t<T> >, boost::detail::thread_move_t<T> >::type move(T& t) + { + return boost::detail::thread_move_t<T>(t); + } +#endif + + template<typename T> + boost::detail::thread_move_t<T> move(boost::detail::thread_move_t<T> t) + { + return t; + } + +#endif //#if !defined BOOST_THREAD_USES_MOVE +} + +#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 +#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) +#define BOOST_THREAD_DCL_MOVABLE(TYPE) +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ + namespace detail { \ + template <typename T> \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ + namespace detail { \ + template <typename T1, typename T2> \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ + : integral_constant<bool, false> \ + {}; \ + } + +#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 +#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) +#define BOOST_THREAD_DCL_MOVABLE(TYPE) +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ + namespace detail { \ + template <typename T> \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ + namespace detail { \ + template <typename T1, typename T2> \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ + : 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 +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) +#define BOOST_THREAD_DCL_MOVABLE(TYPE) +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ + namespace detail { \ + template <typename T> \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ + namespace detail { \ + template <typename T1, typename T2> \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ + : 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 > +#define BOOST_THREAD_RV(V) (*V) +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) + +#define BOOST_THREAD_DCL_MOVABLE(TYPE) \ +template <> \ +struct enable_move_utility_emulation< TYPE > \ +{ \ + static const bool value = false; \ +}; + +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ +template <typename T> \ +struct enable_move_utility_emulation< + +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ +template <typename T1, typename T2> \ +struct enable_move_utility_emulation< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ +{ \ + static const bool value = false; \ +}; + +#endif + +namespace boost +{ +namespace detail +{ + template <typename T> + BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type) + make_rv_ref(T v) BOOST_NOEXCEPT + { + return (BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v); + } +// template <typename T> +// BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type) +// make_rv_ref(T &v) BOOST_NOEXCEPT +// { +// return (BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v); +// } +// template <typename T> +// const BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type) +// make_rv_ref(T const&v) BOOST_NOEXCEPT +// { +// return (const BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v); +// } +} +} + +#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE.move() +//#define BOOST_THREAD_MAKE_RV_REF(RVALUE) boost::detail::make_rv_ref(RVALUE) +#endif + + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + +#define BOOST_THREAD_MOVABLE(TYPE) + +#define BOOST_THREAD_COPYABLE(TYPE) + +#else + +#if defined BOOST_THREAD_USES_MOVE + +#define BOOST_THREAD_MOVABLE(TYPE) \ + ::boost::rv<TYPE>& move() BOOST_NOEXCEPT \ + { \ + return *static_cast< ::boost::rv<TYPE>* >(this); \ + } \ + const ::boost::rv<TYPE>& move() const BOOST_NOEXCEPT \ + { \ + return *static_cast<const ::boost::rv<TYPE>* >(this); \ + } \ + operator ::boost::rv<TYPE>&() \ + { \ + return *static_cast< ::boost::rv<TYPE>* >(this); \ + } \ + operator const ::boost::rv<TYPE>&() const \ + { \ + 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) \ + operator ::boost::detail::thread_move_t<TYPE>() BOOST_NOEXCEPT \ + { \ + return move(); \ + } \ + ::boost::detail::thread_move_t<TYPE> move() BOOST_NOEXCEPT \ + { \ + ::boost::detail::thread_move_t<TYPE> x(*this); \ + 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_COPYABLE(TYPE) \ + BOOST_THREAD_MOVABLE(TYPE) \ + + + +namespace boost +{ + 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> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/nullary_function.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/nullary_function.hpp new file mode 100644 index 00000000000..b3989cf682e --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/detail/platform.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/platform.hpp new file mode 100644 index 00000000000..1f33b1a67ae --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/platform.hpp @@ -0,0 +1,73 @@ +// Copyright 2006 Roland Schwarz. +// (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) +// +// This work is a reimplementation along the design and ideas +// of William E. Kempf. + +#ifndef BOOST_THREAD_RS06040501_HPP +#define BOOST_THREAD_RS06040501_HPP + +// fetch compiler and platform configuration +#include <boost/config.hpp> + +// insist on threading support being available: +#include <boost/config/requires_threads.hpp> + +// choose platform +#if defined(linux) || defined(__linux) || defined(__linux__) +# define BOOST_THREAD_LINUX +//# define BOOST_THREAD_WAIT_BUG boost::posix_time::microseconds(100000) +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +# define BOOST_THREAD_BSD +#elif defined(sun) || defined(__sun) +# define BOOST_THREAD_SOLARIS +#elif defined(__sgi) +# define BOOST_THREAD_IRIX +#elif defined(__hpux) +# define BOOST_THREAD_HPUX +#elif defined(__CYGWIN__) +# define BOOST_THREAD_CYGWIN +#elif (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(BOOST_DISABLE_WIN32) +# define BOOST_THREAD_WIN32 +#elif defined(__BEOS__) +# define BOOST_THREAD_BEOS +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +# define BOOST_THREAD_MACOS +//# define BOOST_THREAD_WAIT_BUG boost::posix_time::microseconds(1000) +#elif defined(__IBMCPP__) || defined(_AIX) +# define BOOST_THREAD_AIX +#elif defined(__amigaos__) +# define BOOST_THREAD_AMIGAOS +#elif defined(__QNXNTO__) +# define BOOST_THREAD_QNXNTO +#elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) +# if defined(BOOST_HAS_PTHREADS) && !defined(BOOST_THREAD_POSIX) +# define BOOST_THREAD_POSIX +# endif +#endif + +// For every supported platform add a new entry into the dispatch table below. +// BOOST_THREAD_POSIX is tested first, so on platforms where posix and native +// threading is available, the user may choose, by defining BOOST_THREAD_POSIX +// in her source. If a platform is known to support pthreads and no native +// port of boost_thread is available just specify "pthread" in the +// dispatcher table. If there is no entry for a platform but pthreads is +// available on the platform, pthread is choosen as default. If nothing is +// available the preprocessor will fail with a diagnostic message. + +#if defined(BOOST_THREAD_POSIX) +# define BOOST_THREAD_PLATFORM_PTHREAD +#else +# if defined(BOOST_THREAD_WIN32) +# define BOOST_THREAD_PLATFORM_WIN32 +# elif defined(BOOST_HAS_PTHREADS) +# define BOOST_THREAD_PLATFORM_PTHREAD +# else +# error "Sorry, no boost threads are available for this platform." +# endif +#endif + +#endif // BOOST_THREAD_RS06040501_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/singleton.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/singleton.hpp new file mode 100644 index 00000000000..a20a42908d2 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/singleton.hpp @@ -0,0 +1,59 @@ +// Copyright (C) 2001-2003 +// Mac Murrett +// +// 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 for most recent version including documentation. + +#ifndef BOOST_SINGLETON_MJM012402_HPP +#define BOOST_SINGLETON_MJM012402_HPP + +#include <boost/thread/detail/config.hpp> + +namespace boost { +namespace detail { +namespace thread { + +// class singleton has the same goal as all singletons: create one instance of +// a class on demand, then dish it out as requested. + +template <class T> +class singleton : private T +{ +private: + singleton(); + ~singleton(); + +public: + static T &instance(); +}; + + +template <class T> +inline singleton<T>::singleton() +{ + /* no-op */ +} + +template <class T> +inline singleton<T>::~singleton() +{ + /* no-op */ +} + +template <class T> +/*static*/ T &singleton<T>::instance() +{ + // function-local static to force this to work correctly at static + // initialization time. + static singleton<T> s_oT; + return(s_oT); +} + +} // namespace thread +} // namespace detail +} // namespace boost + +#endif // BOOST_SINGLETON_MJM012402_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/thread.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/thread.hpp new file mode 100644 index 00000000000..9e7e8b8f5e9 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/thread.hpp @@ -0,0 +1,873 @@ +#ifndef BOOST_THREAD_THREAD_COMMON_HPP +#define BOOST_THREAD_THREAD_COMMON_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 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/core/ref.hpp> +#include <boost/cstdint.hpp> +#include <boost/bind.hpp> +#include <stdlib.h> +#include <memory> +#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> +#include <boost/type_traits/decay.hpp> +#include <boost/functional/hash.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#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 +#pragma warning(push) +#pragma warning(disable:4251) +#endif + +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...>) + { + + detail::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_CXX11_RVALUE_REFERENCES + thread_data(BOOST_THREAD_RV_REF(F) f_): + f(boost::forward<F>(f_)) + {} +// This overloading must be removed if we want the packaged_task's tests to pass. +// thread_data(F& f_): +// f(f_) +// {} +#else + + thread_data(BOOST_THREAD_RV_REF(F) f_): + f(f_) + {} + thread_data(F f_): + f(f_) + {} +#endif + //thread_data() {} + + void run() + { + f(); + } + + private: + F f; + }; + + template<typename F> + class thread_data<boost::reference_wrapper<F> >: + public detail::thread_data_base + { + private: + F& f; + public: + BOOST_THREAD_NO_COPYABLE(thread_data) + thread_data(boost::reference_wrapper<F> f_): + f(f_) + {} + void run() + { + f(); + } + }; + + template<typename F> + class thread_data<const boost::reference_wrapper<F> >: + public detail::thread_data_base + { + private: + F& f; + public: + BOOST_THREAD_NO_COPYABLE(thread_data) + thread_data(const boost::reference_wrapper<F> f_): + f(f_) + {} + void run() + { + f(); + } + }; +#endif + } + + class BOOST_THREAD_DECL thread + { + public: + typedef thread_attributes attributes; + + BOOST_THREAD_MOVABLE_ONLY(thread) + private: + + struct dummy; + + void release_handle(); + + detail::thread_data_ptr thread_info; + + private: + bool start_thread_noexcept(); + bool start_thread_noexcept(const attributes& attr); + 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_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(*)()> >( + boost::forward<void(*)()>(f))); + } +#else + template<typename 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)); + } + 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<F> >(f)); + } + +#endif + public: +#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + thread(const volatile thread&); +#endif +#endif + thread() BOOST_NOEXCEPT; + ~thread() + { + + #if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE + if (joinable()) { + std::terminate(); + } + #else + detach(); + #endif + } +#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 + ): + thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f)))) + { + start_thread(); + } + template < + class 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); + } + +#else +#ifdef BOOST_NO_SFINAE + template <class F> + explicit thread(F f): + thread_info(make_thread_info(f)) + { + start_thread(); + } + template <class F> + thread(attributes const& attrs, F f): + thread_info(make_thread_info(f)) + { + start_thread(attrs); + } +#else + template <class F> + explicit thread(F f + , 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 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); + } +#endif + template <class F> + explicit thread(BOOST_THREAD_RV_REF(F) f + , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0 + ): +#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 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) BOOST_NOEXCEPT + { + thread_info=BOOST_THREAD_RV(x).thread_info; + BOOST_THREAD_RV(x).thread_info.reset(); + } +#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + thread& operator=(thread x) + { + swap(x); + return *this; + } +#endif +#endif + + thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT + { + +#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE + if (joinable()) std::terminate(); +#else + detach(); +#endif + thread_info=BOOST_THREAD_RV(other).thread_info; + BOOST_THREAD_RV(other).thread_info.reset(); + 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::thread_detail::is_convertible<F&,thread_attributes >, dummy* >::type=0): + thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1))) + { + start_thread(); + } + template <class F,class A1,class A2> + thread(F f,A1 a1,A2 a2): + thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2))) + { + start_thread(); + } + + template <class F,class A1,class A2,class A3> + thread(F f,A1 a1,A2 a2,A3 a3): + thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3))) + { + start_thread(); + } + + template <class F,class A1,class A2,class A3,class A4> + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4): + thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4))) + { + start_thread(); + } + + template <class F,class A1,class A2,class A3,class A4,class A5> + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5): + thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5))) + { + start_thread(); + } + + template <class F,class A1,class A2,class A3,class A4,class A5,class A6> + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6): + thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6))) + { + start_thread(); + } + + template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7> + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7): + thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7))) + { + start_thread(); + } + + template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8> + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8): + thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8))) + { + start_thread(); + } + + template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9> + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9): + thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9))) + { + start_thread(); + } +#endif + void swap(thread& x) BOOST_NOEXCEPT + { + thread_info.swap(x.thread_info); + } + + 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; + 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; + bool joined= false; + do { + system_clock::time_point s_now = system_clock::now(); + typename Clock::duration d = ceil<nanoseconds>(t-Clock::now()); + if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached + joined = try_join_until(s_now + d); + } while (! joined); + return true; + } + template <class Duration> + bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; + return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + } +#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) + { + chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now()); + return do_try_join_until(rel_time.count()); + } +#endif + + +#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::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 = boost::detail::to_timespec(d); + return do_try_join_until(ts); + } +#endif + +#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); + } +#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_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(); + } + + static inline void sleep(const system_time& xt) + { + 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 + { + return lhs.swap(rhs); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + inline thread&& move(thread& t) BOOST_NOEXCEPT + { + return static_cast<thread&&>(t); + } +#endif + + BOOST_THREAD_DCL_MOVABLE(thread) + + 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 + { + private: + friend inline + std::size_t + hash_value(const thread::id &v) + { +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + return hash_value(v.thread_data); +#else + return hash_value(v.thread_data.get()); +#endif + } + +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID +#if defined(BOOST_THREAD_PLATFORM_WIN32) + typedef unsigned int data; +#else + typedef thread::native_handle_type data; +#endif +#else + typedef detail::thread_data_ptr data; +#endif + data thread_data; + + id(data thread_data_): + thread_data(thread_data_) + {} + friend class thread; + friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT; + public: + id() BOOST_NOEXCEPT: +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + thread_data(0) +#else + thread_data() +#endif + {} + + id(const id& other) BOOST_NOEXCEPT : + thread_data(other.thread_data) + {} + + bool operator==(const id& y) const BOOST_NOEXCEPT + { + return thread_data==y.thread_data; + } + + bool operator!=(const id& y) const BOOST_NOEXCEPT + { + return thread_data!=y.thread_data; + } + + bool operator<(const id& y) const BOOST_NOEXCEPT + { + return thread_data<y.thread_data; + } + + bool operator>(const id& y) const BOOST_NOEXCEPT + { + return y.thread_data<thread_data; + } + + bool operator<=(const id& y) const BOOST_NOEXCEPT + { + return !(y.thread_data<thread_data); + } + + bool operator>=(const id& y) const BOOST_NOEXCEPT + { + return !(thread_data<y.thread_data); + } + +#ifndef BOOST_NO_IOSTREAM +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + template<class charT, class traits> + friend BOOST_SYMBOL_VISIBLE + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const id& x) + { + if(x.thread_data) + { + io::ios_flags_saver ifs( os ); + return os<< std::hex << x.thread_data; + } + else + { + return os<<"{Not-any-thread}"; + } + } +#else + template<class charT, class traits> + BOOST_SYMBOL_VISIBLE + std::basic_ostream<charT, traits>& + print(std::basic_ostream<charT, traits>& os) const + { + if(thread_data) + { + io::ios_flags_saver ifs( os ); + return os<< std::hex << thread_data; + } + else + { + return os<<"{Not-any-thread}"; + } + } + +#endif +#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 + std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x) + { + return x.print(os); + } +#endif + +#if defined BOOST_THREAD_PROVIDES_THREAD_EQ + inline bool thread::operator==(const thread& other) const + { + return get_id()==other.get_id(); + } + + inline bool thread::operator!=(const thread& other) const + { + return get_id()!=other.get_id(); + } +#endif + + namespace detail + { + struct thread_exit_function_base + { + virtual ~thread_exit_function_base() + {} + virtual void operator()()=0; + }; + + template<typename F> + struct thread_exit_function: + thread_exit_function_base + { + F f; + + thread_exit_function(F f_): + f(f_) + {} + + void operator()() + { + f(); + } + }; + + 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 + { + template<typename F> + void at_thread_exit(F f) + { + detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f); + detail::add_thread_exit_function(thread_exit_func); + } + } +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/thread_group.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/thread_group.hpp new file mode 100644 index 00000000000..4105c734688 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/thread_group.hpp @@ -0,0 +1,155 @@ +#ifndef BOOST_THREAD_DETAIL_THREAD_GROUP_HPP +#define BOOST_THREAD_DETAIL_THREAD_GROUP_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 2007-9 Anthony Williams + +#include <list> +#include <boost/thread/csbl/memory/unique_ptr.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_guard.hpp> + +#include <boost/config/abi_prefix.hpp> + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4251) +#endif + +namespace boost +{ + class thread_group + { + private: + thread_group(thread_group const&); + thread_group& operator=(thread_group const&); + public: + thread_group() {} + ~thread_group() + { + for(std::list<thread*>::iterator it=threads.begin(),end=threads.end(); + it!=end; + ++it) + { + delete *it; + } + } + + 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) + { + boost::lock_guard<shared_mutex> guard(m); + boost::csbl::unique_ptr<thread> new_thread(new thread(threadfunc)); + 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); + std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd); + if(it!=threads.end()) + { + 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) + { + (*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; + }; +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/thread_heap_alloc.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/thread_heap_alloc.hpp new file mode 100644 index 00000000000..2f9bfd5c0b6 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/thread_heap_alloc.hpp @@ -0,0 +1,23 @@ +#ifndef BOOST_THREAD_THREAD_HEAP_ALLOC_HPP +#define BOOST_THREAD_THREAD_HEAP_ALLOC_HPP + +// thread_heap_alloc.hpp +// +// (C) Copyright 2008 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/platform.hpp> + +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include <boost/thread/win32/thread_heap_alloc.hpp> +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include <boost/thread/pthread/thread_heap_alloc.hpp> +#else +#error "Boost threads unavailable on this platform" +#endif + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/thread_interruption.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/thread_interruption.hpp new file mode 100644 index 00000000000..5d7d10fecdf --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/thread_interruption.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_THREAD_DETAIL_THREAD_INTERRUPTION_HPP +#define BOOST_THREAD_DETAIL_THREAD_INTERRUPTION_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 2007-9 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/detail/delete.hpp> + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + +namespace boost +{ + namespace this_thread + { + class BOOST_THREAD_DECL disable_interruption + { + bool interruption_was_enabled; + friend class restore_interruption; + public: + BOOST_THREAD_NO_COPYABLE(disable_interruption) + disable_interruption() BOOST_NOEXCEPT; + ~disable_interruption() BOOST_NOEXCEPT; + }; + + class BOOST_THREAD_DECL restore_interruption + { + public: + BOOST_THREAD_NO_COPYABLE(restore_interruption) + explicit restore_interruption(disable_interruption& d) BOOST_NOEXCEPT; + ~restore_interruption() BOOST_NOEXCEPT; + }; + } +} + +#endif // BOOST_THREAD_PROVIDES_INTERRUPTIONS +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/tss_hooks.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/tss_hooks.hpp new file mode 100644 index 00000000000..b2ceece3ddd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/tss_hooks.hpp @@ -0,0 +1,65 @@ +// (C) Copyright Michael Glassford 2004. +// Use, modification and distribution are subject to 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_TLS_HOOKS_HPP) +#define BOOST_TLS_HOOKS_HPP + +#include <boost/thread/detail/config.hpp> + +#include <boost/config/abi_prefix.hpp> + +#if defined(BOOST_HAS_WINTHREADS) + +namespace boost +{ + BOOST_THREAD_DECL void __cdecl on_process_enter(void); + //Function to be called when the exe or dll + //that uses Boost.Threads first starts + //or is first loaded. + //Should be called only before the first call to + //on_thread_enter(). + //Called automatically by Boost.Threads when + //a method for doing so has been discovered. + //May be omitted; may be called multiple times. + + BOOST_THREAD_DECL void __cdecl on_process_exit(void); + //Function to be called when the exe or dll + //that uses Boost.Threads first starts + //or is first loaded. + //Should be called only after the last call to + //on_exit_thread(). + //Called automatically by Boost.Threads when + //a method for doing so has been discovered. + //Must not be omitted; may be called multiple times. + + BOOST_THREAD_DECL void __cdecl on_thread_enter(void); + //Function to be called just after a thread starts + //in an exe or dll that uses Boost.Threads. + //Must be called in the context of the thread + //that is starting. + //Called automatically by Boost.Threads when + //a method for doing so has been discovered. + //May be omitted; may be called multiple times. + + BOOST_THREAD_DECL void __cdecl on_thread_exit(void); + //Function to be called just be fore a thread ends + //in an exe or dll that uses Boost.Threads. + //Must be called in the context of the thread + //that is ending. + //Called automatically by Boost.Threads when + //a method for doing so has been discovered. + //Must not be omitted; may be called multiple times. + + void tss_cleanup_implemented(); + //Dummy function used both to detect whether tss cleanup + //cleanup has been implemented and to force + //it to be linked into the Boost.Threads library. +} + +#endif //defined(BOOST_HAS_WINTHREADS) + +#include <boost/config/abi_suffix.hpp> + +#endif //!defined(BOOST_TLS_HOOKS_HPP) diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/variadic_footer.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/variadic_footer.hpp new file mode 100644 index 00000000000..9ae25a847c3 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/detail/variadic_header.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/variadic_header.hpp new file mode 100644 index 00000000000..8015ae33cc2 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/exceptional_ptr.hpp b/src/third_party/boost-1.60.0/boost/thread/exceptional_ptr.hpp new file mode 100644 index 00000000000..49547923d92 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/exceptions.hpp b/src/third_party/boost-1.60.0/boost/thread/exceptions.hpp new file mode 100644 index 00000000000..d97465b754e --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/exceptions.hpp @@ -0,0 +1,225 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007-9 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_EXCEPTIONS_PDM070801_H +#define BOOST_THREAD_EXCEPTIONS_PDM070801_H + +#include <boost/thread/detail/config.hpp> + +// pdm: Sorry, but this class is used all over the place & I end up +// with recursive headers if I don't separate it +// wek: Not sure why recursive headers would cause compilation problems +// given the include guards, but regardless it makes sense to +// seperate this out any way. + +#include <string> +#include <stdexcept> +#include <boost/system/system_error.hpp> +#include <boost/system/error_code.hpp> + + +#include <boost/config/abi_prefix.hpp> + +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 + //public std::exception + { + typedef system::system_error base_type; + public: + thread_exception() + : base_type(0,system::system_category()) + {} + + thread_exception(int sys_error_code) + : base_type(sys_error_code, system::system_category()) + {} + + thread_exception( int ev, const char * what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + thread_exception( int ev, const std::string & what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + + ~thread_exception() throw() + {} + + + int native_error() const + { + return code().value(); + } + + }; + + class BOOST_SYMBOL_VISIBLE condition_error: + public system::system_error + //public std::exception + { + typedef system::system_error base_type; + public: + condition_error() + : base_type(system::error_code(0, system::system_category()), "Condition error") + {} + condition_error( int ev ) + : base_type(system::error_code(ev, system::system_category()), "Condition error") + { + } + condition_error( int ev, const char * what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + condition_error( int ev, const std::string & what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + }; + + + class BOOST_SYMBOL_VISIBLE lock_error: + public thread_exception + { + typedef thread_exception base_type; + public: + lock_error() + : base_type(0, "boost::lock_error") + {} + + lock_error( int ev ) + : base_type(ev, "boost::lock_error") + { + } + lock_error( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + lock_error( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + ~lock_error() throw() + {} + + }; + + class BOOST_SYMBOL_VISIBLE thread_resource_error: + public thread_exception + { + typedef thread_exception base_type; + public: + thread_resource_error() + : base_type(static_cast<int>(system::errc::resource_unavailable_try_again), "boost::thread_resource_error") + {} + + thread_resource_error( int ev ) + : base_type(ev, "boost::thread_resource_error") + { + } + thread_resource_error( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + thread_resource_error( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + + ~thread_resource_error() throw() + {} + + }; + + class BOOST_SYMBOL_VISIBLE unsupported_thread_option: + public thread_exception + { + typedef thread_exception base_type; + public: + unsupported_thread_option() + : base_type(static_cast<int>(system::errc::invalid_argument), "boost::unsupported_thread_option") + {} + + unsupported_thread_option( int ev ) + : base_type(ev, "boost::unsupported_thread_option") + { + } + unsupported_thread_option( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + unsupported_thread_option( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + }; + + class BOOST_SYMBOL_VISIBLE invalid_thread_argument: + public thread_exception + { + typedef thread_exception base_type; + public: + invalid_thread_argument() + : base_type(static_cast<int>(system::errc::invalid_argument), "boost::invalid_thread_argument") + {} + + invalid_thread_argument( int ev ) + : base_type(ev, "boost::invalid_thread_argument") + { + } + invalid_thread_argument( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + invalid_thread_argument( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + }; + + class BOOST_SYMBOL_VISIBLE thread_permission_error: + public thread_exception + { + typedef thread_exception base_type; + public: + thread_permission_error() + : base_type(static_cast<int>(system::errc::permission_denied), "boost::thread_permission_error") + {} + + thread_permission_error( int ev ) + : base_type(ev, "boost::thread_permission_error") + { + } + thread_permission_error( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + thread_permission_error( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + }; + +} // namespace boost + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executor.hpp new file mode 100644 index 00000000000..c2b85a0eabe --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/executors/basic_thread_pool.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/basic_thread_pool.hpp new file mode 100644 index 00000000000..e0d4df2c76b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/basic_thread_pool.hpp @@ -0,0 +1,318 @@ +// 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/thread.hpp> +#include <boost/thread/concurrent_queues/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: + typedef thread thread_t; + /// A move aware vector type + typedef csbl::vector<thread_t> thread_vector; + + /// A move aware vector + thread_vector threads; + /// the thread safe work queue + concurrent::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() + { + try + { + work task; + if (work_queue.try_pull(task) == queue_op_status::success) + { + task(); + return true; + } + return false; + } + catch (...) + { + std::terminate(); + //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(task); + if (st == queue_op_status::closed) { + return; + } + task(); + } + } + catch (...) + { + std::terminate(); + 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()+1) + { + 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 before destroying the thread pool resources (e.g. the queue). + join(); + } + + /** + * \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. + */ + void submit(BOOST_THREAD_RV_REF(work) closure) { + work_queue.push(boost::move(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_FWD_REF(Closure) closure) + { + //submit(work(boost::forward<Closure>(closure))); + work w((boost::forward<Closure>(closure))); + submit(boost::move(w)); + } + + /** + * \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/src/third_party/boost-1.60.0/boost/thread/executors/detail/priority_executor_base.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/detail/priority_executor_base.hpp new file mode 100644 index 00000000000..2191c0b37a3 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/detail/priority_executor_base.hpp @@ -0,0 +1,77 @@ +// Copyright (C) 2014 Ian Forbed +// 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_DETAIL_PRIORITY_EXECUTOR_BASE_HPP +#define BOOST_THREAD_EXECUTORS_DETAIL_PRIORITY_EXECUTOR_BASE_HPP + +#include <boost/atomic.hpp> +#include <boost/function.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/concurrent_queues/sync_timed_queue.hpp> +#include <boost/thread/executors/work.hpp> + +namespace boost +{ +namespace executors +{ +namespace detail +{ + template <class Queue> + class priority_executor_base + { + public: + //typedef boost::function<void()> work; + typedef executors::work_pq work; + protected: + typedef Queue queue_type; + queue_type _workq; + + priority_executor_base() {} + public: + + ~priority_executor_base() + { + if(!closed()) + { + this->close(); + } + } + + void close() + { + _workq.close(); + } + + bool closed() + { + return _workq.closed(); + } + + void loop() + { + try + { + for(;;) + { + work task; + queue_op_status st = _workq.wait_pull(task); + if (st == queue_op_status::closed) return; + task(); + } + } + catch (...) + { + std::terminate(); + return; + } + } + }; //end class + +} //end detail namespace +} //end executors namespace +} //end boost namespace +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/detail/scheduled_executor_base.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/detail/scheduled_executor_base.hpp new file mode 100644 index 00000000000..ec0038f7e3e --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/detail/scheduled_executor_base.hpp @@ -0,0 +1,66 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014-2015 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_DETAIL_SCHEDULED_EXECUTOR_BASE_HPP +#define BOOST_THREAD_EXECUTORS_DETAIL_SCHEDULED_EXECUTOR_BASE_HPP + +#include <boost/thread/concurrent_queues/sync_timed_queue.hpp> +#include <boost/thread/executors/detail/priority_executor_base.hpp> +#include <boost/thread/executors/work.hpp> +#include <boost/thread/thread.hpp> + +#include <boost/atomic.hpp> +#include <boost/function.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +namespace executors +{ +namespace detail +{ + template <class Clock=chrono::steady_clock> + class scheduled_executor_base : public priority_executor_base<concurrent::sync_timed_queue<executors::work_pq, Clock > > + { + public: + typedef executors::work_pq work; + typedef Clock clock; + typedef typename clock::duration duration; + typedef typename clock::time_point time_point; + protected: + + scheduled_executor_base() {} + public: + + ~scheduled_executor_base() + { + if(! this->closed()) + { + this->close(); + } + } + + void submit_at(work w, const time_point& tp) + { + this->_workq.push(boost::move(w), tp); + } + + void submit_after(work w, const duration& dura) + { + this->_workq.push(boost::move(w), dura+clock::now()); + } + + }; //end class + +} //end detail namespace +} //end executors namespace +} //end boost namespace + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/executor.hpp new file mode 100644 index 00000000000..96198201f08 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/executor.hpp @@ -0,0 +1,148 @@ +// 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_FWD_REF(Closure) closure) + { + //submit(work(boost::forward<Closure>(closure))); + work w((boost::forward<Closure>(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/src/third_party/boost-1.60.0/boost/thread/executors/executor_adaptor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/executor_adaptor.hpp new file mode 100644 index 00000000000..ca1a35f2d92 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/executor_adaptor.hpp @@ -0,0 +1,136 @@ +// 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)); + } + +#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_FWD_REF(Closure) closure) + { + //submit(work(boost::forward<Closure>(closure))); + work w((boost::forward<Closure>(closure))); + submit(boost::move(w)); + } + + /** + * 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/src/third_party/boost-1.60.0/boost/thread/executors/generic_executor_ref.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/generic_executor_ref.hpp new file mode 100644 index 00000000000..de270bcfed3 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/generic_executor_ref.hpp @@ -0,0 +1,213 @@ +// 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(); } + + /** + * \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. + */ + + void submit(BOOST_THREAD_RV_REF(work) closure) + { + ex->submit(boost::move(closure)); + } + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template <typename Closure> + void submit(Closure & closure) + { + //work w ((closure)); + //submit(boost::move(w)); + submit(work(closure)); + } +#endif + void submit(void (*closure)()) + { + work w ((closure)); + submit(boost::move(w)); + //submit(work(closure)); + } + + template <typename Closure> + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + work w((boost::forward<Closure>(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/src/third_party/boost-1.60.0/boost/thread/executors/inline_executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/inline_executor.hpp new file mode 100644 index 00000000000..5dd523184ed --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/inline_executor.hpp @@ -0,0 +1,171 @@ +// 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_; + mutable mutex mtx_; + /** + * 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() + { + lock_guard<mutex> lk(mtx_); + closed_ = true; + } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed(lock_guard<mutex>& ) + { + return closed_; + } + bool closed() + { + lock_guard<mutex> lk(mtx_); + return closed(lk); + } + + /** + * \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) + { + { + lock_guard<mutex> lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + try + { + closure(); + } + catch (...) + { + std::terminate(); + return; + } + } +#endif + void submit(void (*closure)()) + { + { + lock_guard<mutex> lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + try + { + closure(); + } + catch (...) + { + std::terminate(); + return; + } + } + + template <typename Closure> + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + { + lock_guard<mutex> lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + try + { + closure(); + } + catch (...) + { + std::terminate(); + return; + } + } + + /** + * \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/src/third_party/boost-1.60.0/boost/thread/executors/loop_executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/loop_executor.hpp new file mode 100644 index 00000000000..b08ff76f575 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/loop_executor.hpp @@ -0,0 +1,205 @@ +// 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/concurrent_queues/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 + concurrent::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(task) == queue_op_status::success) + { + task(); + return true; + } + return false; + } + catch (...) + { + std::terminate(); + //return false; + } + } + private: + /** + * Effects: schedule one task or yields + * Throws: whatever the current task constructor throws or the task() throws. + */ + void schedule_one_or_yield() + { + if ( ! try_executing_one()) + { + this_thread::yield(); + } + } + + + + + public: + /// loop_executor is not copyable. + 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(); + } + + /** + * The main loop of the worker thread + */ + void loop() + { + while (!closed()) + { + schedule_one_or_yield(); + } + while (try_executing_one()) + { + } + } + + /** + * \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. + */ + void submit(BOOST_THREAD_RV_REF(work) closure) { + work_queue.push(boost::move(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_FWD_REF(Closure) closure) + { + //work_queue.push(work(boost::forward<Closure>(closure))); + work w((boost::forward<Closure>(closure))); + submit(boost::move(w)); + } + + /** + * \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/src/third_party/boost-1.60.0/boost/thread/executors/scheduled_thread_pool.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/scheduled_thread_pool.hpp new file mode 100644 index 00000000000..408013b283e --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/scheduled_thread_pool.hpp @@ -0,0 +1,48 @@ +// Copyright (C) 2014 Ian Forbed +// 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_SCHEDULED_THREAD_POOL_HPP +#define BOOST_THREAD_EXECUTORS_SCHEDULED_THREAD_POOL_HPP + +#include <boost/thread/executors/detail/scheduled_executor_base.hpp> + +namespace boost +{ +namespace executors +{ + + class scheduled_thread_pool : public detail::scheduled_executor_base<> + { + private: + thread_group _workers; + public: + + scheduled_thread_pool(size_t num_threads) : super() + { + for(size_t i = 0; i < num_threads; i++) + { + _workers.create_thread(bind(&super::loop, this)); + } + } + + ~scheduled_thread_pool() + { + this->close(); + _workers.join_all(); + } + + private: + typedef detail::scheduled_executor_base<> super; + }; //end class + +} //end executors namespace + +using executors::scheduled_thread_pool; + +} //end boost +#endif + diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/scheduler.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/scheduler.hpp new file mode 100644 index 00000000000..5796a7d3947 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/scheduler.hpp @@ -0,0 +1,271 @@ +// 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_SCHEDULER_HPP +#define BOOST_THREAD_EXECUTORS_SCHEDULER_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/executors/detail/scheduled_executor_base.hpp> + +#include <boost/chrono/time_point.hpp> +#include <boost/chrono/duration.hpp> +#include <boost/chrono/system_clocks.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace executors + { + /// Wraps the reference to an executor and a function to make a work that submit the function using the executor. + template <class Executor, class Function> + class resubmitter + { + public: + resubmitter(Executor& ex, Function funct) : + ex(ex), + funct(boost::move(funct)) + {} + + void operator()() + { + ex.submit(funct); + } + + private: + Executor& ex; + Function funct; + }; + + /// resubmitter factory + template <class Executor, class Function> + resubmitter<Executor, typename decay<Function>::type> + resubmit(Executor& ex, BOOST_THREAD_FWD_REF(Function) funct) { + return resubmitter<Executor, typename decay<Function>::type >(ex, boost::move(funct)); + } + + /// Wraps references to a @c Scheduler and an @c Executor providing an @c Executor that + /// resubmit the function using the referenced Executor at a given @c time_point known at construction. + template <class Scheduler, class Executor> + class resubmit_at_executor + { + public: + typedef typename Scheduler::clock clock; + typedef typename Scheduler::work work; + + template <class Duration> + resubmit_at_executor(Scheduler& sch, Executor& ex, chrono::time_point<clock, Duration> const& tp) : + sch(sch), + ex(ex), + tp(tp), + is_closed(false) + { + } + + ~resubmit_at_executor() + { + close(); + } + + template <class Work> + void submit(BOOST_THREAD_FWD_REF(Work) w) + { + if (closed()) + { + BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + sch.submit_at(resubmit(ex,boost::forward<Work>(w)), tp); + } + + Executor& underlying_executor() + { + return ex; + } + Scheduler& underlying_scheduler() + { + return sch; + } + + void close() + { + is_closed = true; + } + + bool closed() + { + return is_closed || sch.closed() || ex.closed(); + } + + private: + Scheduler& sch; + Executor& ex; + typename clock::time_point tp; + bool is_closed; + }; + + + /// Expression template helper storing a pair of references to an @c Scheduler and an @c Executor + /// It provides factory helper functions such as at/after that convert these a pair of @c Scheduler @c Executor + /// into an new @c Executor that submit the work using the referenced @c Executor at/after a specific time/duration + /// respectively, using the referenced @Scheduler. + template <class Scheduler, class Executor> + class scheduler_executor_wrapper + { + public: + typedef typename Scheduler::clock clock; + typedef typename Scheduler::work work; + typedef resubmit_at_executor<Scheduler, Executor> the_executor; + + scheduler_executor_wrapper(Scheduler& sch, Executor& ex) : + sch(sch), + ex(ex) + {} + + ~scheduler_executor_wrapper() + { + } + + Executor& underlying_executor() + { + return ex; + } + Scheduler& underlying_scheduler() + { + return sch; + } + + template <class Rep, class Period> + the_executor after(chrono::duration<Rep,Period> const& rel_time) + { + return at(clock::now() + rel_time ); + } + + template <class Duration> + the_executor at(chrono::time_point<clock,Duration> const& abs_time) + { + return the_executor(sch, ex, abs_time); + } + + private: + Scheduler& sch; + Executor& ex; + }; //end class + + /// Wraps a reference to a @c Scheduler providing an @c Executor that + /// run the function at a given @c time_point known at construction. + template <class Scheduler> + class at_executor + { + public: + typedef typename Scheduler::clock clock; + typedef typename Scheduler::work work; + typedef typename clock::time_point time_point; + + template <class Duration> + at_executor(Scheduler& sch, chrono::time_point<clock,Duration> const& tp) : + sch(sch), + tp(tp), + is_closed(false) + {} + + ~at_executor() + { + close(); + } + + Scheduler& underlying_scheduler() + { + return sch; + } + + void close() + { + is_closed = true; + } + + bool closed() + { + return is_closed || sch.closed(); + } + + template <class Work> + void submit(BOOST_THREAD_FWD_REF(Work) w) + { + if (closed()) + { + BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + sch.submit_at(boost::forward<Work>(w), tp); + } + + template <class Executor> + resubmit_at_executor<Scheduler, Executor> on(Executor& ex) + { + return resubmit_at_executor<Scheduler, Executor>(sch, ex, tp); + } + + private: + Scheduler& sch; + time_point tp; + bool is_closed; + }; //end class + + /// A @c Scheduler using a specific thread. Note that a Scheduler is not an Executor. + /// It provides factory helper functions such as at/after that convert a @c Scheduler into an @c Executor + /// that submit the work at/after a specific time/duration respectively. + template <class Clock = chrono::steady_clock> + class scheduler : public detail::scheduled_executor_base<Clock> + { + public: + typedef typename detail::scheduled_executor_base<Clock>::work work; + + typedef Clock clock; + + scheduler() + : super(), + thr(&super::loop, this) {} + + ~scheduler() + { + this->close(); + thr.join(); + } + template <class Ex> + scheduler_executor_wrapper<scheduler, Ex> on(Ex& ex) + { + return scheduler_executor_wrapper<scheduler, Ex>(*this, ex); + } + + template <class Rep, class Period> + at_executor<scheduler> after(chrono::duration<Rep,Period> const& rel_time) + { + return at(rel_time + clock::now()); + } + + template <class Duration> + at_executor<scheduler> at(chrono::time_point<clock,Duration> const& tp) + { + return at_executor<scheduler>(*this, tp); + } + + private: + typedef detail::scheduled_executor_base<Clock> super; + thread thr; + }; + + + } + using executors::resubmitter; + using executors::resubmit; + using executors::resubmit_at_executor; + using executors::scheduler_executor_wrapper; + using executors::at_executor; + using executors::scheduler; +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/scheduling_adaptor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/scheduling_adaptor.hpp new file mode 100644 index 00000000000..ac0a0acbce8 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/scheduling_adaptor.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2014 Ian Forbed +// 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_SCHEDULING_ADAPTOR_HPP +#define BOOST_THREAD_EXECUTORS_SCHEDULING_ADAPTOR_HPP + +#include <boost/thread/executors/detail/scheduled_executor_base.hpp> + +namespace boost +{ +namespace executors +{ + + template <typename Executor> + class scheduling_adpator : public detail::scheduled_executor_base<> + { + private: + Executor& _exec; + thread _scheduler; + public: + + scheduling_adpator(Executor& ex) + : super(), + _exec(ex), + _scheduler(&super::loop, this) {} + + ~scheduling_adpator() + { + this->close(); + _scheduler.join(); + } + + Executor& underlying_executor() + { + return _exec; + } + + private: + typedef detail::scheduled_executor_base<> super; + }; //end class + +} //end executors + + using executors::scheduling_adpator; + +} //end boost +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor.hpp new file mode 100644 index 00000000000..6d7ed9be97b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor.hpp @@ -0,0 +1,216 @@ +// 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/concurrent_queues/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 + concurrent::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()() { + try { + task(); + p.set_value(); + } catch (...) + { + p.set_exception(current_exception()); + } + } + }; + 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(task) == queue_op_status::success) + { + boost::promise<void> p; + try_executing_one_task tmp(task,p); + ex.submit(tmp); + p.get_future().wait(); + return true; + } + return false; + } + catch (...) + { + std::terminate(); + //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 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. + */ + void submit(BOOST_THREAD_RV_REF(work) closure) + { + work_queue.push(boost::move(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_FWD_REF(Closure) closure) + { + work w((boost::forward<Closure>(closure))); + submit(boost::move(w)); + } + + /** + * \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/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor_cont.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor_cont.hpp new file mode 100644 index 00000000000..91087890be6 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor_cont.hpp @@ -0,0 +1,170 @@ +// Copyright (C) 2015 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_CONT_HPP +#define BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/detail/delete.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/concurrent_queues/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_cont + { + public: + /// type-erasure to store the works to do + typedef executors::work work; + private: + + generic_executor_ref ex_; + future<void> fut_; // protected by mtx_ + bool closed_; // protected by mtx_ + mutex mtx_; + + struct continuation { + work task; + template <class X> + struct result { + typedef void type; + }; + continuation(BOOST_THREAD_RV_REF(work) tsk) + : task(boost::move(tsk)) {} + void operator()(future<void> f) + { + try { + task(); + } catch (...) { + std::terminate(); + } + } + }; + + bool closed(lock_guard<mutex>&) const + { + return closed_; + } + public: + /** + * \par Returns + * The underlying executor wrapped on a generic executor reference. + */ + generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex_; } + + /// serial_executor_cont is not copyable. + BOOST_THREAD_NO_COPYABLE(serial_executor_cont) + + /** + * \b Effects: creates a serial executor that runs closures in fifo order using one the associated executor. + * + * \b Throws: Whatever exception is thrown while initializing the needed resources. + * + * \b Notes: + * * The lifetime of the associated executor must outlive the serial executor. + * * The current implementation doesn't support submission from synchronous continuation, that is, + * - the executor must execute the continuation asynchronously or + * - the continuation can not submit to this serial executor. + */ + template <class Executor> + serial_executor_cont(Executor& ex) + : ex_(ex), fut_(make_ready_future()), closed_(false) + { + } + /** + * \b Effects: Destroys the thread pool. + * + * \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor_cont destructor. + */ + ~serial_executor_cont() + { + // signal to the worker thread that there will be no more submissions. + close(); + } + + /** + * \b Effects: close the \c serial_executor_cont for submissions. + * The loop will work until there is no more closures to run. + */ + void close() + { + lock_guard<mutex> lk(mtx_); + closed_ = true;; + } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed() + { + lock_guard<mutex> lk(mtx_); + return closed(lk); + } + + /** + * Effects: none. + * Returns: always false. + * Throws: No. + * Remark: A serial executor can not execute one of its pending tasks as the tasks depends on the other tasks. + */ + bool try_executing_one() + { + return false; + } + + /** + * \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 after the last submitted closure finish. + * If the invoked closure throws an exception the \c serial_executor_cont will call \c std::terminate, as is the case with threads. + * + * \b Throws: \c sync_queue_is_closed if the executor 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) + { + lock_guard<mutex> lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + fut_ = fut_.then(ex_, continuation(work(closure))); + } +#endif + void submit(void (*closure)()) + { + lock_guard<mutex> lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + fut_ = fut_.then(ex_, continuation(work(closure))); + } + + template <typename Closure> + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + lock_guard<mutex> lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + fut_ = fut_.then(ex_, continuation(work(boost::forward<Closure>(closure)))); + } + + }; +} +using executors::serial_executor_cont; +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/thread_executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/thread_executor.hpp new file mode 100644 index 00000000000..c9f49a7b62f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/thread_executor.hpp @@ -0,0 +1,157 @@ +// 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/thread/scoped_thread.hpp> +#include <boost/thread/csbl/vector.hpp> +#include <boost/thread/concurrent_queues/queue_op_status.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_; + typedef scoped_thread<> thread_t; + typedef csbl::vector<thread_t> threads_type; + threads_type threads_; + mutable mutex mtx_; + + /** + * 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: Waits for closures (if any) to complete, then joins and destroys the threads. + * + * \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(); + // all the scoped threads will join before destroying + } + + /** + * \b Effects: close the \c thread_executor for submissions. + * The loop will work until there is no more closures to run. + */ + void close() + { + lock_guard<mutex> lk(mtx_); + closed_ = true; + } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed(lock_guard<mutex>& ) + { + return closed_; + } + bool closed() + { + lock_guard<mutex> lk(mtx_); + return closed(lk); + } + + /** + * \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) + { + lock_guard<mutex> lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + threads_.reserve(threads_.size() + 1); + thread th(closure); + threads_.push_back(thread_t(boost::move(th))); + } +#endif + void submit(void (*closure)()) + { + lock_guard<mutex> lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + threads_.reserve(threads_.size() + 1); + thread th(closure); + threads_.push_back(thread_t(boost::move(th))); + } + + template <typename Closure> + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + lock_guard<mutex> lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + threads_.reserve(threads_.size() + 1); + thread th(boost::forward<Closure>(closure)); + threads_.push_back(thread_t(boost::move(th))); + } + + /** + * \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/src/third_party/boost-1.60.0/boost/thread/executors/work.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/work.hpp new file mode 100644 index 00000000000..bdaf7651b92 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/work.hpp @@ -0,0 +1,30 @@ +// (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> +#include <boost/thread/detail/nullary_function.hpp> +#include <boost/thread/csbl/functional.hpp> + +namespace boost +{ + namespace executors + { + typedef detail::nullary_function<void()> work; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + typedef detail::nullary_function<void()> work_pq; + //typedef csbl::function<void()> work_pq; +#else + typedef csbl::function<void()> work_pq; +#endif + } +} // namespace boost + + +#endif // BOOST_THREAD_EXECUTORS_WORK_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/config/inline_namespace.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/config/inline_namespace.hpp new file mode 100644 index 00000000000..9c3b081fbe4 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/config/inline_namespace.hpp @@ -0,0 +1,23 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_CONFIG_INLINE_NAMESPACE_HPP +#define BOOST_THREAD_EXPERIMENTAL_CONFIG_INLINE_NAMESPACE_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/config.hpp> + +#if !defined(BOOST_NO_CXX11_INLINE_NAMESPACES) +# define BOOST_THREAD_INLINE_NAMESPACE(name) inline namespace name +#else +# define BOOST_THREAD_INLINE_NAMESPACE(name) namespace name +#endif + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/exception_list.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/exception_list.hpp new file mode 100644 index 00000000000..748bfa85ee7 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/exception_list.hpp @@ -0,0 +1,16 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_EXCEPTION_LIST_HPP +#define BOOST_THREAD_EXPERIMENTAL_EXCEPTION_LIST_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/experimental/parallel/v1/exception_list.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/exception_list.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/exception_list.hpp new file mode 100644 index 00000000000..e4d3354f1c1 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/exception_list.hpp @@ -0,0 +1,70 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_EXCEPTION_LIST_HPP +#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_EXCEPTION_LIST_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/experimental/parallel/v1/inline_namespace.hpp> + +#include <boost/exception_ptr.hpp> +#include <exception> +#include <list> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +namespace experimental +{ +namespace parallel +{ +BOOST_THREAD_INLINE_NAMESPACE(v1) +{ + + class BOOST_SYMBOL_VISIBLE exception_list: public std::exception + { + typedef std::list<exception_ptr> exception_ptr_list; + exception_ptr_list list_; + public: + typedef exception_ptr_list::const_iterator const_iterator; + + ~exception_list() BOOST_NOEXCEPT_OR_NOTHROW {} + + void add(exception_ptr const& e) + { + list_.push_back(e); + } + size_t size() const BOOST_NOEXCEPT + { + return list_.size(); + } + const_iterator begin() const BOOST_NOEXCEPT + { + return list_.begin(); + } + const_iterator end() const BOOST_NOEXCEPT + { + return list_.end(); + } + const char* what() const BOOST_NOEXCEPT_OR_NOTHROW + { + return "exception_list"; + } + + }; +} + +} // parallel +} // experimental +} // boost +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/inline_namespace.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/inline_namespace.hpp new file mode 100644 index 00000000000..a607e53c468 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/inline_namespace.hpp @@ -0,0 +1,28 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_INLINE_NAMESPACE_HPP +#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_INLINE_NAMESPACE_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/experimental/config/inline_namespace.hpp> +namespace boost { +namespace experimental { +namespace parallel { + + BOOST_THREAD_INLINE_NAMESPACE(v1) {} + +#if defined(BOOST_NO_CXX11_INLINE_NAMESPACES) + using namespace v1; +#endif + +} +} +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/inline_namespace.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/inline_namespace.hpp new file mode 100644 index 00000000000..52d8e2904e8 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/inline_namespace.hpp @@ -0,0 +1,29 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_INLINE_NAMESPACE_HPP +#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_INLINE_NAMESPACE_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/experimental/config/inline_namespace.hpp> + +namespace boost { +namespace experimental { +namespace parallel { + + BOOST_THREAD_INLINE_NAMESPACE(v2) {} + +#if defined(BOOST_NO_CXX11_INLINE_NAMESPACES) + using namespace v2; +#endif + +} +} +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/task_region.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/task_region.hpp new file mode 100755 index 00000000000..e4a5833115f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/task_region.hpp @@ -0,0 +1,316 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP +#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014-2015. 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/future.hpp> +#if defined BOOST_THREAD_PROVIDES_EXECUTORS +#include <boost/thread/executors/basic_thread_pool.hpp> +#endif +#include <boost/thread/experimental/exception_list.hpp> +#include <boost/thread/experimental/parallel/v2/inline_namespace.hpp> +#include <boost/thread/detail/move.hpp> + +#include <boost/config/abi_prefix.hpp> + +#define BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + +namespace boost +{ +namespace experimental +{ +namespace parallel +{ +BOOST_THREAD_INLINE_NAMESPACE(v2) +{ + class BOOST_SYMBOL_VISIBLE task_canceled_exception: public std::exception + { + public: + //task_canceled_exception() BOOST_NOEXCEPT {} + //task_canceled_exception(const task_canceled_exception&) BOOST_NOEXCEPT {} + //task_canceled_exception& operator=(const task_canceled_exception&) BOOST_NOEXCEPT {} + virtual const char* what() const BOOST_NOEXCEPT_OR_NOTHROW + { return "task_canceled_exception";} + }; + + template <class Executor> + class task_region_handle_gen; + + namespace detail + { + void handle_task_region_exceptions(exception_list& errors) + { + try { + throw; + } +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + catch (task_canceled_exception&) + { + } +#endif + catch (exception_list const& el) + { + for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it) + { + boost::exception_ptr const& e = *it; + try { + rethrow_exception(e); + } + catch (...) + { + handle_task_region_exceptions(errors); + } + } + } + catch (...) + { + errors.add(boost::current_exception()); + } + } + +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + template <class TRH, class F> + struct wrapped + { + TRH& tr; + F f; + wrapped(TRH& tr, BOOST_THREAD_RV_REF(F) f) : tr(tr), f(move(f)) + {} + void operator()() + { + try + { + f(); + } + catch (...) + { + lock_guard<mutex> lk(tr.mtx); + tr.canceled = true; + throw; + } + } + }; +#endif + } + + template <class Executor> + class task_region_handle_gen + { + private: + // Private members and friends +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + template <class TRH, class F> + friend struct detail::wrapped; +#endif + template <typename F> + friend void task_region(BOOST_THREAD_FWD_REF(F) f); + template<typename F> + friend void task_region_final(BOOST_THREAD_FWD_REF(F) f); + template <class Ex, typename F> + friend void task_region(Ex&, BOOST_THREAD_FWD_REF(F) f); + template<class Ex, typename F> + friend void task_region_final(Ex&, BOOST_THREAD_FWD_REF(F) f); + + void wait_all() + { + wait_for_all(group.begin(), group.end()); + + for (group_type::iterator it = group.begin(); it != group.end(); ++it) + { + future<void>& f = *it; + if (f.has_exception()) + { + try + { + boost::rethrow_exception(f.get_exception_ptr()); + } + catch (...) + { + detail::handle_task_region_exceptions(exs); + } + } + } + if (exs.size() != 0) + { + boost::throw_exception(exs); + } + } +protected: +#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS + task_region_handle_gen() + {} +#endif + +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS + task_region_handle_gen() + : canceled(false) + , ex(0) + {} + task_region_handle_gen(Executor& ex) + : canceled(false) + , ex(&ex) + {} + +#endif + +#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS + task_region_handle_gen() + : ex(0) + {} + task_region_handle_gen(Executor& ex) + : ex(&ex) + {} +#endif + +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS + task_region_handle_gen() + : canceled(false) + { + } +#endif + + ~task_region_handle_gen() + { + //wait_all(); + } + +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + mutable mutex mtx; + bool canceled; +#endif +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + Executor* ex; +#endif + exception_list exs; + typedef csbl::vector<future<void> > group_type; + group_type group; + + public: + BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&)) + BOOST_DELETED_FUNCTION(task_region_handle_gen& operator=(const task_region_handle_gen&)) + BOOST_DELETED_FUNCTION(task_region_handle_gen* operator&() const) + + public: + template<typename F> + void run(BOOST_THREAD_FWD_REF(F) f) + { +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + { + lock_guard<mutex> lk(mtx); + if (canceled) { + boost::throw_exception(task_canceled_exception()); + } + } +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + group.push_back(async(*ex, detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f)))); +#else + group.push_back(async(detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f)))); +#endif +#else +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + group.push_back(async(*ex, forward<F>(f))); +#else + group.push_back(async(forward<F>(f))); +#endif +#endif + } + + void wait() + { +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + { + lock_guard<mutex> lk(mtx); + if (canceled) { + boost::throw_exception(task_canceled_exception()); + } + } +#endif + wait_all(); + } + }; +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + typedef basic_thread_pool default_executor; +#else + typedef int default_executor; +#endif + class task_region_handle : + public task_region_handle_gen<default_executor> + { + default_executor tp; + template <typename F> + friend void task_region(BOOST_THREAD_FWD_REF(F) f); + template<typename F> + friend void task_region_final(BOOST_THREAD_FWD_REF(F) f); + + protected: + task_region_handle() : task_region_handle_gen<default_executor>() + { +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + ex = &tp; +#endif + } + BOOST_DELETED_FUNCTION(task_region_handle(const task_region_handle&)) + BOOST_DELETED_FUNCTION(task_region_handle& operator=(const task_region_handle&)) + BOOST_DELETED_FUNCTION(task_region_handle* operator&() const) + + }; + + template <typename Executor, typename F> + void task_region_final(Executor& ex, BOOST_THREAD_FWD_REF(F) f) + { + task_region_handle_gen<Executor> tr(ex); + try + { + f(tr); + } + catch (...) + { + detail::handle_task_region_exceptions(tr.exs); + } + tr.wait_all(); + } + + template <typename Executor, typename F> + void task_region(Executor& ex, BOOST_THREAD_FWD_REF(F) f) + { + task_region_final(ex, forward<F>(f)); + } + + template <typename F> + void task_region_final(BOOST_THREAD_FWD_REF(F) f) + { + task_region_handle tr; + try + { + f(tr); + } + catch (...) + { + detail::handle_task_region_exceptions(tr.exs); + } + tr.wait_all(); + } + + template <typename F> + void task_region(BOOST_THREAD_FWD_REF(F) f) + { + task_region_final(forward<F>(f)); + } + +} // v2 +} // parallel +} // experimental +} // boost + +#include <boost/config/abi_suffix.hpp> + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/task_region.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/task_region.hpp new file mode 100644 index 00000000000..9b60d8b19ee --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/task_region.hpp @@ -0,0 +1,16 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_TASK_REGION_HPP +#define BOOST_THREAD_EXPERIMENTAL_TASK_REGION_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/experimental/parallel/v2/task_region.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/externally_locked.hpp b/src/third_party/boost-1.60.0/boost/thread/externally_locked.hpp new file mode 100644 index 00000000000..0d4baaa512d --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/externally_locked_stream.hpp b/src/third_party/boost-1.60.0/boost/thread/externally_locked_stream.hpp new file mode 100644 index 00000000000..aa9aeff79d9 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/future.hpp b/src/third_party/boost-1.60.0/boost/thread/future.hpp new file mode 100644 index 00000000000..0ec484c2bf9 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/future.hpp @@ -0,0 +1,5552 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 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_HPP +#define BOOST_THREAD_FUTURE_HPP + +#include <boost/thread/detail/config.hpp> + +// boost::thread::future requires exception handling +// due to boost::exception::exception_ptr dependency + +//#define BOOST_THREAD_CONTINUATION_SYNC +#define BOOST_THREAD_FUTURE_BLOCKING + +#ifndef BOOST_NO_EXCEPTIONS + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/invoker.hpp> +#include <boost/thread/detail/invoke.hpp> +#include <boost/thread/detail/is_convertible.hpp> +#include <boost/thread/exceptional_ptr.hpp> +#include <boost/thread/futures/future_error.hpp> +#include <boost/thread/futures/future_error_code.hpp> +#include <boost/thread/futures/future_status.hpp> +#include <boost/thread/futures/is_future_type.hpp> +#include <boost/thread/futures/launch.hpp> +#include <boost/thread/futures/wait_for_all.hpp> +#include <boost/thread/futures/wait_for_any.hpp> +#include <boost/thread/lock_algorithms.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/thread_time.hpp> +#include <boost/thread/executor.hpp> +#include <boost/thread/executors/generic_executor_ref.hpp> + +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL +#include <boost/optional.hpp> +#else +#include <boost/thread/csbl/memory/unique_ptr.hpp> +#endif + +#include <boost/assert.hpp> +#include <boost/bind.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#endif +#include <boost/core/enable_if.hpp> +#include <boost/core/ref.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/exception_ptr.hpp> +#include <boost/function.hpp> +#include <boost/next_prior.hpp> +#include <boost/scoped_array.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/throw_exception.hpp> +#include <boost/type_traits/conditional.hpp> +#include <boost/type_traits/decay.hpp> +#include <boost/type_traits/is_copy_constructible.hpp> +#include <boost/type_traits/is_fundamental.hpp> +#include <boost/type_traits/is_void.hpp> +#include <boost/utility/result_of.hpp> + + +#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 + +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +#include <boost/thread/csbl/tuple.hpp> +#include <boost/thread/csbl/vector.hpp> +#endif + +#include <algorithm> +#include <list> +#include <vector> +#include <utility> + +#if defined BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_FUTURE future +#else +#define BOOST_THREAD_FUTURE unique_future +#endif + +namespace boost +{ + template <class T> + shared_ptr<T> static_shared_from_this(T* that) + { + return static_pointer_cast<T>(that->shared_from_this()); + } + template <class T> + shared_ptr<T const> static_shared_from_this(T const* that) + { + return static_pointer_cast<T const>(that->shared_from_this()); + } + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS +#else + namespace executors { + class executor; + } +#endif + typedef shared_ptr<executor> executor_ptr_type; + + namespace detail + { + + struct relocker + { + boost::unique_lock<boost::mutex>& lock_; + + relocker(boost::unique_lock<boost::mutex>& lk): + lock_(lk) + { + lock_.unlock(); + } + ~relocker() + { + if (! lock_.owns_lock()) { + lock_.lock(); + } + } + void lock() { + if (! lock_.owns_lock()) { + lock_.lock(); + } + } + 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; + typedef waiter_list::iterator notify_when_ready_handle; + // 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; + typedef std::vector<continuation_ptr_type> continuations_type; + + boost::exception_ptr exception; + bool done; + bool is_valid_; + bool is_deferred_; + bool is_constructed; + launch policy_; + mutable boost::mutex mutex; + boost::condition_variable waiters; + waiter_list external_waiters; + boost::function<void()> callback; + // This declaration should be only included conditionally, but is included to maintain the same layout. + continuations_type continuations; + executor_ptr_type ex; + + // This declaration should be only included conditionally, but is included to maintain the same layout. + virtual void launch_continuation() + { + } + + shared_state_base(): + done(false), + is_valid_(true), + is_deferred_(false), + is_constructed(false), + policy_(launch::none), + continuations(), + ex() + {} + + shared_state_base(exceptional_ptr const& ex): + exception(ex.ptr_), + done(true), + is_valid_(true), + is_deferred_(false), + is_constructed(false), + policy_(launch::none), + continuations(), + ex() + {} + + + virtual ~shared_state_base() + { + } + executor_ptr_type get_executor() + { + return ex; + } + + void set_executor_policy(executor_ptr_type aex) + { + set_executor(); + ex = aex; + } + void set_executor_policy(executor_ptr_type aex, boost::lock_guard<boost::mutex>&) + { + set_executor(); + ex = aex; + } + void set_executor_policy(executor_ptr_type aex, boost::unique_lock<boost::mutex>&) + { + set_executor(); + ex = aex; + } + + bool valid(boost::unique_lock<boost::mutex>&) { return is_valid_; } + bool valid() { + boost::unique_lock<boost::mutex> lk(this->mutex); + return valid(lk); + } + void invalidate(boost::unique_lock<boost::mutex>&) { is_valid_ = false; } + void invalidate() { + boost::unique_lock<boost::mutex> lk(this->mutex); + invalidate(lk); + } + void validate(boost::unique_lock<boost::mutex>&) { is_valid_ = true; } + void validate() { + boost::unique_lock<boost::mutex> lk(this->mutex); + validate(lk); + } + + 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; + } +#else + void set_executor() + { + } +#endif + notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv) + { + boost::unique_lock<boost::mutex> lock(this->mutex); + do_callback(lock); + return external_waiters.insert(external_waiters.end(),&cv); + } + + void unnotify_when_ready(notify_when_ready_handle it) + { + boost::lock_guard<boost::mutex> lock(this->mutex); + external_waiters.erase(it); + } + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + void do_continuation(boost::unique_lock<boost::mutex>& lock) + { + if (! continuations.empty()) { + continuations_type the_continuations = continuations; + continuations.clear(); + relocker rlk(lock); + for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) { + (*it)->launch_continuation(); + } + } + } +#else + void do_continuation(boost::unique_lock<boost::mutex>&) + { + } +#endif +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock) + { + continuations.push_back(continuation); + if (done) { + do_continuation(lock); + } + } +#endif + void mark_finished_internal(boost::unique_lock<boost::mutex>& lock) + { + done=true; + waiters.notify_all(); + for(waiter_list::const_iterator it=external_waiters.begin(), + end=external_waiters.end();it!=end;++it) + { + (*it)->notify_all(); + } + do_continuation(lock); + } + void make_ready() + { + boost::unique_lock<boost::mutex> lock(this->mutex); + mark_finished_internal(lock); + } + + void do_callback(boost::unique_lock<boost::mutex>& lock) + { + if(callback && !done) + { + boost::function<void()> local_callback=callback; + relocker relock(lock); + local_callback(); + } + } + + 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); + + return true; + } + else + return done; + } + void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true) + { + 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(boost::unique_lock<boost::mutex>& lock, bool rethrow=true) + { + wait_internal(lock, rethrow); + } + + void wait(bool rethrow=true) + { + boost::unique_lock<boost::mutex> lock(this->mutex); + wait(lock, rethrow); + } + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_wait_until(boost::system_time const& target_time) + { + boost::unique_lock<boost::mutex> lock(this->mutex); + if (is_deferred_) + return false; + + do_callback(lock); + while(!done) + { + bool const success=waiters.timed_wait(lock,target_time); + if(!success && !done) + { + return false; + } + } + 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(this->mutex); + if (is_deferred_) + return future_status::deferred; + do_callback(lock); + while(!done) + { + cv_status const st=waiters.wait_until(lock,abs_time); + if(st==cv_status::timeout && !done) + { + return future_status::timeout; + } + } + return future_status::ready; + } +#endif + void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock) + { + exception=e; + mark_finished_internal(lock); + } + + void mark_exceptional_finish() + { + boost::unique_lock<boost::mutex> lock(this->mutex); + mark_exceptional_finish_internal(boost::current_exception(), lock); + } + + 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; + } + + launch launch_policy(boost::unique_lock<boost::mutex>&) const + { + return policy_; + } + + future_state::state get_state(boost::unique_lock<boost::mutex>&) const + { + if(!done) + { + return future_state::waiting; + } + else + { + return future_state::ready; + } + } + 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; + } + } + + exception_ptr get_exception_ptr() + { + boost::unique_lock<boost::mutex> lock(this->mutex); + 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: + 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 shared_state: + detail::shared_state_base + { +#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; + typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; + typedef T move_dest_type; +#elif defined BOOST_THREAD_USES_MOVE + 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 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; + + storage_type result; + + shared_state(): + result() + {} + shared_state(exceptional_ptr const& ex): + detail::shared_state_base(ex), result() + {} + + + ~shared_state() + { + } + + void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) + { +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL + result = result_; +#else + result.reset(new T(result_)); +#endif + this->mark_finished_internal(lock); + } + + void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock) + { +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL + result = boost::move(result_); +#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + result.reset(new T(boost::move(result_))); +#else + result.reset(new T(static_cast<rvalue_source_type>(result_))); +#endif + this->mark_finished_internal(lock); + } + + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template <class ...Args> + void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock, BOOST_THREAD_FWD_REF(Args)... args) + { +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL + result.emplace(boost::forward<Args>(args)...); +#else + result.reset(new T(boost::forward<Args>(args)...)); +#endif + this->mark_finished_internal(lock); + } +#endif + + void mark_finished_with_result(source_reference_type result_) + { + 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>& lk) + { + wait_internal(lk); + return result; + } + virtual move_dest_type get(boost::unique_lock<boost::mutex>& lk) + { + return boost::move(*get_storage(lk)); + } + move_dest_type get() + { + boost::unique_lock<boost::mutex> lk(this->mutex); + return this->get(lk); + } + + virtual shared_future_get_result_type get_sh(boost::unique_lock<boost::mutex>& lk) + { + return *get_storage(lk); + } + shared_future_get_result_type get_sh() + { + boost::unique_lock<boost::mutex> lk(this->mutex); + return this->get_sh(lk); + } + + 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 shared_state<T&>: + detail::shared_state_base + { + typedef T* storage_type; + typedef T& source_reference_type; + typedef T& move_dest_type; + typedef T& shared_future_get_result_type; + + T* result; + + shared_state(): + result(0) + {} + + shared_state(exceptional_ptr const& ex): + detail::shared_state_base(ex), result(0) + {} + + ~shared_state() + { + } + + void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) + { + result= &result_; + mark_finished_internal(lock); + } + + void mark_finished_with_result(source_reference_type result_) + { + boost::unique_lock<boost::mutex> lock(this->mutex); + mark_finished_with_result_internal(result_, lock); + } + + virtual T& get(boost::unique_lock<boost::mutex>& lock) + { + wait_internal(lock); + return *result; + } + T& get() + { + boost::unique_lock<boost::mutex> lk(this->mutex); + return get(lk); + } + + virtual T& get_sh(boost::unique_lock<boost::mutex>& lock) + { + wait_internal(lock); + return *result; + } + T& get_sh() + { + boost::unique_lock<boost::mutex> lock(this->mutex); + return get_sh(lock); + } + + 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<> + struct shared_state<void>: + detail::shared_state_base + { + typedef void shared_future_get_result_type; + typedef void move_dest_type; + + shared_state() + {} + + shared_state(exceptional_ptr const& ex): + detail::shared_state_base(ex) + {} + + void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock) + { + mark_finished_internal(lock); + } + + void mark_finished_with_result() + { + boost::unique_lock<boost::mutex> lock(this->mutex); + mark_finished_with_result_internal(lock); + } + + virtual void get(boost::unique_lock<boost::mutex>& lock) + { + this->wait_internal(lock); + } + void get() + { + boost::unique_lock<boost::mutex> lock(this->mutex); + this->get(lock); + } + + virtual void get_sh(boost::unique_lock<boost::mutex>& lock) + { + this->wait_internal(lock); + } + void get_sh() + { + boost::unique_lock<boost::mutex> lock(this->mutex); + this->get_sh(lock); + } + + void set_value_at_thread_exit() + { + 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: +#ifdef BOOST_THREAD_FUTURE_BLOCKING + boost::thread thr_; + void join() + { + if (this_thread::get_id() == thr_.get_id()) + { + thr_.detach(); + return; + } + if (thr_.joinable()) thr_.join(); + } +#endif + public: + future_async_shared_state_base() + { + this->set_async(); + } + + ~future_async_shared_state_base() + { +#ifdef BOOST_THREAD_FUTURE_BLOCKING + join(); +#endif + } + + virtual void wait(boost::unique_lock<boost::mutex>& lk, bool rethrow) + { +#ifdef BOOST_THREAD_FUTURE_BLOCKING + { + relocker rlk(lk); + join(); + } +#endif + this->base_type::wait(lk, rethrow); + } + }; + + ///////////////////////// + /// future_async_shared_state + ///////////////////////// + template<typename Rp, typename Fp> + struct future_async_shared_state: future_async_shared_state_base<Rp> + { + future_async_shared_state() + { + } + + void init(BOOST_THREAD_FWD_REF(Fp) f) + { +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f)); +#else + thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward<Fp>(f)).detach(); +#endif + } + + static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f) + { + try + { + that->mark_finished_with_result(f()); + } + catch(...) + { + that->mark_exceptional_finish(); + } + } + }; + + template<typename Fp> + struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void> + { + void init(BOOST_THREAD_FWD_REF(Fp) f) + { +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)); +#else + thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach(); +#endif + } + + static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f) + { + try + { + f(); + that->mark_finished_with_result(); + } + catch(...) + { + that->mark_exceptional_finish(); + } + } + }; + + template<typename Rp, typename Fp> + struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&> + { + void init(BOOST_THREAD_FWD_REF(Fp) f) + { +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)); +#else + thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach(); +#endif + } + + static void run(shared_ptr<future_async_shared_state> that, BOOST_THREAD_FWD_REF(Fp) f) + { + try + { + that->mark_finished_with_result(f()); + } + catch(...) + { + that->mark_exceptional_finish(); + } + } + }; + + ////////////////////////// + /// future_deferred_shared_state + ////////////////////////// + template<typename Rp, typename Fp> + struct future_deferred_shared_state: 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(); + } + + virtual void execute(boost::unique_lock<boost::mutex>& lck) { + try + { + 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); + } + catch (...) + { + 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(); + } + + virtual void execute(boost::unique_lock<boost::mutex>& lck) { + try + { + this->mark_finished_with_result_internal(func_(), lck); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + + 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 + { + Fp local_fuct=boost::move(func_); + relocker relock(lck); + local_fuct(); + relock.lock(); + this->mark_finished_with_result_internal(lck); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + + class future_waiter + { + public: + typedef std::vector<int>::size_type count_type; + private: + struct registered_waiter; + struct registered_waiter + { + boost::shared_ptr<detail::shared_state_base> future_; + detail::shared_state_base::notify_when_ready_handle handle; + count_type index; + + registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future, + detail::shared_state_base::notify_when_ready_handle handle_, + count_type index_): + future_(a_future),handle(handle_),index(index_) + {} + }; + + struct all_futures_lock + { +#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_portable i=0;i<count;++i) + { + locks[i]=BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(futures[i].future_->mutex)); + } + } + + void lock() + { + boost::lock(locks.get(),locks.get()+count); + } + + void unlock() + { + for(count_type_portable i=0;i<count;++i) + { + locks[i].unlock(); + } + } + }; + + boost::condition_variable_any cv; + std::vector<registered_waiter> futures_; + count_type future_count; + + public: + future_waiter(): + future_count(0) + {} + + template<typename F> + void add(F& f) + { + if(f.future_) + { + registered_waiter waiter(f.future_,f.future_->notify_when_ready(cv),future_count); + try { + futures_.push_back(waiter); + } catch(...) { + f.future_->unnotify_when_ready(waiter.handle); + 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_); + for(;;) + { + for(count_type i=0;i<futures_.size();++i) + { + if(futures_[i].future_->done) + { + return futures_[i].index; + } + } + cv.wait(lk); + } + } + + ~future_waiter() + { + for(count_type i=0;i<futures_.size();++i) + { + futures_[i].future_->unnotify_when_ready(futures_[i].handle); + } + } + }; + + } + + template <typename R> + class BOOST_THREAD_FUTURE; + + template <typename R> + class shared_future; + + template<typename T> + struct is_future_type<BOOST_THREAD_FUTURE<T> > : true_type + { + }; + + template<typename T> + struct is_future_type<shared_future<T> > : true_type + { + }; + +// template<typename Iterator> +// typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end) +// { +// if(begin==end) +// return end; +// +// detail::future_waiter waiter; +// for(Iterator current=begin;current!=end;++current) +// { +// waiter.add(*current); +// } +// 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>,typename detail::future_waiter::count_type>::type wait_for_any(F1& f1,F2& f2) + { + detail::future_waiter waiter; + waiter.add(f1); + waiter.add(f2); + return waiter.wait(); + } + + template<typename F1,typename F2,typename F3> + typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3) + { + detail::future_waiter waiter; + waiter.add(f1); + waiter.add(f2); + waiter.add(f3); + return waiter.wait(); + } + + template<typename F1,typename F2,typename F3,typename F4> + typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4) + { + detail::future_waiter waiter; + waiter.add(f1); + waiter.add(f2); + waiter.add(f3); + waiter.add(f4); + return waiter.wait(); + } + + template<typename F1,typename F2,typename F3,typename F4,typename F5> + typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5) + { + detail::future_waiter waiter; + waiter.add(f1); + waiter.add(f2); + waiter.add(f3); + waiter.add(f4); + waiter.add(f5); + return waiter.wait(); + } +#else + template<typename F1, typename... Fs> + typename boost::enable_if<is_future_type<F1>, typename detail::future_waiter::count_type>::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; + + template <typename R> + class packaged_task; + + namespace detail + { + /// Common implementation for all the futures independently of the return type + class base_future + { + public: + }; + /// Common implementation for future and shared_future. + template <typename R> + class basic_future : public base_future + { + protected: + public: + + typedef boost::shared_ptr<detail::shared_state<R> > future_ptr; + typedef typename detail::shared_state<R>::move_dest_type move_dest_type; + + static //BOOST_CONSTEXPR + future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) { + return future_ptr(new detail::shared_state<R>(ex)); + } + + future_ptr future_; + + basic_future(future_ptr a_future): + future_(a_future) + { + } + + public: + typedef future_state::state state; + + BOOST_THREAD_MOVABLE_ONLY(basic_future) + basic_future(): future_() {} + + + //BOOST_CONSTEXPR + basic_future(exceptional_ptr const& ex) + : future_(make_exceptional_future_ptr(ex)) + { + } + + ~basic_future() { + } + + basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT: + future_(BOOST_THREAD_RV(other).future_) + { + BOOST_THREAD_RV(other).future_.reset(); + } + basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT + { + future_=BOOST_THREAD_RV(other).future_; + BOOST_THREAD_RV(other).future_.reset(); + return *this; + } + void swap(basic_future& that) BOOST_NOEXCEPT + { + future_.swap(that.future_); + } + // functions to check state, and wait for ready + state get_state(boost::unique_lock<boost::mutex>& lk) const + { + if(!future_) + { + return future_state::uninitialized; + } + return future_->get_state(lk); + } + state get_state() const + { + if(!future_) + { + return future_state::uninitialized; + } + return future_->get_state(); + } + + bool is_ready() const + { + return get_state()==future_state::ready; + } + + bool is_ready(boost::unique_lock<boost::mutex>& lk) const + { + return get_state(lk)==future_state::ready; + } + bool has_exception() const + { + return future_ && future_->has_exception(); + } + + 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); + } + + launch launch_policy() const + { + if ( future_ ) { + boost::unique_lock<boost::mutex> lk(this->future_->mutex); + 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 && future_->valid(); + } + + void wait() const + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + future_->wait(false); + } + + typedef detail::shared_state_base::notify_when_ready_handle notify_when_ready_handle; + + boost::mutex& mutex() { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->mutex; + }; + + notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv) + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->notify_when_ready(cv); + } + + void unnotify_when_ready(notify_when_ready_handle h) + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->unnotify_when_ready(h); + } + +#if defined BOOST_THREAD_USES_DATETIME + template<typename Duration> + bool timed_wait(Duration const& rel_time) const + { + return timed_wait_until(boost::get_system_time()+rel_time); + } + + bool timed_wait_until(boost::system_time const& abs_time) const + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->timed_wait_until(abs_time); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const + { + return wait_until(chrono::steady_clock::now() + rel_time); + + } + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + 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); + + 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); + + 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); + + #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); + + 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); + + template <class Rp, class Fp, class Executor> + BOOST_THREAD_FUTURE<Rp> + make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f); + #endif +#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 + } +#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY) + 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); + + inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all(); + + #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); + #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); + + inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any(); + + #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); + #endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + + + 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); + + template<typename F, typename Rp, typename Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template<typename F, typename Rp, typename Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template<typename Ex, typename F, typename Rp, typename Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::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); + + template<typename Ex, typename F, typename Rp, typename Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template <class Rp, class Fp, class Executor> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f); + #endif +#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_FUTURE_WHEN_ALL_WHEN_ANY) + template< typename InputIterator> + friend typename boost::disable_if<is_future_type<InputIterator>, + BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> > + >::type + when_all(InputIterator first, InputIterator last); + + //friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend 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); + #endif + + template< typename InputIterator> + friend typename boost::disable_if<is_future_type<InputIterator>, + BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> > + >::type + when_any(InputIterator first, InputIterator last); + + //friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend 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); + #endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +#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)))) + { + } + inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION + + explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) : + 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_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock<boost::mutex> lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); +#endif + return this->future_->get(lk); + } + + 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_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock<boost::mutex> lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(lk, false); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); +#endif + + if (this->future_->has_value(lk)) { + return this->future_->get(lk); + } + 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_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock<boost::mutex> lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(lk, false); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); +#endif + if (this->future_->has_value(lk)) { + return this->future_->get(lk); + } + 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); + + template<typename F, typename Rp, typename Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template<typename F, typename Rp, typename Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template<typename Ex, typename F, typename Rp, typename Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::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); + + template<typename Ex, typename F, typename Rp, typename Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template <class Rp, class Fp, class Executor> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f); + #endif + +#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_FUTURE_WHEN_ALL_WHEN_ANY) + template< typename InputIterator> + friend typename boost::disable_if<is_future_type<InputIterator>, + BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> > + >::type + when_all(InputIterator first, InputIterator last); + + friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend 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); + #endif + + template< typename InputIterator> + friend typename boost::disable_if<is_future_type<InputIterator>, + BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> > + >::type + when_any(InputIterator first, InputIterator last); + + friend inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend 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); + #endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + + #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_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock<boost::mutex> lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } + #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); + #endif + return this->future_->get(lk); + } + move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION + { + if (this->future_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock<boost::mutex> lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(lk, false); + #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); + #endif + if (this->future_->has_value(lk)) return this->future_->get(lk); + else return boost::move(v); + } + + move_dest_type get_or(R const& v) // EXTENSION + { + if (this->future_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock<boost::mutex> lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(lk, false); + #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); + #endif + if (this->future_->has_value(lk)) return this->future_->get(lk); + 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 : public detail::basic_future<R> + { + typedef detail::basic_future<R> base_type; + typedef typename base_type::future_ptr future_ptr; + + friend class detail::future_waiter; + 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_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): + base_type(a_future) + {} + + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_future) + typedef R value_type; // EXTENSION + + shared_future(shared_future const& other): + base_type(other.future_) + {} + + typedef future_state::state state; + + BOOST_CONSTEXPR shared_future() + {} + //BOOST_CONSTEXPR + shared_future(exceptional_ptr const& ex): + base_type(ex) {} + ~shared_future() + {} + + shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other) + { + this->future_ = other.future_; + return *this; + } + + shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT : + base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) + { + } + 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)))) + { + } + + shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT + { + base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); + return *this; + } + shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT + { + base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); + return *this; + } + + void swap(shared_future& other) BOOST_NOEXCEPT + { + 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::shared_state<R>::shared_future_get_result_type get() const + { + if(!this->future_) + { + boost::throw_exception(future_uninitialized()); + } + return this->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) const // EXTENSION + { + if(!this->future_) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(); + if (this->future_->has_value()) return this->future_->get_sh(); + else return boost::move(v); + } + +#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 + + 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 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::shared_state<R>)); + } +#include <boost/detail/atomic_redef_macros.hpp> +#endif + } + + public: + BOOST_THREAD_MOVABLE_ONLY(promise) +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template <class Allocator> + promise(boost::allocator_arg_t, Allocator a) + { + 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) + {} + + ~promise() + { + 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); + } + } + } + + // Assignment + promise(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; + } + 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; + } + + void swap(promise& other) + { + future_.swap(other.future_); + std::swap(future_obtained,other.future_obtained); + } + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + void set_executor(executor_ptr_type aex) + { + lazy_init(); + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + boost::lock_guard<boost::mutex> lk(future_->mutex); + future_->set_executor_policy(aex, lk); + } +#endif + // Result retrieval + BOOST_THREAD_FUTURE<R> get_future() + { + lazy_init(); + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + if (future_obtained) + { + boost::throw_exception(future_already_retrieved()); + } + future_obtained=true; + return BOOST_THREAD_FUTURE<R>(future_); + } + +#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) + { + 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); + } +#else + void set_value(source_reference_type r) + { + 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); + } +#endif + + void set_value(rvalue_source_type r) + { + 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 + } + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template <class ...Args> + void emplace(BOOST_THREAD_FWD_REF(Args) ...args) + { + 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(lock, boost::forward<Args>(args)...); + } + +#endif + + void set_exception(boost::exception_ptr p) + { + 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(promise_moved()); + } + 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)); + } + + template<typename F> + void set_wait_callback(F f) + { + lazy_init(); + future_->set_wait_callback(f,this); + } + + }; + + template <typename R> + class promise<R&> + { + typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr; + + future_ptr future_; + bool future_obtained; + + void lazy_init() + { +#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::shared_state<R&>)); + } +#include <boost/detail/atomic_redef_macros.hpp> +#endif + } + + public: + BOOST_THREAD_MOVABLE_ONLY(promise) +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template <class Allocator> + promise(boost::allocator_arg_t, Allocator a) + { + 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) + {} + + ~promise() + { + 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); + } + } + } + + // Assignment + promise(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; + } + 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; + } + + void swap(promise& other) + { + future_.swap(other.future_); + std::swap(future_obtained,other.future_obtained); + } + + // Result retrieval + BOOST_THREAD_FUTURE<R&> get_future() + { + lazy_init(); + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + if (future_obtained) + { + boost::throw_exception(future_already_retrieved()); + } + future_obtained=true; + return BOOST_THREAD_FUTURE<R&>(future_); + } + + void set_value(R& r) + { + 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); + } + + void set_exception(boost::exception_ptr p) + { + 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 + void set_value_at_thread_exit(R& r) + { + 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> + void set_wait_callback(F f) + { + lazy_init(); + future_->set_wait_callback(f,this); + } + }; + + template <> + class promise<void> + { + typedef boost::shared_ptr<detail::shared_state<void> > future_ptr; + + future_ptr future_; + bool future_obtained; + + void lazy_init() + { +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY + if(!atomic_load(&future_)) + { + future_ptr blank; + atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>)); + } +#endif + } + public: + BOOST_THREAD_MOVABLE_ONLY(promise) + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template <class Allocator> + promise(boost::allocator_arg_t, Allocator a) + { + 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::shared_state<void>(), D(a2, 1) ); + future_obtained = false; + } +#endif + promise(): +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY + future_(), +#else + future_(new detail::shared_state<void>), +#endif + future_obtained(false) + {} + + ~promise() + { + 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); + } + } + } + + // Assignment + promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) + { + // we need to release the future as shared_ptr doesn't implements move semantics + 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; + } + + void swap(promise& other) + { + future_.swap(other.future_); + std::swap(future_obtained,other.future_obtained); + } + + // Result retrieval + BOOST_THREAD_FUTURE<void> get_future() + { + lazy_init(); + + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + if(future_obtained) + { + 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::unique_lock<boost::mutex> lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_finished_with_result_internal(lock); + } + + void set_exception(boost::exception_ptr p) + { + 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 + 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> + void set_wait_callback(F f) + { + lazy_init(); + future_->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::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 + { +#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_shared_state(): + started(false) + {} + + void reset() + { + // todo The packaged_task::reset must be as if an assignemnt froma new packaged_task with the same function + // the reset function is an optimization that avoids reallocating a new task. + started=false; + this->validate(); + } +#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); + 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_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::unique_lock<boost::mutex> lk(this->mutex); + if(!started) + { + started=true; + this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk); + } + } + }; + +#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_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_)) + {} + + F callable() + { + return 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 + 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 + this->mark_finished_with_result(f()); +#endif + } +#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_)) + {} + + F callable() + { + return 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 + 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(res); + } +#endif + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + +#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&); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef R (*CallableType)(ArgTypes ... ); +#else + typedef R (*CallableType)(); +#endif + public: + CallableType f; + task_shared_state(CallableType f_): + f(f_) + {} + + CallableType callable() + { + return 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 + { + R r((f())); + this->set_value_at_thread_exit(boost::move(r)); + } +#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 + 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) + typedef R& (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... ); +#else + typedef R& (*CallableType)(); +#endif + CallableType f; + task_shared_state(CallableType f_): + f(f_) + {} + + CallableType callable() + { + return 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 + 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 + 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_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_shared_state(task_shared_state&); + public: + typedef F CallableType; + F f; + task_shared_state(F const& f_): + f(f_) + {} + task_shared_state(BOOST_THREAD_RV_REF(F) f_): + f(boost::move(f_)) + {} + F callable() + { + return 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(); + } + 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(); + } + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + +#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&); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef void (*CallableType)(ArgTypes...); +#else + typedef void (*CallableType)(); +#endif + public: + CallableType f; + task_shared_state(CallableType f_): + f(f_) + {} + CallableType callable() + { + return 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(); + } + 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(); + } + 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_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; + BOOST_THREAD_MOVABLE_ONLY(packaged_task) + + packaged_task(): + future_obtained(false) + {} + + // construction and destruction +#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) + 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_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 + , 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) + { +#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)(); +#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)) task_shared_state_type(f), D(a2, 1) ); + future_obtained = false; + } +#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_FWD_REF(F) f) + { + 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)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) ); + future_obtained = false; + } +#else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + template <class F, class Allocator> + packaged_task(boost::allocator_arg_t, Allocator a, const 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; + #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)) 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) + { +#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)) task_shared_state_type(boost::move(f)), D(a2, 1) ); + future_obtained = false; + } + +#endif //BOOST_NO_CXX11_RVALUE_REFERENCES +#endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + + ~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) { + 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 { + +#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; + } + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + void set_executor(executor_ptr_type aex) + { + if (!valid()) + boost::throw_exception(task_moved()); + boost::lock_guard<boost::mutex> lk(task->mutex); + task->set_executor_policy(aex, lk); + } +#endif + void reset() { + if (!valid()) + boost::throw_exception(future_error(system::make_error_code(future_errc::no_state))); + + // As if *this = packaged_task(task->callable()); + + task->reset(); + future_obtained=false; + } + + void swap(packaged_task& other) BOOST_NOEXCEPT { + task.swap(other.task); + std::swap(future_obtained,other.future_obtained); + } + bool valid() const BOOST_NOEXCEPT { + return task.get()!=0; + } + + // result retrieval + BOOST_THREAD_FUTURE<R> get_future() { + if(!task) { + boost::throw_exception(task_moved()); + } else if(!future_obtained) { + future_obtained=true; + return BOOST_THREAD_FUTURE<R>(task); + } else { + boost::throw_exception(future_already_retrieved()); + } + } + + // execution +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void operator()(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) { + 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>()); + h->init(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 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 + { + + typedef shared_ptr<shared_state_base > storage_type; + storage_type that; + Fp f_; + public: + + shared_state_nullary_task(storage_type 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.reset(); + } + 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.reset(); + } + return *this; + } +#endif + void operator()() { + shared_ptr<shared_state<Rp> > that_ = static_pointer_cast<shared_state<Rp> >(that); + try { + that_->mark_finished_with_result(f_()); + } catch(...) { + that_->mark_exceptional_finish(); + } + } + ~shared_state_nullary_task() + { + } + }; + + template<typename Fp> + struct shared_state_nullary_task<void, Fp> + { + typedef shared_ptr<shared_state_base > storage_type; + storage_type that; + Fp f_; + public: + shared_state_nullary_task(storage_type 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.reset(); + } + 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.reset(); + } + return *this; + } +#endif + void operator()() { + shared_ptr<shared_state<void> > that_ = static_pointer_cast<shared_state<void> >(that); + try { + f_(); + that_->mark_finished_with_result(); + } catch(...) { + that_->mark_exceptional_finish(); + } + } + }; + +} + BOOST_THREAD_DCL_MOVABLE_BEG2(R,F) detail::shared_state_nullary_task<R,F> BOOST_THREAD_DCL_MOVABLE_END +namespace detail { + + ///////////////////////// + /// future_executor_shared_state_base + ///////////////////////// + template<typename Rp> + struct future_executor_shared_state: shared_state<Rp> + { + typedef shared_state<Rp> base_type; + protected: + public: + future_executor_shared_state() { + } + + template <class Fp, class Executor> + void init(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) + { + typedef typename decay<Fp>::type Cont; + this->set_executor_policy(executor_ptr_type(new executor_ref<Executor>(ex))); + shared_state_nullary_task<Rp,Cont> t(this->shared_from_this(), boost::forward<Fp>(f)); + ex.submit(boost::move(t)); + } + + ~future_executor_shared_state() {} + }; + + //////////////////////////////// + // 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> > + h(new future_executor_shared_state<Rp>()); + h->init(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 + + //////////////////////////////// + // 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 + +#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 + //////////////////////////////// + namespace detail { + template <class T> + struct deduced_type_impl + { + typedef T type; + }; + + template <class T> + struct deduced_type_impl<reference_wrapper<T> const> + { + typedef T& type; + }; + template <class T> + struct deduced_type_impl<reference_wrapper<T> > + { + typedef T& type; + }; +#if __cplusplus > 201103L + template <class T> + struct deduced_type_impl<std::reference_wrapper<T> > + { + typedef T& type; + }; +#endif + template <class T> + struct deduced_type + { + typedef typename detail::deduced_type_impl<typename decay<T>::type>::type type; + }; + + } + + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template <int = 0, int..., class T> +#else + template <class T> +#endif + BOOST_THREAD_FUTURE<typename detail::deduced_type<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) { + typedef typename detail::deduced_type<T>::type future_value_type; + promise<future_value_type> p; + p.set_value(boost::forward<T>(value)); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + + // explicit overloads + template <class T> + BOOST_THREAD_FUTURE<T> make_ready_future(typename remove_reference<T>::type & x) + { + promise<T> p; + p.set_value(x); + return p.get_future(); + } + + template <class T> + BOOST_THREAD_FUTURE<T> make_ready_future(BOOST_THREAD_FWD_REF(typename remove_reference<T>::type) x) + { + promise<T> p; + p.set_value(forward<typename remove_reference<T>::type>(x)); + return p.get_future(); + } + + // variadic overload +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template <class T, class ...Args> + BOOST_THREAD_FUTURE<T> make_ready_future(Args&&... args) + { + promise<T> p; + p.emplace(forward<Args>(args)...); + return p.get_future(); + + } +#endif + + 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_NO_CXX11_VARIADIC_TEMPLATES) || defined BOOST_THREAD_USES_MOVE + inline BOOST_THREAD_FUTURE<void> make_ready_future() { + promise<void> p; + p.set_value(); + return p.get_future(); + } +#endif + + + 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_ready_future(exception_ptr ex) { + return make_exceptional_future<T>(ex); + } + +#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 + +#if defined BOOST_THREAD_CONTINUATION_SYNC +#define continuation_shared_state_base shared_state +#else +#define continuation_shared_state_base future_async_shared_state_base +#endif + +namespace detail +{ + ////////////////////// + // detail::continuation_shared_state + ////////////////////// + template<typename F, typename Rp, typename Fp, class ShSt=shared_state<Rp> > + struct continuation_shared_state: ShSt + { + F parent; + Fp continuation; + + public: + continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : parent(boost::move(f)), + continuation(boost::move(c)) + { + } + + void init(boost::unique_lock<boost::mutex> &lock) + { + parent.future_->set_continuation_ptr(this->shared_from_this(), lock); + } + + void call() { + try { + this->mark_finished_with_result(this->continuation(boost::move(this->parent))); + } catch(...) { + this->mark_exceptional_finish(); + } + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); + } + + void call(boost::unique_lock<boost::mutex>& lck) { + try { + relocker relock(lck); + + // neither continuation nor parent are protected by the lock - call() must only + // be called once, and no one else must modify it. + Rp res = this->continuation(boost::move(this->parent)); + + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); + + relock.lock(); + + this->mark_finished_with_result_internal(boost::move(res), lck); + } catch (...) { + this->mark_exceptional_finish_internal(current_exception(), lck); + + // make sure parent is really cleared to prevent memory "leaks" + relocker relock(lck); + this->parent = F(); + } + } + + static void run(shared_ptr<boost::detail::shared_state_base> that_) + { + continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get()); + that->call(); + } + + ~continuation_shared_state() {} + }; + + template<typename F, typename Fp, class ShSt> + struct continuation_shared_state<F, void, Fp, ShSt>: ShSt + { + F parent; + Fp continuation; + + public: + continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : parent(boost::move(f)), + continuation(boost::move(c)) + { + } + + void init(boost::unique_lock<boost::mutex> &lock) + { + parent.future_->set_continuation_ptr(this->shared_from_this(), lock); + } + + void call() + { + try { + this->continuation(boost::move(this->parent)); + this->mark_finished_with_result(); + } catch(...) { + this->mark_exceptional_finish(); + } + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); + } + + void call(boost::unique_lock<boost::mutex>& lck) { + try { + { + relocker relock(lck); + // neither continuation nor parent are protected by the lock - call() must only + // be called once, and no one else must modify it. + this->continuation(boost::move(this->parent)); + + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); + } + this->mark_finished_with_result_internal(lck); + } catch (...) { + this->mark_exceptional_finish_internal(current_exception(), lck); + + // make sure parent is really cleared to prevent memory "leaks" + relocker relock(lck); + this->parent = F(); + } + } + + static void run(shared_ptr<boost::detail::shared_state_base> that_) + { + continuation_shared_state* that = static_cast<continuation_shared_state*>(that_.get()); + that->call(); + } + + ~continuation_shared_state() {} + }; + ///////////////////////// + /// future_async_continuation_shared_state + ///////////////////////// + + template<typename F, typename Rp, typename Fp> + struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > + { + typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > base_type; + public: + future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward<Fp>(c)) + { } + + void launch_continuation() { +#if defined BOOST_THREAD_CONTINUATION_SYNC + this->call(); +#elif defined BOOST_THREAD_FUTURE_BLOCKING + boost::lock_guard<boost::mutex> lk(this->mutex); + this->thr_ = thread(&future_async_continuation_shared_state::run, static_shared_from_this(this)); +#else + thread(&future_async_continuation_shared_state::run, static_shared_from_this(this)).detach(); +#endif + } + }; + + ///////////////////////// + /// future_executor_continuation_shared_state + ///////////////////////// +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + + template <typename FutureExecutorContinuationSharedState> + struct run_it { + shared_ptr<FutureExecutorContinuationSharedState> that_; + +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_THREAD_COPYABLE_AND_MOVABLE(run_it) + run_it(run_it const& x) //BOOST_NOEXCEPT + : that_(x.that_) + {} + run_it& operator=(BOOST_THREAD_COPY_ASSIGN_REF(run_it) x) //BOOST_NOEXCEPT + { + if (this != &x) { + that_=x.that_; + } + return *this; + } + // move + run_it(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT + : that_(x.that_) + { + x.that_.reset(); + } + run_it& operator=(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT { + if (this != &x) { + that_=x.that; + x.that_.reset(); + } + return *this; + } +#endif + run_it(shared_ptr<FutureExecutorContinuationSharedState> that) : that_ (that) {} + + void operator()() + { + that_->run(that_); + } + }; + +} + BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::run_it<F> BOOST_THREAD_DCL_MOVABLE_END + +namespace detail { + + template<typename F, typename Rp, typename Fp> + struct future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp> + { + typedef continuation_shared_state<F,Rp,Fp> base_type; + + public: + future_executor_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward<Fp>(c)) + { + } + + template <class Ex> + void init(boost::unique_lock<boost::mutex> &lk, Ex& ex) + { + this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk); + this->base_type::init(lk); + } + + void launch_continuation() { + run_it<base_type> fct(static_shared_from_this(this)); + this->get_executor()->submit(boost::move(fct)); + } + + ~future_executor_continuation_shared_state() {} + }; +#endif + + ///////////////////////// + /// shared_future_async_continuation_shared_state + ///////////////////////// + + template<typename F, typename Rp, typename Fp> + struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > + { + typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > base_type; + + public: + shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward<Fp>(c)) + { + } + + void launch_continuation() { +#if defined BOOST_THREAD_CONTINUATION_SYNC + this->call(); +#elif defined BOOST_THREAD_FUTURE_BLOCKING + boost::lock_guard<boost::mutex> lk(this->mutex); + this->thr_ = thread(&shared_future_async_continuation_shared_state::run, static_shared_from_this(this)); +#else + thread(&shared_future_async_continuation_shared_state::run, static_shared_from_this(this)).detach(); +#endif + } + + ~shared_future_async_continuation_shared_state() {} + }; + + ///////////////////////// + /// shared_future_executor_continuation_shared_state + ///////////////////////// +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + + template<typename F, typename Rp, typename Fp> + struct shared_future_executor_continuation_shared_state: continuation_shared_state<F,Rp,Fp> + { + typedef continuation_shared_state<F,Rp,Fp> base_type; + + public: + + shared_future_executor_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward<Fp>(c)) + { + } + + template <class Ex> + void init(boost::unique_lock<boost::mutex> &lk, Ex& ex) + { + this->set_executor_policy(executor_ptr_type(new executor_ref<Ex>(ex)), lk); + this->base_type::init(lk); + } + + void launch_continuation() { + run_it<base_type> fct(static_shared_from_this(this)); + this->get_executor()->submit(boost::move(fct)); + } + + ~shared_future_executor_continuation_shared_state() {} + }; + +#endif + ////////////////////////// + /// future_deferred_continuation_shared_state + ////////////////////////// + template<typename F, typename Rp, typename Fp> + struct future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp> + { + typedef continuation_shared_state<F,Rp,Fp> base_type; + public: + future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward<Fp>(c)) + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock<boost::mutex>& lk) { + this->parent.wait(); + this->call(lk); + } + + virtual void launch_continuation() { } + }; + + ////////////////////////// + /// shared_future_deferred_continuation_shared_state + ////////////////////////// + template<typename F, typename Rp, typename Fp> + struct shared_future_deferred_continuation_shared_state: continuation_shared_state<F,Rp,Fp> + { + typedef continuation_shared_state<F,Rp,Fp> base_type; + + public: + shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward<Fp>(c)) + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock<boost::mutex>& lk) { + this->parent.wait(); + this->call(lk); + } + + virtual void launch_continuation() { } + }; + + //////////////////////////////// + // 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) { + typedef typename decay<Fp>::type Cont; + shared_ptr<future_deferred_continuation_shared_state<F, Rp, Cont> > + h(new future_deferred_continuation_shared_state<F, Rp, Cont>(boost::move(f), boost::forward<Fp>(c))); + h->init(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) { + typedef typename decay<Fp>::type Cont; + shared_ptr<future_async_continuation_shared_state<F,Rp, Cont> > + h(new future_async_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c))); + h->init(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) { + typedef typename decay<Fp>::type Cont; + shared_ptr<future_executor_continuation_shared_state<F,Rp, Cont> > + h(new future_executor_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c))); + h->init(lock, ex); + + 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) { + typedef typename decay<Fp>::type Cont; + shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Cont> > + h(new shared_future_deferred_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c))); + h->init(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) { + typedef typename decay<Fp>::type Cont; + shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Cont> > + h(new shared_future_async_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c))); + h->init(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) { + typedef typename decay<Fp>::type Cont; + shared_ptr<shared_future_executor_continuation_shared_state<F, Rp, Cont> > + h(new shared_future_executor_continuation_shared_state<F, Rp, Cont>(f, boost::forward<Fp>(c))); + h->init(lock, ex); + + return BOOST_THREAD_FUTURE<Rp>(h); + } +#endif +} + + //////////////////////////////// + // template<typename F> + // auto future<R>::then(launch policy, 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()); + + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->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>( + 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>( + lock, boost::move(*this), boost::forward<F>(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, + lock, boost::move(*this), boost::forward<F>(func) + ))); +#endif + } else if (underlying_cast<int>(policy) & int(launch::inherit)) { + + launch policy = this->launch_policy(lock); + 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>( + 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>( + lock, boost::move(*this), boost::forward<F>(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, + lock, boost::move(*this), boost::forward<F>(func) + ))); +#endif + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + 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>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } + } +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + //////////////////////////////// + // template<typename Ex, typename F> + // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// + 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()); + + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, + lock, boost::move(*this), boost::forward<F>(func) + ))); + } +#endif + //////////////////////////////// + // template<typename F> + // auto future<future<R2> >::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(BOOST_THREAD_FWD_REF(F) func) { + +#ifndef BOOST_THREAD_CONTINUATION_SYNC + return this->then(this->launch_policy(), boost::forward<F>(func)); +#else + typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + + launch policy = this->launch_policy(lock); + 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>( + 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>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } +#endif + + } + + //////////////////////////////// + // template<typename F> + // auto future<future<R2> >::then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// + template <typename R2> + template <typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type> + BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) { + typedef BOOST_THREAD_FUTURE<R2> R; + typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->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>( + 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>( + lock, boost::move(*this), boost::forward<F>(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, + lock, boost::move(*this), boost::forward<F>(func) + ))); +#endif + } else if (underlying_cast<int>(policy) & int(launch::inherit)) { + launch policy = this->launch_policy(lock); + + 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>( + 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>( + lock, boost::move(*this), boost::forward<F>(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, + lock, boost::move(*this), boost::forward<F>(func) + ))); +#endif + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>( + 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>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } + } + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + //////////////////////////////// + // template<typename Ex, typename F> + // auto future<future<R2> >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// + template <typename R2> + template <typename Ex, typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type> + BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) { + typedef BOOST_THREAD_FUTURE<R2> R; + typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type>(ex, + lock, boost::move(*this), boost::forward<F>(func) + ))); + } +#endif + + //////////////////////////////// + // template<typename F> + // auto future<future<R2> >::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// + template <typename R2> + template <typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type> + BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(BOOST_THREAD_FWD_REF(F) func) { + +#ifndef BOOST_THREAD_CONTINUATION_SYNC + return this->then(this->launch_policy(), boost::forward<F>(func)); +#else + typedef BOOST_THREAD_FUTURE<R2> R; + typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->mutex); + + launch policy = this->launch_policy(lock); + + 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>( + 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>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } +#endif + } + + //////////////////////////////// + // template<typename F> + // auto shared_future<R>::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// + 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>( + 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>( + lock, *this, boost::forward<F>(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex, + lock, *this, boost::forward<F>(func) + ))); +#endif + } else if (underlying_cast<int>(policy) & int(launch::inherit)) { + + launch policy = this->launch_policy(lock); + 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>( + 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>( + lock, *this, boost::forward<F>(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast<int>(policy) & int(launch::executor)) { + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex, + lock, *this, boost::forward<F>(func) + ))); +#endif + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>( + 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>( + lock, *this, boost::forward<F>(func) + ))); + } + } +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + //////////////////////////////// + // template<typename Ex, typename F> + // auto shared_future<R>::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// + 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>(ex, + lock, *this, boost::forward<F>(func) + ))); + } +#endif + + //////////////////////////////// + // template<typename F> + // auto shared_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(shared_future<R>)>::type> + shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const { +#ifndef BOOST_THREAD_CONTINUATION_SYNC + return this->then(this->launch_policy(), boost::forward<F>(func)); +#else + 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); + launch policy = this->launch_policy(lock); + 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>( + 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>( + lock, *this, boost::forward<F>(func) + ))); + } +#endif + } + +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) const { + 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 wrapped; + typename F::value_type unwrapped; + public: + explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f) + : wrapped(boost::move(f)) { + } + + void launch_continuation() + { + boost::unique_lock<boost::mutex> lk(this->mutex); + // assert(wrapped.is_ready()); + if (! unwrapped.valid() ) + { + if (wrapped.has_exception()) { + this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk); + } else { + unwrapped = wrapped.get(); + if (unwrapped.valid()) + { + lk.unlock(); + boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex); + unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2); + } else { + this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk); + } + } + } else { + // assert(unwrapped.is_ready()); + if (unwrapped.has_exception()) { + this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk); + } else { + this->mark_finished_with_result_internal(unwrapped.get(), lk); + } + } + } + }; + + template<typename F> + struct future_unwrap_shared_state<F,void>: shared_state<void> + { + F wrapped; + typename F::value_type unwrapped; + public: + explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f) + : wrapped(boost::move(f)) { + } + + void launch_continuation() + { + boost::unique_lock<boost::mutex> lk(this->mutex); + // assert(wrapped.is_ready()); + if (! unwrapped.valid() ) + { + if (wrapped.has_exception()) { + this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk); + } else { + unwrapped = wrapped.get(); + if (unwrapped.valid()) + { + lk.unlock(); + boost::unique_lock<boost::mutex> lk2(unwrapped.future_->mutex); + unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2); + } else { + this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk); + } + } + } else { + // assert(unwrapped.is_ready()); + if (unwrapped.has_exception()) { + this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk); + } else { + this->mark_finished_with_result_internal(lk); + } + } + } + }; + + 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->wrapped.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()); + + // keep state alive as we move ourself but hold the lock + shared_ptr<detail::shared_state_base> sentinel(this->future_); + boost::unique_lock<boost::mutex> lock(sentinel->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(shared_ptr<boost::detail::shared_state_base> that_) { + future_when_all_vector_shared_state* that = static_cast<future_when_all_vector_shared_state*>(that_.get()); + try { + boost::wait_for_all(that->vec_.begin(), that->vec_.end()); + that->mark_finished_with_result(boost::move(that->vec_)); + } 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->shared_from_this()); + return; + } +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_when_all_vector_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_all_vector_shared_state::run, this->shared_from_this()).detach(); +#endif + } + + 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)) + { + } + + future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v) + : vec_(boost::move(v)) + { + } + +#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 + } +#endif + + ~future_when_all_vector_shared_state() {} + }; + + //////////////////////////////// + // 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(shared_ptr<boost::detail::shared_state_base> that_) + { + future_when_any_vector_shared_state* that = static_cast<future_when_any_vector_shared_state*>(that_.get()); + try { + boost::wait_for_any(that->vec_.begin(), that->vec_.end()); + that->mark_finished_with_result(boost::move(that->vec_)); + } 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->shared_from_this()); + return; + } + +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_when_any_vector_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_any_vector_shared_state::run, this->shared_from_this()).detach(); +#endif + } + + 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)) + { + } + + future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v) + : vec_(boost::move(v)) + { + } + +#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 + } +#endif + + ~future_when_any_vector_shared_state() {} + }; + +#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(shared_ptr<boost::detail::shared_state_base> that_) { + future_when_all_tuple_shared_state* that = static_cast<future_when_all_tuple_shared_state*>(that_.get()); + 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_)); + } 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->shared_from_this()); + return; + } +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()).detach(); +#endif + + } + 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)...)) + { + } + + ~future_when_all_tuple_shared_state() {} + + }; + + + 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(shared_ptr<boost::detail::shared_state_base> that_) + { + future_when_any_tuple_shared_state* that = static_cast<future_when_any_tuple_shared_state*>(that_.get()); + 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_)); + } 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->shared_from_this()); + return; + } + +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()).detach(); +#endif + } + + 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)...)) + { + } + + ~future_when_any_tuple_shared_state() {} + }; +#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)); + h->init(); + 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)...)); + h->init(); + 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)); + h->init(); + 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)...)); + h->init(); + return BOOST_THREAD_FUTURE<container_type>(h); + } +#endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +} + +#endif // BOOST_NO_EXCEPTION +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/future_error.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/future_error.hpp new file mode 100644 index 00000000000..6212deece36 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/future_error.hpp @@ -0,0 +1,98 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 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_FUTURES_FUTURE_ERROR_HPP +#define BOOST_THREAD_FUTURES_FUTURE_ERROR_HPP + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/futures/future_error_code.hpp> +#include <boost/system/error_code.hpp> + +#include <stdexcept> + +namespace boost +{ + class BOOST_SYMBOL_VISIBLE future_error + : public std::logic_error + { + system::error_code ec_; + public: + future_error(system::error_code ec) + : logic_error(ec.message()), + ec_(ec) + { + } + + const system::error_code& code() const BOOST_NOEXCEPT + { + return ec_; + } + }; + + class BOOST_SYMBOL_VISIBLE future_uninitialized: + public future_error + { + public: + future_uninitialized() : + future_error(system::make_error_code(future_errc::no_state)) + {} + }; + class BOOST_SYMBOL_VISIBLE broken_promise: + public future_error + { + public: + broken_promise(): + future_error(system::make_error_code(future_errc::broken_promise)) + {} + }; + class BOOST_SYMBOL_VISIBLE future_already_retrieved: + public future_error + { + public: + future_already_retrieved(): + future_error(system::make_error_code(future_errc::future_already_retrieved)) + {} + }; + class BOOST_SYMBOL_VISIBLE promise_already_satisfied: + public future_error + { + public: + promise_already_satisfied(): + future_error(system::make_error_code(future_errc::promise_already_satisfied)) + {} + }; + + class BOOST_SYMBOL_VISIBLE task_already_started: + public future_error + { + public: + task_already_started(): + future_error(system::make_error_code(future_errc::promise_already_satisfied)) + {} + }; + + 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)) + {} + }; +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/future_error_code.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/future_error_code.hpp new file mode 100644 index 00000000000..7c8b6f2696a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/future_error_code.hpp @@ -0,0 +1,61 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2012,2015 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_FUTURES_FUTURE_ERROR_CODE_HPP +#define BOOST_THREAD_FUTURES_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/src/third_party/boost-1.60.0/boost/thread/futures/future_status.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/future_status.hpp new file mode 100644 index 00000000000..383ac4673cf --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/future_status.hpp @@ -0,0 +1,30 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 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_FUTURES_FUTURE_STATUS_HPP +#define BOOST_THREAD_FUTURES_FUTURE_STATUS_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/core/scoped_enum.hpp> + +namespace boost +{ + //enum class future_status + BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status) + { + ready, + timeout, + deferred + } + BOOST_SCOPED_ENUM_DECLARE_END(future_status) + namespace future_state + { + enum state { uninitialized, waiting, ready, moved, deferred }; + } +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/is_future_type.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/is_future_type.hpp new file mode 100644 index 00000000000..df7a680faae --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/is_future_type.hpp @@ -0,0 +1,21 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 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_FUTURES_IS_FUTURE_TYPE_HPP +#define BOOST_THREAD_FUTURES_IS_FUTURE_TYPE_HPP + +#include <boost/type_traits/integral_constant.hpp> + +namespace boost +{ + template<typename T> + struct is_future_type : false_type + { + }; +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/launch.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/launch.hpp new file mode 100644 index 00000000000..8eed42cf4d0 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/launch.hpp @@ -0,0 +1,31 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 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_FUTURES_LAUNCH_HPP +#define BOOST_THREAD_FUTURES_LAUNCH_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/core/scoped_enum.hpp> + +namespace boost +{ + //enum class launch + BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch) + { + none = 0, + async = 1, + deferred = 2, +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + executor = 4, +#endif + inherit = 8, + any = async | deferred + } + BOOST_SCOPED_ENUM_DECLARE_END(launch) +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_all.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_all.hpp new file mode 100644 index 00000000000..90cc2b77cb3 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_all.hpp @@ -0,0 +1,74 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 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_FUTURES_WAIT_FOR_ALL_HPP +#define BOOST_THREAD_FUTURES_WAIT_FOR_ALL_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/futures/is_future_type.hpp> + +#include <boost/core/enable_if.hpp> + +namespace boost +{ + template<typename Iterator> + typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end) + { + for(Iterator current=begin;current!=end;++current) + { + current->wait(); + } + } + +#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) + { + f1.wait(); + f2.wait(); + } + + template<typename F1,typename F2,typename F3> + void wait_for_all(F1& f1,F2& f2,F3& f3) + { + f1.wait(); + f2.wait(); + f3.wait(); + } + + template<typename F1,typename F2,typename F3,typename F4> + void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4) + { + f1.wait(); + f2.wait(); + f3.wait(); + f4.wait(); + } + + template<typename F1,typename F2,typename F3,typename F4,typename F5> + void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5) + { + f1.wait(); + f2.wait(); + f3.wait(); + 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)} + +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_any.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_any.hpp new file mode 100644 index 00000000000..b869a4318a8 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_any.hpp @@ -0,0 +1,161 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 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_FUTURES_WAIT_FOR_ANY_HPP +#define BOOST_THREAD_FUTURES_WAIT_FOR_ANY_HPP + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/detail/move.hpp> +#include <boost/thread/futures/is_future_type.hpp> +#include <boost/thread/lock_algorithms.hpp> +#include <boost/thread/mutex.hpp> + +#include <boost/core/enable_if.hpp> +#include <boost/next_prior.hpp> +#include <boost/scoped_array.hpp> + +#include <iterator> +#include <vector> + +namespace boost +{ + namespace detail + { + template <class Future> + class waiter_for_any_in_seq + { + struct registered_waiter; + typedef std::vector<int>::size_type count_type; + + struct registered_waiter + { + typedef Future future_type; + future_type* future_; + typedef typename Future::notify_when_ready_handle notify_when_ready_handle; + notify_when_ready_handle handle; + count_type index; + + registered_waiter(future_type & a_future, + notify_when_ready_handle handle_, count_type index_) : + future_(&a_future), handle(handle_), index(index_) + { + } + }; + + struct all_futures_lock + { +#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>& waiters) : + count(waiters.size()), locks(new boost::unique_lock<boost::mutex>[count]) + { + for (count_type_portable i = 0; i < count; ++i) + { + locks[i] = BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(waiters[i].future_->mutex())); + } + } + + void lock() + { + boost::lock(locks.get(), locks.get() + count); + } + + void unlock() + { + for (count_type_portable i = 0; i < count; ++i) + { + locks[i].unlock(); + } + } + }; + + boost::condition_variable_any cv; + std::vector<registered_waiter> waiters_; + count_type future_count; + + public: + waiter_for_any_in_seq() : + future_count(0) + { + } + + template <typename F> + void add(F& f) + { + if (f.valid()) + { + registered_waiter waiter(f, f.notify_when_ready(cv), future_count); + try + { + waiters_.push_back(waiter); + } + catch (...) + { + f.future_->unnotify_when_ready(waiter.handle); + 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(waiters_); + for (;;) + { + for (count_type i = 0; i < waiters_.size(); ++i) + { + if (waiters_[i].future_->is_ready(lk.locks[i])) + { + return waiters_[i].index; + } + } + cv.wait(lk); + } + } + + ~waiter_for_any_in_seq() + { + for (count_type i = 0; i < waiters_.size(); ++i) + { + waiters_[i].future_->unnotify_when_ready(waiters_[i].handle); + } + } + }; + } + + template <typename Iterator> + typename boost::disable_if<is_future_type<Iterator> , Iterator>::type wait_for_any(Iterator begin, Iterator end) + { + if (begin == end) return end; + + detail::waiter_for_any_in_seq<typename std::iterator_traits<Iterator>::value_type> waiter; + for (Iterator current = begin; current != end; ++current) + { + waiter.add(*current); + } + return boost::next(begin, waiter.wait()); + } +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/is_locked_by_this_thread.hpp b/src/third_party/boost-1.60.0/boost/thread/is_locked_by_this_thread.hpp new file mode 100644 index 00000000000..6344c0ff6dd --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/latch.hpp b/src/third_party/boost-1.60.0/boost/thread/latch.hpp new file mode 100644 index 00000000000..dc921e68fe6 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/latch.hpp @@ -0,0 +1,170 @@ +// 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> &) + /// 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_); + if (count_ == 0) return; + 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_); + if (count_ == 0) return cv_status::no_timeout; + 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_); + if (count_ == 0) return cv_status::no_timeout; + 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/src/third_party/boost-1.60.0/boost/thread/lock_algorithms.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_algorithms.hpp new file mode 100644 index 00000000000..7a55f92a289 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/lock_concepts.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_concepts.hpp new file mode 100644 index 00000000000..d96c3dc1b96 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/lock_factories.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_factories.hpp new file mode 100644 index 00000000000..523b90a5eac --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/lock_guard.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_guard.hpp new file mode 100644 index 00000000000..4c2908af43f --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/lock_options.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_options.hpp new file mode 100644 index 00000000000..68899ca89fe --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/lock_traits.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_traits.hpp new file mode 100644 index 00000000000..e45d8229831 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/lock_types.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_types.hpp new file mode 100644 index 00000000000..2b73edfb02a --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/lockable_adapter.hpp b/src/third_party/boost-1.60.0/boost/thread/lockable_adapter.hpp new file mode 100644 index 00000000000..93d9ba5023c --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/lockable_concepts.hpp b/src/third_party/boost-1.60.0/boost/thread/lockable_concepts.hpp new file mode 100644 index 00000000000..bedd962e3be --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/lockable_traits.hpp b/src/third_party/boost-1.60.0/boost/thread/lockable_traits.hpp new file mode 100644 index 00000000000..8a17ae72d3f --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/locks.hpp b/src/third_party/boost-1.60.0/boost/thread/locks.hpp new file mode 100644 index 00000000000..6749964cf52 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/locks.hpp @@ -0,0 +1,16 @@ +// 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_LOCKS_HPP +#define BOOST_THREAD_LOCKS_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/src/third_party/boost-1.60.0/boost/thread/mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/mutex.hpp new file mode 100644 index 00000000000..05c60941c46 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/mutex.hpp @@ -0,0 +1,53 @@ +#ifndef BOOST_THREAD_MUTEX_HPP +#define BOOST_THREAD_MUTEX_HPP + +// mutex.hpp +// +// (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/platform.hpp> +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include <boost/thread/win32/mutex.hpp> +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include <boost/thread/pthread/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<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/src/third_party/boost-1.60.0/boost/thread/null_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/null_mutex.hpp new file mode 100644 index 00000000000..f439f9ffb27 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/once.hpp b/src/third_party/boost-1.60.0/boost/thread/once.hpp new file mode 100644 index 00000000000..9fcfb533397 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/once.hpp @@ -0,0 +1,44 @@ +#ifndef BOOST_THREAD_ONCE_HPP +#define BOOST_THREAD_ONCE_HPP + +// once.hpp +// +// (C) Copyright 2006-7 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> +#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 + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + // template<class Callable, class ...Args> void + // call_once(once_flag& flag, Callable&& func, Args&&... args); +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); + } +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/ostream_buffer.hpp b/src/third_party/boost-1.60.0/boost/thread/ostream_buffer.hpp new file mode 100644 index 00000000000..cc02a9c0cee --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/poly_lockable.hpp b/src/third_party/boost-1.60.0/boost/thread/poly_lockable.hpp new file mode 100644 index 00000000000..fffcbce1330 --- /dev/null +++ b/src/third_party/boost-1.60.0/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 + { + public: + + virtual ~poly_lockable() = 0; + virtual bool try_lock() = 0; + }; + //] + + //[timed_poly_lockable + class timed_poly_lockable: public poly_lockable + { + 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/src/third_party/boost-1.60.0/boost/thread/poly_lockable_adapter.hpp b/src/third_party/boost-1.60.0/boost/thread/poly_lockable_adapter.hpp new file mode 100644 index 00000000000..448789ecbc8 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable.hpp b/src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable.hpp new file mode 100644 index 00000000000..4348ed76c25 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable_adapter.hpp b/src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable_adapter.hpp new file mode 100644 index 00000000000..f1361289078 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable.hpp new file mode 100644 index 00000000000..a6033515915 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable.hpp @@ -0,0 +1,428 @@ +#ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP +#define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_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 2007-10 Anthony Williams +// (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> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/thread/detail/delete.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + namespace this_thread + { + void BOOST_THREAD_DECL interruption_point(); + } +#endif + + namespace thread_cv_detail + { + template<typename MutexType> + struct lock_on_exit + { + MutexType* m; + + lock_on_exit(): + m(0) + {} + + void activate(MutexType& m_) + { + m_.unlock(); + m=&m_; + } + ~lock_on_exit() + { + if(m) + { + m->lock(); + } + } + }; + } + + 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); + pthread_mutex_t* the_mutex = &internal_mutex; + guard.activate(m); +#else + pthread_mutex_t* the_mutex = m.mutex()->native_handle(); +#endif + do { + res = pthread_cond_wait(&cond,the_mutex); + } while (res == EINTR); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + this_thread::interruption_point(); +#endif + if(res) + { + boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_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, "boost::condition_variable::do_wait_until() failed precondition mutex not owned")); + } +#endif + int cond_res; + { +#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); + pthread_mutex_t* the_mutex = &internal_mutex; + guard.activate(m); +#else + pthread_mutex_t* the_mutex = m.mutex()->native_handle(); +#endif + cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout); + } +#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, "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)); + } + + class condition_variable_any + { + pthread_mutex_t internal_mutex; + pthread_cond_t cond; + + public: + BOOST_THREAD_NO_COPYABLE(condition_variable_any) + condition_variable_any() + { + int const res=pthread_mutex_init(&internal_mutex,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init")); + } + int const res2 = detail::monotonic_pthread_cond_init(cond); + if(res2) + { + BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); + boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init")); + } + } + ~condition_variable_any() + { + BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); + BOOST_VERIFY(!pthread_cond_destroy(&cond)); + } + + template<typename lock_type> + void wait(lock_type& m) + { + 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, "boost::condition_variable_any::wait() failed in pthread_cond_wait")); + } + } + + template<typename lock_type,typename predicate_type> + void wait(lock_type& m,predicate_type pred) + { + 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) + { + 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& abs_time) + { + return timed_wait(m,system_time(abs_time)); + } + + template<typename lock_type,typename duration_type> + bool timed_wait(lock_type& m,duration_type const& wait_duration) + { + return timed_wait(m,get_system_time()+wait_duration); + } + + template<typename lock_type,typename predicate_type> + bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred) + { + while (!pred()) + { + 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& abs_time, predicate_type pred) + { + return timed_wait(m,system_time(abs_time),pred); + } + + template<typename lock_type,typename duration_type,typename predicate_type> + bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred) + { + return timed_wait(m,get_system_time()+wait_duration,pred); + } +#endif +#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + +#ifdef BOOST_THREAD_USES_CHRONO + template <class lock_type,class Duration> + cv_status + wait_until( + lock_type& lock, + const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + return system_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class lock_type, class Clock, class Duration> + cv_status + wait_until( + lock_type& lock, + 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(); + wait_until(lock, s_now + ceil<nanoseconds>(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + template <class lock_type, class Rep, class Period> + cv_status + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, s_now + ceil<nanoseconds>(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + + } + + template <class lock_type> + 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 = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif +#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#ifdef BOOST_THREAD_USES_CHRONO + + template <class lock_type, class Duration> + cv_status + wait_until( + lock_type& lock, + const chrono::time_point<chrono::steady_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + return steady_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class lock_type, class Clock, class Duration> + cv_status + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + steady_clock::time_point s_now = steady_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil<nanoseconds>(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + template <class lock_type, class Rep, class Period> + cv_status + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, c_now + ceil<nanoseconds>(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + inline cv_status wait_until( + unique_lock<mutex>& lk, + chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } + +#endif +#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + +#ifdef BOOST_THREAD_USES_CHRONO + template <class lock_type, class Clock, class Duration, class Predicate> + bool + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + template <class lock_type, class Rep, class Period, class Predicate> + bool + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + } +#endif + + void notify_one() BOOST_NOEXCEPT + { + boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); + BOOST_VERIFY(!pthread_cond_signal(&cond)); + } + + void notify_all() BOOST_NOEXCEPT + { + boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); + BOOST_VERIFY(!pthread_cond_broadcast(&cond)); + } + private: // used by boost::thread::try_join_until + + template <class lock_type> + 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, "boost::condition_variable_any::do_wait_until() failed in pthread_cond_timedwait")); + } + return true; + } + }; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable_fwd.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable_fwd.hpp new file mode 100644 index 00000000000..1255eac59b7 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable_fwd.hpp @@ -0,0 +1,360 @@ +#ifndef BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP +#define BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_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 2007-8 Anthony Williams +// (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/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 +{ + namespace detail { + inline int monotonic_pthread_cond_init(pthread_cond_t& cond) { + +#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + pthread_condattr_t attr; + int res = pthread_condattr_init(&attr); + if (res) + { + return res; + } + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + res=pthread_cond_init(&cond,&attr); + pthread_condattr_destroy(&attr); + return res; +#else + return pthread_cond_init(&cond,NULL); +#endif + + } + } + + 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 res=pthread_mutex_init(&internal_mutex,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init")); + } +#endif + res = detail::monotonic_pthread_cond_init(cond); + if (res) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); +#endif + boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init")); + } + } + ~condition_variable() + { + 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_ASSERT(!ret); + } + + void wait(unique_lock<mutex>& m); + + template<typename predicate_type> + void wait(unique_lock<mutex>& m,predicate_type pred) + { + while(!pred()) wait(m); + } + +#if defined BOOST_THREAD_USES_DATETIME + inline bool timed_wait( + unique_lock<mutex>& m, + boost::system_time const& abs_time) + { +#if defined BOOST_THREAD_WAIT_BUG + 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::to_timespec(abs_time); + return do_wait_until(m, timeout); +#endif + } + bool timed_wait( + unique_lock<mutex>& m, + xtime const& abs_time) + { + return timed_wait(m,system_time(abs_time)); + } + + template<typename duration_type> + bool timed_wait( + unique_lock<mutex>& m, + duration_type const& wait_duration) + { + 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 timed_wait(m,get_system_time()+wait_duration); + } + + template<typename predicate_type> + bool timed_wait( + unique_lock<mutex>& m, + boost::system_time const& abs_time,predicate_type pred) + { + while (!pred()) + { + if(!timed_wait(m, abs_time)) + return pred(); + } + return true; + } + + template<typename predicate_type> + bool timed_wait( + unique_lock<mutex>& m, + xtime const& abs_time,predicate_type pred) + { + return timed_wait(m,system_time(abs_time),pred); + } + + template<typename duration_type,typename predicate_type> + bool timed_wait( + unique_lock<mutex>& m, + duration_type const& wait_duration,predicate_type pred) + { + if (wait_duration.is_pos_infinity()) + { + while (!pred()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + } + return true; + } + if (wait_duration.is_special()) + { + return pred(); + } + return timed_wait(m,get_system_time()+wait_duration,pred); + } +#endif + +#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Duration> + cv_status + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + return system_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class Clock, class Duration> + cv_status + wait_until( + unique_lock<mutex>& lock, + 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(); + wait_until(lock, s_now + ceil<nanoseconds>(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + + + template <class Rep, class Period> + cv_status + wait_for( + unique_lock<mutex>& lock, + const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, s_now + ceil<nanoseconds>(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + + } + + 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 = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif + +#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Duration> + cv_status + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<chrono::steady_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + return steady_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class Clock, class Duration> + cv_status + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + steady_clock::time_point s_now = steady_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil<nanoseconds>(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + template <class Rep, class Period> + cv_status + wait_for( + unique_lock<mutex>& lock, + const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, c_now + ceil<nanoseconds>(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + inline cv_status wait_until( + unique_lock<mutex>& lk, + chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif + +#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + +#ifdef BOOST_THREAD_USES_CHRONO + template <class Clock, class Duration, class Predicate> + bool + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + template <class Rep, class Period, class Predicate> + bool + wait_for( + unique_lock<mutex>& lock, + const chrono::duration<Rep, Period>& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + } +#endif + +#define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE + typedef pthread_cond_t* native_handle_type; + native_handle_type native_handle() + { + return &cond; + } + + void notify_one() BOOST_NOEXCEPT; + void notify_all() BOOST_NOEXCEPT; + + + }; + + 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/src/third_party/boost-1.60.0/boost/thread/pthread/mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/mutex.hpp new file mode 100644 index 00000000000..9ac808b6f4a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/mutex.hpp @@ -0,0 +1,361 @@ +#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP +#define BOOST_THREAD_PTHREAD_MUTEX_HPP +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011,2012,2015 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/assert.hpp> +#include <pthread.h> +#include <boost/throw_exception.hpp> +#include <boost/core/ignore_unused.hpp> +#include <boost/thread/exceptions.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> +#include <errno.h> +#include <boost/thread/pthread/timespec.hpp> +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/thread/detail/delete.hpp> + +#if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \ + || (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21) +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK +#define BOOST_PTHREAD_HAS_TIMEDLOCK +#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: + pthread_mutex_t m; + public: + BOOST_THREAD_NO_COPYABLE(mutex) + + mutex() + { + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init")); + } + } + ~mutex() + { + int const res = posix::pthread_mutex_destroy(&m); + boost::ignore_unused(res); + BOOST_ASSERT(!res); + } + + void lock() + { + 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() + { + int res = posix::pthread_mutex_unlock(&m); + (void)res; + BOOST_ASSERT(res == 0); +// if (res) +// { +// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); +// } + } + + bool try_lock() + { + int res; + do + { + res = pthread_mutex_trylock(&m); + } while (res == EINTR); + if (res==EBUSY) + { + return false; + } + + return !res; + } + +#define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE + typedef pthread_mutex_t* native_handle_type; + native_handle_type native_handle() + { + 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; + + class timed_mutex + { + private: + pthread_mutex_t m; +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK + pthread_cond_t cond; + bool is_locked; +#endif + public: + BOOST_THREAD_NO_COPYABLE(timed_mutex) + timed_mutex() + { + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init")); + } +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK + int const res2=pthread_cond_init(&cond,NULL); + if(res2) + { + 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; +#endif + } + ~timed_mutex() + { + 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) + { + return timed_lock(get_system_time()+relative_time); + } + bool timed_lock(boost::xtime const & absolute_time) + { + return timed_lock(system_time(absolute_time)); + } +#endif +#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK + void lock() + { + 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() + { + int res = posix::pthread_mutex_unlock(&m); + (void)res; + BOOST_ASSERT(res == 0); +// if (res) +// { +// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); +// } + } + + bool try_lock() + { + int res; + do + { + res = pthread_mutex_trylock(&m); + } while (res == EINTR); + if (res==EBUSY) + { + return false; + } + + return !res; + } + + + private: + bool do_try_lock_until(struct timespec const &timeout) + { + int const res=pthread_mutex_timedlock(&m,&timeout); + BOOST_ASSERT(!res || res==ETIMEDOUT); + return !res; + } + public: + +#else + void lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + while(is_locked) + { + BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); + } + is_locked=true; + } + + void unlock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + is_locked=false; + BOOST_VERIFY(!pthread_cond_signal(&cond)); + } + + bool try_lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked) + { + return false; + } + is_locked=true; + return true; + } + + private: + bool do_try_lock_until(struct timespec const &timeout) + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + while(is_locked) + { + int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout); + if(cond_res==ETIMEDOUT) + { + return false; + } + BOOST_ASSERT(!cond_res); + } + is_locked=true; + return true; + } + public: +#endif + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(system_time const & 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) + { + 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>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil<nanoseconds>(t - c_now)); + } + template <class Duration> + bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; + return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) + { + //using namespace chrono; + chrono::nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + return do_try_lock_until(ts); + } +#endif + +#define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE + typedef pthread_mutex_t* native_handle_type; + native_handle_type native_handle() + { + 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 + }; + +} + +#include <boost/config/abi_suffix.hpp> + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/once.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/once.hpp new file mode 100644 index 00000000000..0bef0387de7 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/once.hpp @@ -0,0 +1,540 @@ +#ifndef BOOST_THREAD_PTHREAD_ONCE_HPP +#define BOOST_THREAD_PTHREAD_ONCE_HPP + +// once.hpp +// +// (C) Copyright 2007-8 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) + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/invoke.hpp> + +#include <boost/thread/pthread/pthread_mutex_scoped_lock.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 +{ + + 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 + { + BOOST_THREAD_NO_COPYABLE(once_flag) + BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT + : epoch(BOOST_ONCE_INITIAL_FLAG_VALUE) + {} + private: + 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); + 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 + { + volatile thread_detail::uintmax_atomic_t epoch; + }; + +#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE} +#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 thread_detail + { + 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 + + +#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) + { + 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<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; + + } + } +#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) + { + 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, 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 + } + 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> + 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> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/once_atomic.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/once_atomic.hpp new file mode 100644 index 00000000000..c54a35c5413 --- /dev/null +++ b/src/third_party/boost-1.60.0/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); + } + } +#if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130)) + 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 // __SUNPRO_CC + +#endif +} + +#include <boost/config/abi_suffix.hpp> + +#endif + diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/pthread_mutex_scoped_lock.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/pthread_mutex_scoped_lock.hpp new file mode 100644 index 00000000000..cdbf8c67408 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/pthread_mutex_scoped_lock.hpp @@ -0,0 +1,64 @@ +#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP +#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP +// (C) Copyright 2007-8 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 <pthread.h> +#include <boost/assert.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace pthread + { + class pthread_mutex_scoped_lock + { + pthread_mutex_t* m; + bool locked; + public: + explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_): + m(m_),locked(true) + { + BOOST_VERIFY(!pthread_mutex_lock(m)); + } + void unlock() + { + BOOST_VERIFY(!pthread_mutex_unlock(m)); + locked=false; + } + + ~pthread_mutex_scoped_lock() + { + if(locked) + { + unlock(); + } + } + + }; + + class pthread_mutex_scoped_unlock + { + pthread_mutex_t* m; + public: + explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_): + m(m_) + { + BOOST_VERIFY(!pthread_mutex_unlock(m)); + } + ~pthread_mutex_scoped_unlock() + { + BOOST_VERIFY(!pthread_mutex_lock(m)); + } + + }; + } +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/recursive_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/recursive_mutex.hpp new file mode 100644 index 00000000000..4caae0b5df9 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/recursive_mutex.hpp @@ -0,0 +1,404 @@ +#ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP +#define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP +// (C) Copyright 2007-8 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) + +#include <pthread.h> +#include <boost/throw_exception.hpp> +#include <boost/thread/exceptions.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 +#include <unistd.h> +#endif +#include <boost/date_time/posix_time/conversion.hpp> +#include <errno.h> +#include <boost/thread/pthread/timespec.hpp> +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/thread/detail/delete.hpp> + +#if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \ + || (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21) +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK +#define BOOST_PTHREAD_HAS_TIMEDLOCK +#endif +#endif + +#if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \ + || defined __ANDROID__ +#define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE +#endif + +#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK +#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK +#endif + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + class recursive_mutex + { + private: + pthread_mutex_t m; +#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE + pthread_cond_t cond; + bool is_locked; + pthread_t owner; + unsigned count; +#endif + public: + BOOST_THREAD_NO_COPYABLE(recursive_mutex) + recursive_mutex() + { +#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE + pthread_mutexattr_t attr; + + int const init_attr_res=pthread_mutexattr_init(&attr); + if(init_attr_res) + { + boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_init")); + } + int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); + if(set_attr_res) + { + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); + boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype")); + } + + int const res=pthread_mutex_init(&m,&attr); + if(res) + { + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); + boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init")); + } + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); +#else + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init")); + } + int const res2=pthread_cond_init(&cond,NULL); + if(res2) + { + BOOST_VERIFY(!pthread_mutex_destroy(&m)); + boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init")); + } + is_locked=false; + count=0; +#endif + } + ~recursive_mutex() + { + BOOST_VERIFY(!pthread_mutex_destroy(&m)); +#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE + BOOST_VERIFY(!pthread_cond_destroy(&cond)); +#endif + } + +#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE + void lock() + { + BOOST_VERIFY(!pthread_mutex_lock(&m)); + } + + void unlock() + { + BOOST_VERIFY(!pthread_mutex_unlock(&m)); + } + + bool try_lock() BOOST_NOEXCEPT + { + int const res=pthread_mutex_trylock(&m); + BOOST_ASSERT(!res || res==EBUSY); + return !res; + } +#define BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE + typedef pthread_mutex_t* native_handle_type; + native_handle_type native_handle() + { + return &m; + } + +#else + void lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && pthread_equal(owner,pthread_self())) + { + ++count; + return; + } + + while(is_locked) + { + BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); + } + is_locked=true; + ++count; + owner=pthread_self(); + } + + void unlock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(!--count) + { + is_locked=false; + } + BOOST_VERIFY(!pthread_cond_signal(&cond)); + } + + bool try_lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && !pthread_equal(owner,pthread_self())) + { + return false; + } + is_locked=true; + ++count; + owner=pthread_self(); + return true; + } + +#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; + + class recursive_timed_mutex + { + private: + pthread_mutex_t m; +#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK + pthread_cond_t cond; + bool is_locked; + pthread_t owner; + unsigned count; +#endif + public: + BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex) + recursive_timed_mutex() + { +#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK + pthread_mutexattr_t attr; + + int const init_attr_res=pthread_mutexattr_init(&attr); + if(init_attr_res) + { + boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_init")); + } + int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); + if(set_attr_res) + { + boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype")); + } + + int const res=pthread_mutex_init(&m,&attr); + if(res) + { + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); + boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init")); + } + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); +#else + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init")); + } + int const res2=pthread_cond_init(&cond,NULL); + if(res2) + { + BOOST_VERIFY(!pthread_mutex_destroy(&m)); + boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init")); + } + is_locked=false; + count=0; +#endif + } + ~recursive_timed_mutex() + { + BOOST_VERIFY(!pthread_mutex_destroy(&m)); +#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK + BOOST_VERIFY(!pthread_cond_destroy(&cond)); +#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() + { + BOOST_VERIFY(!pthread_mutex_lock(&m)); + } + + void unlock() + { + BOOST_VERIFY(!pthread_mutex_unlock(&m)); + } + + bool try_lock() + { + int const res=pthread_mutex_trylock(&m); + BOOST_ASSERT(!res || res==EBUSY); + return !res; + } + private: + bool do_try_lock_until(struct timespec const &timeout) + { + int const res=pthread_mutex_timedlock(&m,&timeout); + BOOST_ASSERT(!res || res==ETIMEDOUT); + return !res; + } + + public: + +#else + void lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && pthread_equal(owner,pthread_self())) + { + ++count; + return; + } + + while(is_locked) + { + BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); + } + is_locked=true; + ++count; + owner=pthread_self(); + } + + void unlock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(!--count) + { + is_locked=false; + } + BOOST_VERIFY(!pthread_cond_signal(&cond)); + } + + bool try_lock() BOOST_NOEXCEPT + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && !pthread_equal(owner,pthread_self())) + { + return false; + } + is_locked=true; + ++count; + owner=pthread_self(); + return true; + } + + private: + bool do_try_lock_until(struct timespec const &timeout) + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && pthread_equal(owner,pthread_self())) + { + ++count; + return true; + } + while(is_locked) + { + int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout); + if(cond_res==ETIMEDOUT) + { + return false; + } + BOOST_ASSERT(!cond_res); + } + is_locked=true; + ++count; + owner=pthread_self(); + return true; + } + public: + +#endif + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(system_time const & 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) + { + 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>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil<nanoseconds>(t - c_now)); + } + template <class Duration> + bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; + return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) + { + //using namespace chrono; + chrono::nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + return do_try_lock_until(ts); + } +#endif + +#define BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE + typedef pthread_mutex_t* native_handle_type; + native_handle_type native_handle() + { + 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 + }; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex.hpp new file mode 100644 index 00000000000..458d6c83613 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex.hpp @@ -0,0 +1,716 @@ +#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 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; + 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; + } + 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()) + //while(state.exclusive || state.exclusive_waiting_blocked) + { + 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.more_shared()) + { + 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(); + } + } + + 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.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=true; + exclusive_cond.wait(lk); + } + 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; +#endif + boost::unique_lock<boost::mutex> lk(state_change); + + while(state.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=true; + if(!exclusive_cond.timed_wait(lk,timeout)) + { + if(state.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=false; + release_waiters(); + return false; + } + break; + } + } + state.exclusive=true; + 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.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=true; + if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time)) + { + if(state.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=false; + release_waiters(); + return false; + } + break; + } + } + state.exclusive=true; + return true; + } +#endif + + bool try_lock() + { + boost::unique_lock<boost::mutex> lk(state_change); + + if(state.shared_count || state.exclusive) + { + return false; + } + else + { + state.exclusive=true; + return true; + } + + } + + void unlock() + { + 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; +#endif + boost::unique_lock<boost::mutex> lk(state_change); + while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + shared_cond.wait(lk); + } + 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; +#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)) + { + if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + return false; + } + break; + } + } + state.lock_shared(); + state.upgrade=true; + 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.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + if(cv_status::timeout == shared_cond.wait_until(lk,abs_time)) + { + if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + return false; + } + break; + } + } + state.lock_shared(); + state.upgrade=true; + return true; + } +#endif + bool try_lock_upgrade() + { + boost::unique_lock<boost::mutex> lk(state_change); + if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + return false; + } + else + { + state.lock_shared(); + state.upgrade=true; + state.assert_lock_upgraded(); + return true; + } + } + + void unlock_upgrade() + { + 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(); + } + } + + // 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(); + 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::unique_lock<boost::mutex> lk(state_change); + state.assert_locked(); + state.exclusive=false; + state.upgrade=true; + state.lock_shared(); + state.exclusive_waiting_blocked=false; + 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 + && !state.exclusive_waiting_blocked + && state.upgrade + && state.shared_count==1) + { + state.shared_count=0; + state.exclusive=true; + state.upgrade=false; + 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.shared_count != 1) + { + for (;;) + { + cv_status status = shared_cond.wait_until(lk,abs_time); + if (state.shared_count == 1) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=false; + state.exclusive=true; + state.exclusive_waiting_blocked=false; + state.shared_count=0; + return true; + } +#endif + + // Shared <-> Exclusive + void unlock_and_lock_shared() + { + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_locked(); + state.exclusive=false; + state.lock_shared(); + state.exclusive_waiting_blocked=false; + 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 + && !state.exclusive_waiting_blocked + && !state.upgrade + && state.shared_count==1) + { + state.shared_count=0; + state.exclusive=true; + 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.shared_count != 1) + { + for (;;) + { + cv_status status = shared_cond.wait_until(lk,abs_time); + if (state.shared_count == 1) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=false; + state.exclusive=true; + state.exclusive_waiting_blocked=false; + state.shared_count=0; + 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.upgrade=false; + state.exclusive_waiting_blocked=false; + 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 + && !state.exclusive_waiting_blocked + && !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 + || state.exclusive_waiting_blocked + || state.upgrade + ) + { + for (;;) + { + cv_status status = exclusive_cond.wait_until(lk,abs_time); + if( ! state.exclusive + && ! state.exclusive_waiting_blocked + && ! state.upgrade + ) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=true; + return true; + } +#endif +#endif + }; + + typedef shared_mutex upgrade_mutex; +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex_assert.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex_assert.hpp new file mode 100644 index 00000000000..186ab7984bd --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/pthread/thread_data.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/thread_data.hpp new file mode 100644 index 00000000000..dc8ba0fb1ba --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/thread_data.hpp @@ -0,0 +1,292 @@ +#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP +#define BOOST_THREAD_PTHREAD_THREAD_DATA_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 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#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/assert.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#endif + +#include <map> +#include <vector> +#include <utility> + +#if defined(__ANDROID__) +# ifndef PAGE_SIZE +# define PAGE_SIZE 4096 +# endif +#endif + +#include <pthread.h> +#include <unistd.h> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + class thread_attributes { + public: + thread_attributes() BOOST_NOEXCEPT { + int res = pthread_attr_init(&val_); + BOOST_VERIFY(!res && "pthread_attr_init failed"); + } + ~thread_attributes() { + int res = pthread_attr_destroy(&val_); + BOOST_VERIFY(!res && "pthread_attr_destroy failed"); + } + // stack + void set_stack_size(std::size_t size) BOOST_NOEXCEPT { + if (size==0) return; + std::size_t page_size = getpagesize(); +#ifdef PTHREAD_STACK_MIN + if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN; +#endif + size = ((size+page_size-1)/page_size)*page_size; + int res = pthread_attr_setstacksize(&val_, size); + BOOST_VERIFY(!res && "pthread_attr_setstacksize failed"); + } + + std::size_t get_stack_size() const BOOST_NOEXCEPT { + std::size_t size; + int res = pthread_attr_getstacksize(&val_, &size); + BOOST_VERIFY(!res && "pthread_attr_getstacksize failed"); + return size; + } +#define BOOST_THREAD_DEFINES_THREAD_ATTRIBUTES_NATIVE_HANDLE + + typedef pthread_attr_t native_handle_type; + native_handle_type* native_handle() BOOST_NOEXCEPT { + return &val_; + } + const native_handle_type* native_handle() const BOOST_NOEXCEPT { + return &val_; + } + + private: + pthread_attr_t val_; + }; + + class thread; + + namespace detail + { + struct shared_state_base; + struct tss_cleanup_function; + struct thread_exit_callback_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; + typedef boost::shared_ptr<thread_data_base> thread_data_ptr; + + struct BOOST_THREAD_DECL thread_data_base: + enable_shared_from_this<thread_data_base> + { + thread_data_ptr self; + pthread_t thread_handle; + boost::mutex data_mutex; + boost::condition_variable done_condition; + boost::mutex sleep_mutex; + boost::condition_variable sleep_condition; + bool done; + bool join_started; + bool joined; + boost::detail::thread_exit_callback_node* thread_exit_callbacks; + std::map<void const*,boost::detail::tss_data_node> tss_data; + +//#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 + pthread_mutex_t* cond_mutex; + pthread_cond_t* current_cond; +//#endif + 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), +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + cond_mutex(0), + current_cond(0), +//#endif + 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; + pthread_mutex_t* m; + bool set; + + void check_for_interruption() + { +#ifndef BOOST_NO_EXCEPTIONS + if(thread_info->interrupt_requested) + { + thread_info->interrupt_requested=false; + throw thread_interrupted(); // BOOST_NO_EXCEPTIONS protected + } +#endif + } + + void operator=(interruption_checker&); + public: + explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond): + thread_info(detail::get_current_thread_data()),m(cond_mutex), + set(thread_info && thread_info->interrupt_enabled) + { + if(set) + { + lock_guard<mutex> guard(thread_info->data_mutex); + check_for_interruption(); + thread_info->cond_mutex=cond_mutex; + thread_info->current_cond=cond; + BOOST_VERIFY(!pthread_mutex_lock(m)); + } + else + { + BOOST_VERIFY(!pthread_mutex_lock(m)); + } + } + ~interruption_checker() + { + if(set) + { + BOOST_VERIFY(!pthread_mutex_unlock(m)); + lock_guard<mutex> guard(thread_info->data_mutex); + thread_info->cond_mutex=NULL; + thread_info->current_cond=NULL; + } + else + { + BOOST_VERIFY(!pthread_mutex_unlock(m)); + } + } + }; +#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 +#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::no_interruption_point::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<> +#endif + inline void sleep(system_time const& abs_time) + { + return boost::this_thread::hiden::sleep_until(boost::detail::to_timespec(abs_time)); + } + + template<typename TimeDuration> + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) + { + this_thread::sleep(get_system_time()+rel_time); + } +#endif // BOOST_THREAD_USES_DATETIME + } // this_thread +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/thread_heap_alloc.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/thread_heap_alloc.hpp new file mode 100644 index 00000000000..7828318f05f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/thread_heap_alloc.hpp @@ -0,0 +1,242 @@ +// 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 +#ifndef THREAD_HEAP_ALLOC_PTHREAD_HPP +#define THREAD_HEAP_ALLOC_PTHREAD_HPP + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + template<typename T> + inline T* heap_new() + { + return new T(); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template<typename T,typename A1> + inline T* heap_new(A1&& a1) + { + return new T(static_cast<A1&&>(a1)); + } + template<typename T,typename A1,typename A2> + inline T* heap_new(A1&& a1,A2&& a2) + { + return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2)); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1&& a1,A2&& a2,A3&& a3) + { + return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2), + static_cast<A3&&>(a3)); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4) + { + return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2), + static_cast<A3&&>(a3),static_cast<A4&&>(a4)); + } +#else + template<typename T,typename A1> + inline T* heap_new_impl(A1 a1) + { + return new T(a1); + } + template<typename T,typename A1,typename A2> + inline T* heap_new_impl(A1 a1,A2 a2) + { + return new T(a1,a2); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new_impl(A1 a1,A2 a2,A3 a3) + { + return new T(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4) + { + return new T(a1,a2,a3,a4); + } + + template<typename T,typename A1> + inline T* heap_new(A1 const& a1) + { + return heap_new_impl<T,A1 const&>(a1); + } + template<typename T,typename A1> + inline T* heap_new(A1& a1) + { + return heap_new_impl<T,A1&>(a1); + } + + template<typename T,typename A1,typename A2> + inline T* heap_new(A1 const& a1,A2 const& a2) + { + return heap_new_impl<T,A1 const&,A2 const&>(a1,a2); + } + template<typename T,typename A1,typename A2> + inline T* heap_new(A1& a1,A2 const& a2) + { + return heap_new_impl<T,A1&,A2 const&>(a1,a2); + } + template<typename T,typename A1,typename A2> + inline T* heap_new(A1 const& a1,A2& a2) + { + return heap_new_impl<T,A1 const&,A2&>(a1,a2); + } + template<typename T,typename A1,typename A2> + inline T* heap_new(A1& a1,A2& a2) + { + return heap_new_impl<T,A1&,A2&>(a1,a2); + } + + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3) + { + return heap_new_impl<T,A1 const&,A2 const&,A3 const&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3) + { + return heap_new_impl<T,A1&,A2 const&,A3 const&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3) + { + return heap_new_impl<T,A1 const&,A2&,A3 const&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2& a2,A3 const& a3) + { + return heap_new_impl<T,A1&,A2&,A3 const&>(a1,a2,a3); + } + + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3) + { + return heap_new_impl<T,A1 const&,A2 const&,A3&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2 const& a2,A3& a3) + { + return heap_new_impl<T,A1&,A2 const&,A3&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2& a2,A3& a3) + { + return heap_new_impl<T,A1 const&,A2&,A3&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2& a2,A3& a3) + { + return heap_new_impl<T,A1&,A2&,A3&>(a1,a2,a3); + } + + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3 const&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2&,A3 const&,A4&>(a1,a2,a3,a4); + } + + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4); + } + +#endif + template<typename T> + inline void heap_delete(T* data) + { + delete data; + } + + template<typename T> + struct do_heap_delete + { + void operator()(T* data) const + { + detail::heap_delete(data); + } + }; + } +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/timespec.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/timespec.hpp new file mode 100644 index 00000000000..82f50f6ca74 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/timespec.hpp @@ -0,0 +1,120 @@ +#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP +#define BOOST_THREAD_PTHREAD_TIMESPEC_HPP +// (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 + { +#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> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/recursive_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/recursive_mutex.hpp new file mode 100644 index 00000000000..e716a190ffb --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/recursive_mutex.hpp @@ -0,0 +1,64 @@ +#ifndef BOOST_THREAD_RECURSIVE_MUTEX_HPP +#define BOOST_THREAD_RECURSIVE_MUTEX_HPP + +// recursive_mutex.hpp +// +// (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/platform.hpp> +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include <boost/thread/win32/recursive_mutex.hpp> +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include <boost/thread/pthread/recursive_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<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/src/third_party/boost-1.60.0/boost/thread/reverse_lock.hpp b/src/third_party/boost-1.60.0/boost/thread/reverse_lock.hpp new file mode 100644 index 00000000000..479c314bdbe --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/reverse_lock.hpp @@ -0,0 +1,59 @@ +// 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_REVERSE_LOCK_HPP +#define BOOST_THREAD_REVERSE_LOCK_HPP +#include <boost/thread/detail/config.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 +{ + + template<typename Lock> + class reverse_lock + { + public: + typedef typename Lock::mutex_type mutex_type; + BOOST_THREAD_NO_COPYABLE(reverse_lock) + + explicit reverse_lock(Lock& m_) + : m(m_), mtx(0) + { + if (m.owns_lock()) + { + m.unlock(); + } + mtx=m.release(); + } + ~reverse_lock() + { + if (mtx) { + mtx->lock(); + m = BOOST_THREAD_MAKE_RV_REF(Lock(*mtx, adopt_lock)); + } + } + + private: + Lock& m; + mutex_type* mtx; + }; + + +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + template<typename T> + struct is_mutex_type<reverse_lock<T> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + +#endif + + +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/scoped_thread.hpp b/src/third_party/boost-1.60.0/boost/thread/scoped_thread.hpp new file mode 100644 index 00000000000..ae0d1efc53c --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/shared_lock_guard.hpp b/src/third_party/boost-1.60.0/boost/thread/shared_lock_guard.hpp new file mode 100644 index 00000000000..97a6397c1e6 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/shared_lock_guard.hpp @@ -0,0 +1,53 @@ +// 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_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/lock_options.hpp> +#include <boost/thread/detail/delete.hpp> + +namespace boost +{ + + template<typename SharedMutex> + class shared_lock_guard + { + private: + SharedMutex& m; + + public: + typedef SharedMutex mutex_type; + BOOST_THREAD_NO_COPYABLE(shared_lock_guard) + explicit shared_lock_guard(SharedMutex& m_): + m(m_) + { + m.lock_shared(); + } + shared_lock_guard(SharedMutex& m_,adopt_lock_t): + m(m_) + {} + ~shared_lock_guard() + { + m.unlock_shared(); + } + }; + +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + + template<typename T> + struct is_mutex_type<shared_lock_guard<T> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + +#endif + + +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/shared_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/shared_mutex.hpp new file mode 100644 index 00000000000..ce5d6d1bfbf --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/shared_mutex.hpp @@ -0,0 +1,50 @@ +#ifndef BOOST_THREAD_SHARED_MUTEX_HPP +#define BOOST_THREAD_SHARED_MUTEX_HPP + +// shared_mutex.hpp +// +// (C) Copyright 2007 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) + +#include <boost/thread/detail/config.hpp> +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#if defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN) +#include <boost/thread/pthread/shared_mutex.hpp> +#else +#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 +{ + typedef shared_mutex shared_timed_mutex; + 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/src/third_party/boost-1.60.0/boost/thread/strict_lock.hpp b/src/third_party/boost-1.60.0/boost/thread/strict_lock.hpp new file mode 100644 index 00000000000..93b7b1e71cd --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/sync_bounded_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/sync_bounded_queue.hpp new file mode 100644 index 00000000000..2024d6602e4 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/sync_bounded_queue.hpp @@ -0,0 +1,16 @@ +#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/concurrent_queues/sync_bounded_queue.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/sync_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/sync_queue.hpp new file mode 100644 index 00000000000..0d9334b4783 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/sync_queue.hpp @@ -0,0 +1,16 @@ +#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/concurrent_queues/sync_queue.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/synchronized_value.hpp b/src/third_party/boost-1.60.0/boost/thread/synchronized_value.hpp new file mode 100644 index 00000000000..e161063040f --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/testable_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/testable_mutex.hpp new file mode 100644 index 00000000000..3c87f9349a5 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/thread.hpp b/src/third_party/boost-1.60.0/boost/thread/thread.hpp new file mode 100644 index 00000000000..3e63b42aaa1 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/thread.hpp @@ -0,0 +1,16 @@ +#ifndef BOOST_THREAD_THREAD_HPP +#define BOOST_THREAD_THREAD_HPP + +// thread.hpp +// +// (C) Copyright 2007-8 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/thread_only.hpp> +#include <boost/thread/detail/thread_group.hpp> + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/thread_functors.hpp b/src/third_party/boost-1.60.0/boost/thread/thread_functors.hpp new file mode 100644 index 00000000000..f7bd816b178 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/thread_guard.hpp b/src/third_party/boost-1.60.0/boost/thread/thread_guard.hpp new file mode 100644 index 00000000000..85157f101e2 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/thread_only.hpp b/src/third_party/boost-1.60.0/boost/thread/thread_only.hpp new file mode 100644 index 00000000000..0d0c07061f2 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/thread_pool.hpp b/src/third_party/boost-1.60.0/boost/thread/thread_pool.hpp new file mode 100644 index 00000000000..4d2dcbea3a7 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/thread_time.hpp b/src/third_party/boost-1.60.0/boost/thread/thread_time.hpp new file mode 100644 index 00000000000..ffdcf850f73 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/thread_time.hpp @@ -0,0 +1,55 @@ +#ifndef BOOST_THREAD_TIME_HPP +#define BOOST_THREAD_TIME_HPP +// (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/date_time/time_clock.hpp> +#include <boost/date_time/microsec_time_clock.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + typedef boost::posix_time::ptime system_time; + + inline system_time get_system_time() + { +#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) + return boost::date_time::microsec_clock<system_time>::universal_time(); +#else // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) + return boost::date_time::second_clock<system_time>::universal_time(); +#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) + } + + namespace detail + { + inline system_time get_system_time_sentinel() + { + return system_time(boost::posix_time::pos_infin); + } + + inline unsigned long get_milliseconds_until(system_time const& target_time) + { + if(target_time.is_pos_infinity()) + { + return ~(unsigned long)0; + } + system_time const now=get_system_time(); + if(target_time<=now) + { + return 0; + } + return static_cast<unsigned long>((target_time-now).total_milliseconds()+1); + } + + } + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/tss.hpp b/src/third_party/boost-1.60.0/boost/thread/tss.hpp new file mode 100644 index 00000000000..d798bef558a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/tss.hpp @@ -0,0 +1,113 @@ +#ifndef BOOST_THREAD_TSS_HPP +#define BOOST_THREAD_TSS_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 2007-8 Anthony Williams + +#include <boost/thread/detail/config.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/thread/detail/thread_heap_alloc.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + struct tss_cleanup_function + { + 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); + } + + template <typename T> + class thread_specific_ptr + { + private: + thread_specific_ptr(thread_specific_ptr&); + thread_specific_ptr& operator=(thread_specific_ptr&); + + struct delete_data: + detail::tss_cleanup_function + { + void operator()(void* data) + { + 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)); + } + }; + + + 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>()) + {} + explicit thread_specific_ptr(void (*func_)(T*)) + { + if(func_) + { + cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>()); + } + } + ~thread_specific_ptr() + { + detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,true); + } + + T* get() const + { + return static_cast<T*>(detail::get_tss_data(this)); + } + T* operator->() const + { + return get(); + } + typename boost::detail::sp_dereference< T >::type operator*() const + { + return *get(); + } + T* release() + { + T* const temp=get(); + detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false); + return temp; + } + void reset(T* new_value=0) + { + T* const current_value=get(); + if(current_value!=new_value) + { + detail::set_tss_data(this,cleanup,new_value,true); + } + } + }; +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/user_scheduler.hpp b/src/third_party/boost-1.60.0/boost/thread/user_scheduler.hpp new file mode 100644 index 00000000000..c551d21710d --- /dev/null +++ b/src/third_party/boost-1.60.0/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/concurrent_queues/sync_queue.hpp> +#include <boost/thread/executors/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(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(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(boost::move(w)); + //work_queue.push(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(boost::move(w)); + //work_queue.push(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/src/third_party/boost-1.60.0/boost/thread/v2/shared_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/v2/shared_mutex.hpp new file mode 100755 index 00000000000..5acab4d8cda --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/v2/thread.hpp b/src/third_party/boost-1.60.0/boost/thread/v2/thread.hpp new file mode 100644 index 00000000000..53560610e23 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/v2/thread.hpp @@ -0,0 +1,155 @@ +// 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 2011 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_V2_THREAD_HPP +#define BOOST_THREAD_V2_THREAD_HPP + +#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/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; + 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) + { + using namespace chrono; + mutex mut; + condition_variable cv; + unique_lock<mutex> lk(mut); + while (Clock::now() < t) + cv.wait_until(lk, t); + } + +#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC && defined BOOST_CHRONO_HAS_CLOCK_STEADY + 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); + } + } + +#elif defined 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) + { + 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()) + { + //system_clock::time_point c_timeout = time_point_cast<system_clock::duration>(system_clock::now() + ceil<nanoseconds>(d)); + system_clock::time_point c_timeout = system_clock::now() + ceil<system_clock::duration>(d); + sleep_until(c_timeout); + } + } + +#endif + +#endif + } +} + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/basic_recursive_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/basic_recursive_mutex.hpp new file mode 100644 index 00000000000..cfdfa043a3b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/basic_recursive_mutex.hpp @@ -0,0 +1,164 @@ +#ifndef BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP +#define BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP + +// basic_recursive_mutex.hpp +// +// (C) Copyright 2006-8 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) + +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/thread/win32/basic_timed_mutex.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + template<typename underlying_mutex_type> + struct basic_recursive_mutex_impl + { + long recursion_count; + long locking_thread_id; + underlying_mutex_type mutex; + + void initialize() + { + recursion_count=0; + locking_thread_id=0; + mutex.initialize(); + } + + void destroy() + { + mutex.destroy(); + } + + 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); + } + + void lock() + { + long const current_thread_id=win32::GetCurrentThreadId(); + if(!try_recursive_lock(current_thread_id)) + { + mutex.lock(); + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + } + } +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(::boost::system_time const& target) + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target); + } + template<typename Duration> + bool timed_lock(Duration const& timeout) + { + return timed_lock(get_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) + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time); + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& t) + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t); + } +#endif + void unlock() + { + if(!--recursion_count) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,0); + mutex.unlock(); + } + } + + private: + bool try_recursive_lock(long current_thread_id) BOOST_NOEXCEPT + { + if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id) + { + ++recursion_count; + return true; + } + return false; + } + + bool try_basic_lock(long current_thread_id) BOOST_NOEXCEPT + { + if(mutex.try_lock()) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + 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)) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } +#endif + template <typename TP> + bool try_timed_lock_until(long current_thread_id,TP const& target) + { + if(mutex.try_lock_until(target)) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } + template <typename D> + bool try_timed_lock_for(long current_thread_id,D const& target) + { + if(mutex.try_lock_for(target)) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } + }; + + typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_mutex; + typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_timed_mutex; + } +} + +#define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/basic_timed_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/basic_timed_mutex.hpp new file mode 100644 index 00000000000..d20c6589e69 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/basic_timed_mutex.hpp @@ -0,0 +1,279 @@ +#ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP +#define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP + +// basic_timed_mutex_win32.hpp +// +// (C) Copyright 2006-8 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) + +#include <boost/assert.hpp> +#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> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + struct basic_timed_mutex + { + BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31); + BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30); + BOOST_STATIC_CONSTANT(long,lock_flag_value=1<<lock_flag_bit); + BOOST_STATIC_CONSTANT(long,event_set_flag_value=1<<event_set_flag_bit); + long active_count; + void* event; + + void initialize() + { + active_count=0; + event=0; + } + + void destroy() + { +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4312) +#endif + void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + if(old_event) + { + win32::CloseHandle(old_event); + } + } + + + bool try_lock() BOOST_NOEXCEPT + { + return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit); + } + + void lock() + { + if(try_lock()) + { + return; + } + long old_count=active_count; + mark_waiting_and_try_lock(old_count); + + if(old_count&lock_flag_value) + { + bool lock_acquired=false; + void* const sem=get_event(); + + do + { + 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); + } + while(!lock_acquired); + } + } + void mark_waiting_and_try_lock(long& old_count) + { + for(;;) + { + 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; + } + } + + void clear_waiting_and_try_lock(long& old_count) + { + old_count&=~lock_flag_value; + old_count|=event_set_flag_value; + for(;;) + { + long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value; + long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count); + if(current==old_count) + { + break; + } + old_count=current; + } + } + + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(::boost::system_time const& wait_until) + { + if(try_lock()) + { + return true; + } + long old_count=active_count; + mark_waiting_and_try_lock(old_count); + + if(old_count&lock_flag_value) + { + bool lock_acquired=false; + void* const sem=get_event(); + + do + { + if(win32::WaitForSingleObjectEx(sem,::boost::detail::get_milliseconds_until(wait_until),0)!=0) + { + BOOST_INTERLOCKED_DECREMENT(&active_count); + return false; + } + clear_waiting_and_try_lock(old_count); + lock_acquired=!(old_count&lock_flag_value); + } + while(!lock_acquired); + } + return true; + } + + template<typename Duration> + bool timed_lock(Duration const& timeout) + { + return timed_lock(get_system_time()+timeout); + } + + bool timed_lock(boost::xtime const& timeout) + { + 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) + { + 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>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now)); + } + template <class Duration> + bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; + return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) + { + if(try_lock()) + { + return true; + } + long old_count=active_count; + mark_waiting_and_try_lock(old_count); + + if(old_count&lock_flag_value) + { + bool lock_acquired=false; + void* const sem=get_event(); + + do + { + 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::WaitForSingleObjectEx(sem,static_cast<unsigned long>(rel_time.count()),0)!=0) + { + BOOST_INTERLOCKED_DECREMENT(&active_count); + return false; + } + clear_waiting_and_try_lock(old_count); + lock_acquired=!(old_count&lock_flag_value); + } + while(!lock_acquired); + } + return true; + } +#endif + + void unlock() + { + long const offset=lock_flag_value; + long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value); + if(!(old_count&event_set_flag_value) && (old_count>offset)) + { + if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit)) + { + win32::SetEvent(get_event()); + } + } + } + + private: + void* get_event() + { + void* current_event=::boost::detail::interlocked_read_acquire(&event); + + if(!current_event) + { + void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset); +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4311) +#pragma warning(disable:4312) +#endif + void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + if(old_event!=0) + { + win32::CloseHandle(new_event); + return old_event; + } + else + { + return new_event; + } + } + return current_event; + } + + }; + + } +} + +#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/condition_variable.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/condition_variable.hpp new file mode 100644 index 00000000000..23e9e444840 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/condition_variable.hpp @@ -0,0 +1,567 @@ +#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP +#define BOOST_THREAD_CONDITION_VARIABLE_WIN32_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 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/thread/win32/thread_data.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> +#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 +{ + namespace detail + { + class basic_cv_list_entry; + void intrusive_ptr_add_ref(basic_cv_list_entry * p); + void intrusive_ptr_release(basic_cv_list_entry * p); + + class basic_cv_list_entry + { + private: + detail::win32::handle_manager semaphore; + detail::win32::handle_manager wake_sem; + long waiters; + bool notified; + long references; + + public: + BOOST_THREAD_NO_COPYABLE(basic_cv_list_entry) + explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_): + semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)), + wake_sem(wake_sem_.duplicate()), + waiters(1),notified(false),references(0) + {} + + static bool no_waiters(boost::intrusive_ptr<basic_cv_list_entry> const& entry) + { + return !detail::interlocked_read_acquire(&entry->waiters); + } + + void add_waiter() + { + BOOST_INTERLOCKED_INCREMENT(&waiters); + } + + void remove_waiter() + { + BOOST_INTERLOCKED_DECREMENT(&waiters); + } + + void release(unsigned count_to_release) + { + notified=true; + detail::win32::ReleaseSemaphore(semaphore,count_to_release,0); + } + + void release_waiters() + { + release(detail::interlocked_read_acquire(&waiters)); + } + + bool is_notified() const + { + return notified; + } + + bool wait(timeout abs_time) + { + return this_thread::interruptible_wait(semaphore,abs_time); + } + + bool woken() + { + 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; + } + + friend void intrusive_ptr_add_ref(basic_cv_list_entry * p); + friend void intrusive_ptr_release(basic_cv_list_entry * p); + }; + + inline void intrusive_ptr_add_ref(basic_cv_list_entry * p) + { + BOOST_INTERLOCKED_INCREMENT(&p->references); + } + + inline void intrusive_ptr_release(basic_cv_list_entry * p) + { + if(!BOOST_INTERLOCKED_DECREMENT(&p->references)) + { + delete p; + } + } + + class basic_condition_variable + { + boost::mutex internal_mutex; + long total_count; + unsigned active_generation_count; + + typedef basic_cv_list_entry list_entry; + + typedef boost::intrusive_ptr<list_entry> entry_ptr; + typedef std::vector<entry_ptr> generation_list; + + generation_list generations; + detail::win32::handle_manager wake_sem; + + void wake_waiters(long count_to_wake) + { + detail::interlocked_write_release(&total_count,total_count-count_to_wake); + detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0); + } + + template<typename lock_type> + struct relocker + { + BOOST_THREAD_NO_COPYABLE(relocker) + lock_type& lock; + bool unlocked; + + relocker(lock_type& lock_): + lock(lock_),unlocked(false) + {} + void unlock() + { + lock.unlock(); + unlocked=true; + } + ~relocker() + { + if(unlocked) + { + lock.lock(); + } + + } + }; + + + entry_ptr get_wait_entry() + { + boost::lock_guard<boost::mutex> internal_lock(internal_mutex); + + if(!wake_sem) + { + wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + BOOST_ASSERT(wake_sem); + } + + detail::interlocked_write_release(&total_count,total_count+1); + if(generations.empty() || generations.back()->is_notified()) + { + entry_ptr new_entry(new list_entry(wake_sem)); + generations.push_back(new_entry); + return new_entry; + } + else + { + generations.back()->add_waiter(); + return generations.back(); + } + } + + struct entry_manager + { + entry_ptr const entry; + boost::mutex& internal_mutex; + + BOOST_THREAD_NO_COPYABLE(entry_manager) + 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(); + } + + list_entry* operator->() + { + return entry.get(); + } + }; + + + protected: + template<typename lock_type> + bool do_wait(lock_type& lock,timeout abs_time) + { + relocker<lock_type> locker(lock); + + entry_manager entry(get_wait_entry(), internal_mutex); + + locker.unlock(); + + bool woken=false; + while(!woken) + { + if(!entry->wait(abs_time)) + { + return false; + } + + woken=entry->woken(); + } + return woken; + } + + template<typename lock_type,typename predicate_type> + bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred) + { + while (!pred()) + { + if(!do_wait(m, abs_time)) + return pred(); + } + return true; + } + + basic_condition_variable(const basic_condition_variable& other); + basic_condition_variable& operator=(const basic_condition_variable& other); + + public: + basic_condition_variable(): + total_count(0),active_generation_count(0),wake_sem(0) + {} + + ~basic_condition_variable() + {} + + void notify_one() BOOST_NOEXCEPT + { + if(detail::interlocked_read_acquire(&total_count)) + { + boost::lock_guard<boost::mutex> internal_lock(internal_mutex); + if(!total_count) + { + return; + } + wake_waiters(1); + + for(generation_list::iterator it=generations.begin(), + end=generations.end(); + it!=end;++it) + { + (*it)->release(1); + } + generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end()); + } + } + + void notify_all() BOOST_NOEXCEPT + { + if(detail::interlocked_read_acquire(&total_count)) + { + boost::lock_guard<boost::mutex> internal_lock(internal_mutex); + if(!total_count) + { + return; + } + wake_waiters(total_count); + for(generation_list::iterator it=generations.begin(), + end=generations.end(); + it!=end;++it) + { + (*it)->release_waiters(); + } + generations.clear(); + wake_sem=detail::win32::handle(0); + } + } + + }; + } + + class condition_variable: + private detail::basic_condition_variable + { + public: + BOOST_THREAD_NO_COPYABLE(condition_variable) + condition_variable() + {} + + using detail::basic_condition_variable::notify_one; + using detail::basic_condition_variable::notify_all; + + void wait(unique_lock<mutex>& m) + { + do_wait(m,detail::timeout::sentinel()); + } + + template<typename predicate_type> + void wait(unique_lock<mutex>& m,predicate_type pred) + { + while(!pred()) wait(m); + } + + +#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); + } + + bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time) + { + return do_wait(m,system_time(abs_time)); + } + template<typename duration_type> + bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration) + { + 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> + bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred) + { + return do_wait(m,abs_time,pred); + } + template<typename predicate_type> + bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred) + { + return do_wait(m,system_time(abs_time),pred); + } + template<typename duration_type,typename predicate_type> + bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred) + { + if (wait_duration.is_pos_infinity()) + { + while (!pred()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + } + return true; + } + if (wait_duration.is_special()) + { + return pred(); + } + return do_wait(m,wait_duration.total_milliseconds(),pred); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Clock, class Duration> + cv_status + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + 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; + } + + template <class Rep, class Period> + cv_status + wait_for( + unique_lock<mutex>& lock, + 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 : + cv_status::timeout; + } + + template <class Clock, class Duration, class Predicate> + bool + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + template <class Rep, class Period, class Predicate> + bool + wait_for( + unique_lock<mutex>& lock, + const chrono::duration<Rep, Period>& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + } +#endif + }; + + class condition_variable_any: + private detail::basic_condition_variable + { + public: + BOOST_THREAD_NO_COPYABLE(condition_variable_any) + condition_variable_any() + {} + + using detail::basic_condition_variable::notify_one; + using detail::basic_condition_variable::notify_all; + + template<typename lock_type> + void wait(lock_type& m) + { + do_wait(m,detail::timeout::sentinel()); + } + + template<typename lock_type,typename predicate_type> + void wait(lock_type& m,predicate_type pred) + { + 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) + { + return do_wait(m,abs_time); + } + + template<typename lock_type> + bool timed_wait(lock_type& m,boost::xtime const& abs_time) + { + return do_wait(m,system_time(abs_time)); + } + + template<typename lock_type,typename duration_type> + bool timed_wait(lock_type& m,duration_type const& wait_duration) + { + return do_wait(m,wait_duration.total_milliseconds()); + } + + template<typename lock_type,typename predicate_type> + bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred) + { + return do_wait(m,abs_time,pred); + } + + template<typename lock_type,typename predicate_type> + bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred) + { + return do_wait(m,system_time(abs_time),pred); + } + + template<typename lock_type,typename duration_type,typename predicate_type> + bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred) + { + return do_wait(m,wait_duration.total_milliseconds(),pred); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + + template <class lock_type, class Clock, class Duration> + cv_status + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + 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; + } + + template <class lock_type, class Rep, class Period> + cv_status + wait_for( + lock_type& lock, + 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 : + cv_status::timeout; + } + + template <class lock_type, class Clock, class Duration, class Predicate> + bool + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + template <class lock_type, class Rep, class Period, class Predicate> + bool + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d, + Predicate 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> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/interlocked_read.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/interlocked_read.hpp new file mode 100644 index 00000000000..2ad3fe9017a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/interlocked_read.hpp @@ -0,0 +1,77 @@ +#ifndef BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP +#define BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP + +// interlocked_read_win32.hpp +// +// (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 + +namespace boost +{ + namespace detail + { + // Since VS2005 volatile reads always acquire + inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT + { + long const res=*x; + return res; + } + inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT + { + void* const res=*x; + return res; + } + + // Since VS2005 volatile writes always release + inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT + { + *x=value; + } + inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT + { + *x=value; + } + } +} + +#else + +namespace boost +{ + namespace detail + { + 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) BOOST_NOEXCEPT + { + return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0); + } + 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) BOOST_NOEXCEPT + { + BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value); + } + } +} + +#endif + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/mfc_thread_init.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/mfc_thread_init.hpp new file mode 100644 index 00000000000..e866f8949f5 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/win32/mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/mutex.hpp new file mode 100644 index 00000000000..01544784b5b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/mutex.hpp @@ -0,0 +1,72 @@ +#ifndef BOOST_THREAD_WIN32_MUTEX_HPP +#define BOOST_THREAD_WIN32_MUTEX_HPP +// (C) Copyright 2005-7 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) + +#include <boost/thread/win32/basic_timed_mutex.hpp> +#include <boost/thread/exceptions.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> + +namespace boost +{ + namespace detail + { + typedef ::boost::detail::basic_timed_mutex underlying_mutex; + } + + class mutex: + public ::boost::detail::underlying_mutex + { + public: + BOOST_THREAD_NO_COPYABLE(mutex) + mutex() + { + initialize(); + } + ~mutex() + { + 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; + + class timed_mutex: + public ::boost::detail::basic_timed_mutex + { + public: + BOOST_THREAD_NO_COPYABLE(timed_mutex) + timed_mutex() + { + initialize(); + } + + ~timed_mutex() + { + 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 + }; +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/once.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/once.hpp new file mode 100644 index 00000000000..24eb0f29d06 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/once.hpp @@ -0,0 +1,1087 @@ +#ifndef BOOST_THREAD_WIN32_ONCE_HPP +#define BOOST_THREAD_WIN32_ONCE_HPP + +// once.hpp +// +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2005 John Maddock +// (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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include <cstring> +#include <cstddef> +#include <boost/assert.hpp> +#include <boost/static_assert.hpp> +#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> + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std +{ + using ::memcpy; + using ::ptrdiff_t; +} +#endif + +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 + { + BOOST_THREAD_NO_COPYABLE(once_flag) + BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT + : status(0), count(0) + {} + long status; + long count; + 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() +#else // BOOST_THREAD_PROVIDES_ONCE_CXX11 + + struct once_flag + { + long status; + long count; + }; + +#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 + typedef wchar_t once_char_type; +#else + typedef char once_char_type; +#endif + unsigned const once_mutex_name_fixed_length=54; + unsigned const once_mutex_name_length=once_mutex_name_fixed_length+ + sizeof(void*)*2+sizeof(unsigned long)*2+1; + + template <class I> + void int_to_string(I p, once_char_type* buf) + { + for(unsigned i=0; i < sizeof(I)*2; ++i,++buf) + { +#ifdef BOOST_NO_ANSI_APIS + once_char_type const a=L'A'; +#else + once_char_type const a='A'; +#endif + *buf = a + static_cast<once_char_type>((p >> (i*4)) & 0x0f); + } + *buf = 0; + } + + inline void name_once_mutex(once_char_type* mutex_name,void* flag_address) + { +#ifdef BOOST_NO_ANSI_APIS + static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; +#else + static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; +#endif + BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) == + (sizeof(once_char_type)*(once_mutex_name_fixed_length+1))); + + std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name)); + detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), + mutex_name + once_mutex_name_fixed_length); + detail::int_to_string(win32::GetCurrentProcessId(), + mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2); + } + + inline void* open_once_event(once_char_type* mutex_name,void* flag_address) + { + if(!*mutex_name) + { + name_once_mutex(mutex_name,flag_address); + } + +#ifdef BOOST_NO_ANSI_APIS + return ::boost::detail::win32::OpenEventW( +#else + return ::boost::detail::win32::OpenEventA( +#endif + ::boost::detail::win32::synchronize | + ::boost::detail::win32::event_modify_state, + false, + mutex_name); + } + + inline void* create_once_event(once_char_type* mutex_name,void* flag_address) + { + if(!*mutex_name) + { + name_once_mutex(mutex_name,flag_address); + } + + 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: + 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 + + 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) + { + 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 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)) + { + 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 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 + { + f( + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T2>(p2)) + ); + } + 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,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; + + } + 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 +#endif +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/recursive_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/recursive_mutex.hpp new file mode 100644 index 00000000000..1f0f7f5e5fd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/recursive_mutex.hpp @@ -0,0 +1,70 @@ +#ifndef BOOST_RECURSIVE_MUTEX_WIN32_HPP +#define BOOST_RECURSIVE_MUTEX_WIN32_HPP + +// recursive_mutex.hpp +// +// (C) Copyright 2006-7 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/win32/basic_recursive_mutex.hpp> +#include <boost/thread/exceptions.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> + +namespace boost +{ + class recursive_mutex: + public ::boost::detail::basic_recursive_mutex + { + public: + BOOST_THREAD_NO_COPYABLE(recursive_mutex) + recursive_mutex() + { + ::boost::detail::basic_recursive_mutex::initialize(); + } + ~recursive_mutex() + { + ::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; + + class recursive_timed_mutex: + public ::boost::detail::basic_recursive_timed_mutex + { + public: + BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex) + recursive_timed_mutex() + { + ::boost::detail::basic_recursive_timed_mutex::initialize(); + } + ~recursive_timed_mutex() + { + ::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 + }; +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/shared_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/shared_mutex.hpp new file mode 100644 index 00000000000..b7822d1142f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/shared_mutex.hpp @@ -0,0 +1,903 @@ +#ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP +#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP + +// (C) Copyright 2006-8 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) + +#include <boost/assert.hpp> +#include <boost/detail/interlocked.hpp> +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/static_assert.hpp> +#include <limits.h> +#include <boost/thread/thread_time.hpp> +#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/config/abi_prefix.hpp> + +namespace boost +{ + class shared_mutex + { + private: + struct state_data + { + unsigned shared_count:11, + shared_waiting:11, + exclusive:1, + upgrade:1, + exclusive_waiting:7, + exclusive_waiting_blocked:1; + + friend bool operator==(state_data const& lhs,state_data const& rhs) + { + return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs); + } + }; + + + template<typename T> + T interlocked_compare_exchange(T* target,T new_value,T comparand) + { + BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long)); + long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target), + *reinterpret_cast<long*>(&new_value), + *reinterpret_cast<long*>(&comparand)); + return *reinterpret_cast<T const*>(&res); + } + + enum + { + unlock_sem = 0, + exclusive_sem = 1 + }; + + state_data state; + detail::win32::handle semaphores[2]; + detail::win32::handle upgrade_sem; + + void release_waiters(state_data old_state) + { + if(old_state.exclusive_waiting) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0); + } + + 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); + } + } + 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) + shared_mutex() + { + semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!semaphores[exclusive_sem]) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } + upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!upgrade_sem) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } + state_data state_={0,0,0,0,0,0}; + state=state_; + } + + ~shared_mutex() + { + detail::win32::CloseHandle(upgrade_sem); + detail::win32::CloseHandle(semaphores[unlock_sem]); + detail::win32::CloseHandle(semaphores[exclusive_sem]); + } + + bool try_lock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(!new_state.exclusive && !new_state.exclusive_waiting_blocked) + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + return !(old_state.exclusive| old_state.exclusive_waiting_blocked); + } + + 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(;;) + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + + unsigned long const res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0); + if(res==detail::win32::timeout) + { + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + if(new_state.shared_waiting) + { + --new_state.shared_waiting; + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + return false; + } + + BOOST_ASSERT(res==0); + } + } +#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>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now)); + } + template <class Duration> + bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; + return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); + } + bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) + { + for(;;) + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + + chrono::system_clock::time_point n = chrono::system_clock::now(); + unsigned long res; + if (tp>n) { + chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n); + res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem], + static_cast<unsigned long>(rel_time.count()), 0); + } else { + res=detail::win32::timeout; + } + if(res==detail::win32::timeout) + { + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + if(new_state.shared_waiting) + { + --new_state.shared_waiting; + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + return false; + } + + BOOST_ASSERT(res==0); + } + } +#endif + + void unlock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + bool const last_reader=!--new_state.shared_count; + + if(last_reader) + { + if(new_state.upgrade) + { + new_state.upgrade=false; + new_state.exclusive=true; + } + else + { + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + if(last_reader) + { + if(old_state.upgrade) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0); + } + else + { + release_waiters(old_state); + } + } + break; + } + old_state=current_state; + } + } + + 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() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + return false; + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + return true; + } + + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(boost::system_time const& wait_until) + { + for(;;) + { + state_data old_state=state; + + for(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + ++new_state.exclusive_waiting; + if(!new_state.exclusive_waiting) + { + boost::throw_exception(boost::lock_error()); + } + + new_state.exclusive_waiting_blocked=true; + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + #ifndef UNDER_CE + const bool wait_all = true; + #else + const bool wait_all = false; + #endif + 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) + { + if(new_state.exclusive_waiting) + { + if(!--new_state.exclusive_waiting) + { + new_state.exclusive_waiting_blocked=false; + must_notify = true; + } + } + } + else + { + new_state.exclusive=true; + } + + 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; + } + old_state=current_state; + } + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + return false; + } + 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) + { + 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>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now)); + } + template <class Duration> + bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; + return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) + { + for(;;) + { + state_data old_state=state; + + for(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + ++new_state.exclusive_waiting; + if(!new_state.exclusive_waiting) + { + boost::throw_exception(boost::lock_error()); + } + + new_state.exclusive_waiting_blocked=true; + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + #ifndef UNDER_CE + const bool wait_all = true; + #else + const bool wait_all = false; + #endif + + chrono::system_clock::time_point n = chrono::system_clock::now(); + unsigned long wait_res; + if (tp>n) { + chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now()); + wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all, + static_cast<unsigned long>(rel_time.count()), 0); + } else { + wait_res=detail::win32::timeout; + } + 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) + { + if(new_state.exclusive_waiting) + { + if(!--new_state.exclusive_waiting) + { + new_state.exclusive_waiting_blocked=false; + must_notify = true; + } + } + } + else + { + new_state.exclusive=true; + } + + 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; + } + old_state=current_state; + } + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + return false; + } + BOOST_ASSERT(wait_res<2); + } + } +#endif + + void unlock() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.exclusive=false; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } + + void lock_upgrade() + { + for(;;) + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade) + { + ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } + new_state.upgrade=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade)) + { + return; + } + + BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],detail::win32::infinite, 0)); + } + } + + bool try_lock_upgrade() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade) + { + return false; + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + new_state.upgrade=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + return true; + } + + void unlock_upgrade() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.upgrade=false; + bool const last_reader=!--new_state.shared_count; + + new_state.shared_waiting=0; + if(last_reader) + { + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + if(last_reader) + { + release_waiters(old_state); + } + else { + release_shared_waiters(old_state); + } + // #7720 + //else { + // release_waiters(old_state); + //} + break; + } + old_state=current_state; + } + } + + void unlock_upgrade_and_lock() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + bool const last_reader=!--new_state.shared_count; + + if(last_reader) + { + new_state.upgrade=false; + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + if(!last_reader) + { + BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0)); + } + break; + } + old_state=current_state; + } + } + + void unlock_and_lock_upgrade() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.exclusive=false; + new_state.upgrade=true; + ++new_state.shared_count; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } +// bool try_unlock_upgrade_and_lock() +// { +// 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) +// { +// return false; +// } +//#endif + + void unlock_and_lock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.exclusive=false; + ++new_state.shared_count; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } + void unlock_upgrade_and_lock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.upgrade=false; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } + + }; + typedef shared_mutex upgrade_mutex; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/thread_data.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/thread_data.hpp new file mode 100644 index 00000000000..005f3ba5035 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/thread_data.hpp @@ -0,0 +1,328 @@ +#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP +#define BOOST_THREAD_PTHREAD_THREAD_DATA_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 + +#include <boost/thread/detail/config.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 { + val_.stack_size = 0; + //val_.lpThreadAttributes=0; + } + ~thread_attributes() { + } + // stack size + void set_stack_size(std::size_t size) BOOST_NOEXCEPT { + val_.stack_size = size; + } + + std::size_t get_stack_size() const BOOST_NOEXCEPT { + return val_.stack_size; + } + + //void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes) + //{ + // val_.lpThreadAttributes=lpThreadAttributes; + //} + //LPSECURITY_ATTRIBUTES get_security() + //{ + // return val_.lpThreadAttributes; + //} + + struct win_attrs { + std::size_t stack_size; + //LPSECURITY_ATTRIBUTES lpThreadAttributes; + }; + typedef win_attrs native_handle_type; + native_handle_type* native_handle() {return &val_;} + const native_handle_type* native_handle() const {return &val_;} + + private: + win_attrs val_; + }; + + namespace detail + { + struct shared_state_base; + struct tss_cleanup_function; + struct thread_exit_callback_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_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; +#endif + + boost::detail::thread_exit_callback_node* thread_exit_callbacks; + 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(), + 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) + { + BOOST_INTERLOCKED_INCREMENT(&p->count); + } + + friend void intrusive_ptr_release(thread_data_base * p) + { + if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) + { + detail::heap_delete(p); + } + } + +#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 + { + win32::ticks_type start; + uintmax_t milliseconds; + bool relative; + boost::system_time abs_time; + + static unsigned long const max_non_infinite_wait=0xfffffffe; + + timeout(uintmax_t milliseconds_): + start(win32::GetTickCount64_()()), + milliseconds(milliseconds_), + relative(true) + //, + // abs_time(boost::get_system_time()) + {} + + timeout(boost::system_time const& abs_time_): + start(win32::GetTickCount64_()()), + milliseconds(0), + relative(false), + abs_time(abs_time_) + {} + + struct BOOST_SYMBOL_VISIBLE remaining_time + { + bool more; + unsigned long milliseconds; + + remaining_time(uintmax_t remaining): + more(remaining>max_non_infinite_wait), + milliseconds(more?max_non_infinite_wait:(unsigned long)remaining) + {} + }; + + remaining_time remaining_milliseconds() const + { + if(is_sentinel()) + { + return remaining_time(win32::infinite); + } + else if(relative) + { + win32::ticks_type const now=win32::GetTickCount64_()(); + win32::ticks_type const elapsed=now-start; + return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0); + } + else + { + system_time const now=get_system_time(); + if(abs_time<=now) + { + return remaining_time(0); + } + return remaining_time((abs_time-now).total_milliseconds()+1); + } + } + + bool is_sentinel() const + { + return milliseconds==~uintmax_t(0); + } + + + static timeout sentinel() + { + return timeout(sentinel_type()); + } + private: + struct sentinel_type + {}; + + explicit timeout(sentinel_type): + start(0),milliseconds(~uintmax_t(0)),relative(true) + {} + }; + + inline uintmax_t pin_to_zero(intmax_t value) + { + return (value<0)?0u:(uintmax_t)value; + } + } + + namespace this_thread + { + void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; + + bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); + inline void interruptible_wait(uintmax_t milliseconds) + { + interruptible_wait(detail::win32::invalid_handle_value,milliseconds); + } + inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time) + { + interruptible_wait(detail::win32::invalid_handle_value,abs_time); + } + template<typename TimeDuration> + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) + { + interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); + } + inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) + { + interruptible_wait(abs_time); + } +// #11322 sleep_for() nanoseconds overload will always return too early on windows +//#ifdef BOOST_THREAD_USES_CHRONO +// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) +// { +// 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); + } +// #11322 sleep_for() nanoseconds overload will always return too early on windows +//#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/src/third_party/boost-1.60.0/boost/thread/win32/thread_heap_alloc.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/thread_heap_alloc.hpp new file mode 100644 index 00000000000..610fe3263e1 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/thread_heap_alloc.hpp @@ -0,0 +1,409 @@ +// 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 +#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> + +namespace boost +{ + namespace detail + { + namespace win32 + { + using ::GetProcessHeap; + using ::HeapAlloc; + using ::HeapFree; + } + } +} + +#else + +# ifdef HeapAlloc +# undef HeapAlloc +# endif + +namespace boost +{ + namespace detail + { + namespace win32 + { + extern "C" + { + __declspec(dllimport) handle __stdcall GetProcessHeap(); + __declspec(dllimport) void* __stdcall HeapAlloc(handle,unsigned long,ulong_ptr); + __declspec(dllimport) int __stdcall HeapFree(handle,unsigned long,void*); + } + } + } +} + +#endif + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + inline void* allocate_raw_heap_memory(unsigned size) + { + void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size); + if(!heap_memory) + { + boost::throw_exception(std::bad_alloc()); + } + return heap_memory; + } + + inline void free_raw_heap_memory(void* heap_memory) + { + BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0); + } + + template<typename T> + inline T* heap_new() + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + +#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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(static_cast<A1&&>(a1)); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2)); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2), + static_cast<A3&&>(a3)); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + 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; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1,a2); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1,a2,a3); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1,a2,a3,a4); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + + template<typename T,typename A1> + inline T* heap_new(A1 const& a1) + { + return heap_new_impl<T,A1 const&>(a1); + } + template<typename T,typename A1> + inline T* heap_new(A1& a1) + { + return heap_new_impl<T,A1&>(a1); + } + + template<typename T,typename A1,typename A2> + inline T* heap_new(A1 const& a1,A2 const& a2) + { + return heap_new_impl<T,A1 const&,A2 const&>(a1,a2); + } + template<typename T,typename A1,typename A2> + inline T* heap_new(A1& a1,A2 const& a2) + { + return heap_new_impl<T,A1&,A2 const&>(a1,a2); + } + template<typename T,typename A1,typename A2> + inline T* heap_new(A1 const& a1,A2& a2) + { + return heap_new_impl<T,A1 const&,A2&>(a1,a2); + } + template<typename T,typename A1,typename A2> + inline T* heap_new(A1& a1,A2& a2) + { + return heap_new_impl<T,A1&,A2&>(a1,a2); + } + + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3) + { + return heap_new_impl<T,A1 const&,A2 const&,A3 const&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3) + { + return heap_new_impl<T,A1&,A2 const&,A3 const&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3) + { + return heap_new_impl<T,A1 const&,A2&,A3 const&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2& a2,A3 const& a3) + { + return heap_new_impl<T,A1&,A2&,A3 const&>(a1,a2,a3); + } + + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3) + { + return heap_new_impl<T,A1 const&,A2 const&,A3&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2 const& a2,A3& a3) + { + return heap_new_impl<T,A1&,A2 const&,A3&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2& a2,A3& a3) + { + return heap_new_impl<T,A1 const&,A2&,A3&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2& a2,A3& a3) + { + return heap_new_impl<T,A1&,A2&,A3&>(a1,a2,a3); + } + + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3 const&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2&,A3 const&,A4&>(a1,a2,a3,a4); + } + + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4); + } + +#endif + template<typename T> + inline void heap_delete(T* data) + { + data->~T(); + free_raw_heap_memory(data); + } + + template<typename T> + struct do_heap_delete + { + void operator()(T* data) const + { + detail::heap_delete(data); + } + }; + } +} + +#include <boost/config/abi_suffix.hpp> + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/thread_primitives.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/thread_primitives.hpp new file mode 100644 index 00000000000..b63503ad52b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/thread_primitives.hpp @@ -0,0 +1,669 @@ +#ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP +#define BOOST_WIN32_THREAD_PRIMITIVES_HPP + +// win32_thread_primitives.hpp +// +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2007 David Deakins +// +// 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/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> + +namespace boost +{ + namespace detail + { + namespace win32 + { + typedef HANDLE handle; + typedef SYSTEM_INFO system_info; + typedef unsigned __int64 ticks_type; + typedef FARPROC farproc_t; + 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 ::CreateSemaphoreW; +# else + using ::CreateMutexExW; + using ::CreateEventExW; + using ::CreateSemaphoreExW; +# endif + using ::OpenEventW; + using ::GetModuleHandleW; +# else + using ::CreateMutexA; + using ::CreateEventA; + using ::OpenEventA; + using ::CreateSemaphoreA; + using ::GetModuleHandleA; +# endif +#if BOOST_PLAT_WINDOWS_RUNTIME + using ::GetNativeSystemInfo; + using ::GetTickCount64; +#else + using ::GetSystemInfo; + using ::GetTickCount; +#endif + using ::CloseHandle; + using ::ReleaseMutex; + using ::ReleaseSemaphore; + using ::SetEvent; + using ::ResetEvent; + 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 ::GetProcAddress; +#endif + } + } +} +#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) + +# ifdef UNDER_CE +# ifndef WINAPI +# ifndef _WIN32_WCE_EMULATION +# define WINAPI __cdecl // Note this doesn't match the desktop definition +# else +# define WINAPI __stdcall +# endif +# endif + +# ifdef __cplusplus +extern "C" { +# endif +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; + typedef int (__stdcall *farproc_t)(); + 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*); + __declspec(dllimport) void* __stdcall GetModuleHandleW(wchar_t const*); +# else + __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*); + __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*); + __declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*); + __declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*); + __declspec(dllimport) void* __stdcall GetModuleHandleA(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*); + __declspec(dllimport) unsigned long __stdcall GetTickCount(); +#endif + __declspec(dllimport) int __stdcall CloseHandle(void*); + __declspec(dllimport) int __stdcall ReleaseMutex(void*); + __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) farproc_t __stdcall GetProcAddress(void *, const char *); +#endif + +# ifndef UNDER_CE + __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId(); + __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(); + __declspec(dllimport) void* __stdcall GetCurrentThread(); + __declspec(dllimport) void* __stdcall GetCurrentProcess(); + __declspec(dllimport) int __stdcall SetEvent(void*); + __declspec(dllimport) int __stdcall ResetEvent(void*); +# else + using ::GetCurrentProcessId; + using ::GetCurrentThreadId; + using ::GetCurrentThread; + using ::GetCurrentProcess; + using ::SetEvent; + using ::ResetEvent; +# endif + } + } + } +} +#else +# error "Win32 functions not available" +#endif + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + namespace win32 + { + namespace detail { typedef ticks_type (__stdcall *gettickcount64_t)(); } +#if !BOOST_PLAT_WINDOWS_RUNTIME + extern "C" + { +#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 + 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, + manual_reset_event=true + }; + + enum initial_event_state + { + event_initially_reset=false, + event_initially_set=true + }; + + 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, 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::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()); + } + return res; + } + + inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count) + { +#if !defined(BOOST_NO_ANSI_APIS) + handle const res=win32::CreateSemaphoreA(0,initial_count,max_count,0); +#else +#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 duplicate_handle(handle source) + { + handle const current_process=GetCurrentProcess(); + long const same_access_flag=2; + handle new_handle=0; + bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0; + if(!success) + { + boost::throw_exception(thread_resource_error()); + } + return new_handle; + } + + inline void release_semaphore(handle semaphore,long count) + { + 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; + } + + private: + handle m_completionHandle; + }; +#endif + class BOOST_THREAD_DECL handle_manager + { + private: + handle handle_to_manage; + handle_manager(handle_manager&); + handle_manager& operator=(handle_manager&); + + void cleanup() + { + if(handle_to_manage && handle_to_manage!=invalid_handle_value) + { + BOOST_VERIFY(CloseHandle(handle_to_manage)); + } + } + + public: + explicit handle_manager(handle handle_to_manage_): + handle_to_manage(handle_to_manage_) + {} + handle_manager(): + handle_to_manage(0) + {} + + handle_manager& operator=(handle new_handle) + { + cleanup(); + handle_to_manage=new_handle; + return *this; + } + + operator handle() const + { + return handle_to_manage; + } + + handle duplicate() const + { + return duplicate_handle(handle_to_manage); + } + + void swap(handle_manager& other) + { + std::swap(handle_to_manage,other.handle_to_manage); + } + + handle release() + { + handle const res=handle_to_manage; + handle_to_manage=0; + return res; + } + + bool operator!() const + { + return !handle_to_manage; + } + + ~handle_manager() + { + cleanup(); + } + }; + } + } +} + +#if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE) + +namespace boost +{ + namespace detail + { + namespace win32 + { +#if _MSC_VER==1400 + extern "C" unsigned char _interlockedbittestandset(long *a,long b); + extern "C" unsigned char _interlockedbittestandreset(long *a,long b); +#else + extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b); + extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b); +#endif + +#pragma intrinsic(_interlockedbittestandset) +#pragma intrinsic(_interlockedbittestandreset) + + inline bool interlocked_bit_test_and_set(long* x,long bit) + { + return _interlockedbittestandset(x,bit)!=0; + } + + inline bool interlocked_bit_test_and_reset(long* x,long bit) + { + return _interlockedbittestandreset(x,bit)!=0; + } + + } + } +} +#define BOOST_THREAD_BTS_DEFINED +#elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86) +namespace boost +{ + namespace detail + { + namespace win32 + { + inline bool interlocked_bit_test_and_set(long* x,long bit) + { +#ifndef BOOST_INTEL_CXX_VERSION + __asm { + mov eax,bit; + mov edx,x; + lock bts [edx],eax; + setc al; + }; +#else + bool ret; + __asm { + mov eax,bit + mov edx,x + lock bts [edx],eax + setc al + mov ret, al + }; + return ret; + +#endif + } + + inline bool interlocked_bit_test_and_reset(long* x,long bit) + { +#ifndef BOOST_INTEL_CXX_VERSION + __asm { + mov eax,bit; + mov edx,x; + lock btr [edx],eax; + setc al; + }; +#else + bool ret; + __asm { + mov eax,bit + mov edx,x + lock btr [edx],eax + setc al + mov ret, al + }; + return ret; + +#endif + } + + } + } +} +#define BOOST_THREAD_BTS_DEFINED +#endif + +#ifndef BOOST_THREAD_BTS_DEFINED + +namespace boost +{ + namespace detail + { + namespace win32 + { + inline bool interlocked_bit_test_and_set(long* x,long bit) + { + long const value=1<<bit; + long old=*x; + do + { + long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old); + if(current==old) + { + break; + } + old=current; + } + while(true) ; + return (old&value)!=0; + } + + inline bool interlocked_bit_test_and_reset(long* x,long bit) + { + long const value=1<<bit; + long old=*x; + do + { + long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old); + if(current==old) + { + break; + } + old=current; + } + while(true) ; + return (old&value)!=0; + } + } + } +} +#endif + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/with_lock_guard.hpp b/src/third_party/boost-1.60.0/boost/thread/with_lock_guard.hpp new file mode 100644 index 00000000000..5d99b36f2e4 --- /dev/null +++ b/src/third_party/boost-1.60.0/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/src/third_party/boost-1.60.0/boost/thread/xtime.hpp b/src/third_party/boost-1.60.0/boost/thread/xtime.hpp new file mode 100644 index 00000000000..9c6a3596400 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/xtime.hpp @@ -0,0 +1,93 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007-8 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) + +#ifndef BOOST_XTIME_WEK070601_HPP +#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> +#include <boost/date_time/posix_time/conversion.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost { + +enum xtime_clock_types +{ + TIME_UTC_=1 +// TIME_TAI, +// TIME_MONOTONIC, +// TIME_PROCESS, +// TIME_THREAD, +// TIME_LOCAL, +// TIME_SYNC, +// TIME_RESOLUTION +}; + +struct xtime +{ +#if defined(BOOST_NO_INT64_T) + typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX +#else + typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX +#endif + + typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND + + xtime_sec_t sec; + xtime_nsec_t nsec; + + operator system_time() const + { + return boost::posix_time::from_time_t(0)+ + boost::posix_time::seconds(static_cast<long>(sec))+ +#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS + boost::posix_time::nanoseconds(nsec); +#else + boost::posix_time::microseconds((nsec+500)/1000); +#endif + } + +}; + +inline xtime get_xtime(boost::system_time const& abs_time) +{ + xtime res; + boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); + + res.sec=static_cast<xtime::xtime_sec_t>(time_since_epoch.total_seconds()); + res.nsec=static_cast<xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second())); + return res; +} + +inline int xtime_get(struct xtime* xtp, int clock_type) +{ + if (clock_type == TIME_UTC_) + { + *xtp=get_xtime(get_system_time()); + return clock_type; + } + return 0; +} + + +inline int xtime_cmp(const xtime& xt1, const xtime& xt2) +{ + if (xt1.sec == xt2.sec) + return (int)(xt1.nsec - xt2.nsec); + else + return (xt1.sec > xt2.sec) ? 1 : -1; +} + +} // namespace boost + +#include <boost/config/abi_suffix.hpp> +#endif +#endif //BOOST_XTIME_WEK070601_HPP |