summaryrefslogtreecommitdiff
path: root/boost/thread
diff options
context:
space:
mode:
Diffstat (limited to 'boost/thread')
-rw-r--r--boost/thread/caller_context.hpp7
-rw-r--r--boost/thread/concurrent_queues/deque_adaptor.hpp209
-rw-r--r--boost/thread/concurrent_queues/deque_base.hpp202
-rw-r--r--boost/thread/concurrent_queues/deque_views.hpp165
-rw-r--r--boost/thread/concurrent_queues/detail/sync_deque_base.hpp223
-rw-r--r--boost/thread/concurrent_queues/detail/sync_queue_base.hpp223
-rw-r--r--boost/thread/concurrent_queues/queue_adaptor.hpp78
-rwxr-xr-xboost/thread/concurrent_queues/queue_base.hpp102
-rw-r--r--boost/thread/concurrent_queues/queue_op_status.hpp2
-rw-r--r--boost/thread/concurrent_queues/queue_views.hpp36
-rw-r--r--boost/thread/concurrent_queues/sync_bounded_queue.hpp725
-rw-r--r--boost/thread/concurrent_queues/sync_deque.hpp327
-rw-r--r--boost/thread/concurrent_queues/sync_priority_queue.hpp369
-rw-r--r--boost/thread/concurrent_queues/sync_queue.hpp328
-rw-r--r--boost/thread/concurrent_queues/sync_timed_queue.hpp466
-rw-r--r--boost/thread/csbl/deque.hpp2
-rw-r--r--boost/thread/csbl/devector.hpp100
-rw-r--r--boost/thread/csbl/list.hpp2
-rw-r--r--boost/thread/csbl/queue.hpp45
-rw-r--r--boost/thread/csbl/vector.hpp2
-rw-r--r--boost/thread/detail/invoker.hpp2
-rw-r--r--boost/thread/detail/work.hpp23
-rw-r--r--boost/thread/executors/basic_thread_pool.hpp28
-rw-r--r--boost/thread/executors/detail/priority_executor_base.hpp77
-rw-r--r--boost/thread/executors/detail/scheduled_executor_base.hpp66
-rw-r--r--boost/thread/executors/inline_executor.hpp54
-rw-r--r--boost/thread/executors/loop_executor.hpp45
-rw-r--r--boost/thread/executors/scheduled_thread_pool.hpp48
-rw-r--r--boost/thread/executors/scheduler.hpp271
-rw-r--r--boost/thread/executors/scheduling_adaptor.hpp51
-rw-r--r--boost/thread/executors/serial_executor.hpp35
-rw-r--r--boost/thread/executors/serial_executor_cont.hpp170
-rw-r--r--boost/thread/executors/thread_executor.hpp36
-rw-r--r--boost/thread/executors/work.hpp25
-rw-r--r--boost/thread/experimental/config/inline_namespace.hpp23
-rw-r--r--boost/thread/experimental/exception_list.hpp16
-rw-r--r--boost/thread/experimental/parallel/v1/exception_list.hpp70
-rw-r--r--boost/thread/experimental/parallel/v1/inline_namespace.hpp28
-rw-r--r--boost/thread/experimental/parallel/v2/inline_namespace.hpp29
-rwxr-xr-xboost/thread/experimental/parallel/v2/task_region.hpp316
-rw-r--r--boost/thread/experimental/task_region.hpp16
-rw-r--r--boost/thread/future.hpp1413
-rw-r--r--boost/thread/futures/future_error.hpp98
-rw-r--r--boost/thread/futures/future_error_code.hpp (renamed from boost/thread/future_error_code.hpp)6
-rw-r--r--boost/thread/futures/future_status.hpp30
-rw-r--r--boost/thread/futures/is_future_type.hpp21
-rw-r--r--boost/thread/futures/launch.hpp30
-rw-r--r--boost/thread/futures/wait_for_all.hpp74
-rw-r--r--boost/thread/futures/wait_for_any.hpp161
-rw-r--r--boost/thread/latch.hpp2
-rw-r--r--boost/thread/pthread/mutex.hpp28
-rw-r--r--boost/thread/pthread/recursive_mutex.hpp19
-rw-r--r--boost/thread/pthread/thread_data.hpp13
-rw-r--r--boost/thread/sync_bounded_queue.hpp708
-rw-r--r--boost/thread/sync_queue.hpp649
-rw-r--r--boost/thread/user_scheduler.hpp16
-rw-r--r--boost/thread/win32/thread_primitives.hpp1
57 files changed, 6030 insertions, 2281 deletions
diff --git a/boost/thread/caller_context.hpp b/boost/thread/caller_context.hpp
index 1e341686b0..dc50a05f97 100644
--- a/boost/thread/caller_context.hpp
+++ b/boost/thread/caller_context.hpp
@@ -1,4 +1,4 @@
-// (C) Copyright 2013 Vicente J. Botet Escriba
+// (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)
@@ -12,6 +12,7 @@
#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>
@@ -43,9 +44,11 @@ namespace boost
#endif
{
io::ios_flags_saver ifs(os);
- os << ctx.filename << "["
+ 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;
}
diff --git a/boost/thread/concurrent_queues/deque_adaptor.hpp b/boost/thread/concurrent_queues/deque_adaptor.hpp
new file mode 100644
index 0000000000..a8f45f863f
--- /dev/null
+++ b/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/boost/thread/concurrent_queues/deque_base.hpp b/boost/thread/concurrent_queues/deque_base.hpp
new file mode 100644
index 0000000000..f76e8a761d
--- /dev/null
+++ b/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/boost/thread/concurrent_queues/deque_views.hpp b/boost/thread/concurrent_queues/deque_views.hpp
new file mode 100644
index 0000000000..5715fb88cf
--- /dev/null
+++ b/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/boost/thread/concurrent_queues/detail/sync_deque_base.hpp b/boost/thread/concurrent_queues/detail/sync_deque_base.hpp
new file mode 100644
index 0000000000..877e1e2eb4
--- /dev/null
+++ b/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/boost/thread/concurrent_queues/detail/sync_queue_base.hpp b/boost/thread/concurrent_queues/detail/sync_queue_base.hpp
new file mode 100644
index 0000000000..653e273f8b
--- /dev/null
+++ b/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/boost/thread/concurrent_queues/queue_adaptor.hpp b/boost/thread/concurrent_queues/queue_adaptor.hpp
index c729276f99..f04e0354f7 100644
--- a/boost/thread/concurrent_queues/queue_adaptor.hpp
+++ b/boost/thread/concurrent_queues/queue_adaptor.hpp
@@ -27,12 +27,12 @@ namespace detail
template <typename Queue>
class queue_adaptor_copyable_only :
- public boost::queue_base<typename Queue::value_type>
+ public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
- typedef std::size_t size_type;
+ typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
queue_adaptor_copyable_only() {}
@@ -46,29 +46,29 @@ namespace detail
// Modifiers
void close() { queue.close(); }
- void push_back(const value_type& x) { queue.push_back(x); }
+ void push(const value_type& x) { queue.push(x); }
- void pull_front(value_type& x) { queue.pull_front(x); };
- value_type pull_front() { return queue.pull_front(); }
+ void pull(value_type& x) { queue.pull(x); };
+ value_type pull() { return queue.pull(); }
- 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 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_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 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_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); }
+ 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>
+ public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
- typedef std::size_t size_type;
+ typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -84,30 +84,30 @@ namespace detail
void close() { queue.close(); }
- void pull_front(value_type& x) { queue.pull_front(x); };
+ void pull(value_type& x) { queue.pull(x); };
// enable_if is_nothrow_copy_movable<value_type>
- value_type pull_front() { return queue.pull_front(); }
+ value_type pull() { return queue.pull(); }
- queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); }
+ queue_op_status try_pull(value_type& x) { return queue.try_pull(x); }
- queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); }
+ queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); }
- queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); }
+ queue_op_status wait_pull(value_type& x) { return queue.wait_pull(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)); }
+ 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>
+ public boost::queue_base<typename Queue::value_type, typename Queue::size_type>
{
Queue queue;
public:
typedef typename Queue::value_type value_type;
- typedef std::size_t size_type;
+ typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
@@ -123,31 +123,31 @@ namespace detail
void close() { queue.close(); }
- void push_back(const value_type& x) { queue.push_back(x); }
+ void push(const value_type& x) { queue.push(x); }
- void pull_front(value_type& x) { queue.pull_front(x); };
+ void pull(value_type& x) { queue.pull(x); };
// enable_if is_nothrow_copy_movable<value_type>
- value_type pull_front() { return queue.pull_front(); }
+ value_type pull() { return queue.pull(); }
- 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 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_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 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_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); }
+ 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_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)); }
+ 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__
+#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
@@ -195,7 +195,7 @@ namespace detail
{
public:
typedef typename Queue::value_type value_type;
- typedef std::size_t size_type;
+ typedef typename Queue::size_type size_type;
// Constructors/Assignment/Destructors
virtual ~queue_adaptor() {};
};
diff --git a/boost/thread/concurrent_queues/queue_base.hpp b/boost/thread/concurrent_queues/queue_base.hpp
index 5ed14fd393..0d42839158 100755
--- a/boost/thread/concurrent_queues/queue_base.hpp
+++ b/boost/thread/concurrent_queues/queue_base.hpp
@@ -27,12 +27,12 @@ namespace concurrent
namespace detail
{
- template <typename ValueType>
+ template <typename ValueType, class SizeType>
class queue_base_copyable_only
{
public:
typedef ValueType value_type;
- typedef std::size_t size_type;
+ typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_copyable_only() {};
@@ -46,28 +46,28 @@ namespace detail
// Modifiers
virtual void close() = 0;
- virtual void push_back(const value_type& x) = 0;
+ virtual void push(const value_type& x) = 0;
- virtual void pull_front(value_type&) = 0;
- virtual value_type pull_front() = 0;
+ virtual void pull(value_type&) = 0;
+ virtual value_type pull() = 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 try_push(const value_type& x) = 0;
+ virtual queue_op_status try_pull(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 nonblocking_push(const value_type& x) = 0;
+ virtual queue_op_status nonblocking_pull(value_type&) = 0;
- virtual queue_op_status wait_push_back(const value_type& x) = 0;
- virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
+ virtual queue_op_status wait_push(const value_type& x) = 0;
+ virtual queue_op_status wait_pull(ValueType& elem) = 0;
};
- template <typename ValueType>
+ template <typename ValueType, class SizeType>
class queue_base_movable_only
{
public:
typedef ValueType value_type;
- typedef std::size_t size_type;
+ typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_movable_only() {};
@@ -80,29 +80,29 @@ namespace detail
// Modifiers
virtual void close() = 0;
- virtual void pull_front(value_type&) = 0;
+ virtual void pull(value_type&) = 0;
// enable_if is_nothrow_movable<value_type>
- virtual value_type pull_front() = 0;
+ virtual value_type pull() = 0;
- virtual queue_op_status try_pull_front(value_type&) = 0;
+ virtual queue_op_status try_pull(value_type&) = 0;
- virtual queue_op_status nonblocking_pull_front(value_type&) = 0;
+ virtual queue_op_status nonblocking_pull(value_type&) = 0;
- virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
+ virtual queue_op_status wait_pull(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;
+ 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>
+ template <typename ValueType, class SizeType>
class queue_base_copyable_and_movable
{
public:
typedef ValueType value_type;
- typedef std::size_t size_type;
+ typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base_copyable_and_movable() {};
@@ -116,30 +116,30 @@ namespace detail
// Modifiers
virtual void close() = 0;
- virtual void push_back(const value_type& x) = 0;
+ virtual void push(const value_type& x) = 0;
- virtual void pull_front(value_type&) = 0;
+ virtual void pull(value_type&) = 0;
// enable_if is_nothrow_copy_movable<value_type>
- virtual value_type pull_front() = 0;
+ virtual value_type pull() = 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 try_push(const value_type& x) = 0;
+ virtual queue_op_status try_pull(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 nonblocking_push(const value_type& x) = 0;
+ virtual queue_op_status nonblocking_pull(value_type&) = 0;
- virtual queue_op_status wait_push_back(const value_type& x) = 0;
- virtual queue_op_status wait_pull_front(ValueType& elem) = 0;
+ virtual queue_op_status wait_push(const value_type& x) = 0;
+ virtual queue_op_status wait_pull(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;
+ 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,
+ template <class T, class ST,
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
-#if defined __GNUC__
+#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
@@ -166,28 +166,28 @@ namespace detail
>
struct queue_base;
- template <class T>
- struct queue_base<T, true, true> {
- typedef queue_base_copyable_and_movable<T> type;
+ template <class T, class ST>
+ struct queue_base<T, ST, true, true> {
+ typedef queue_base_copyable_and_movable<T, ST> type;
};
- template <class T>
- struct queue_base<T, true, false> {
- typedef queue_base_copyable_only<T> type;
+ template <class T, class ST>
+ struct queue_base<T, ST, true, false> {
+ typedef queue_base_copyable_only<T, ST> type;
};
- template <class T>
- struct queue_base<T, false, true> {
- typedef queue_base_movable_only<T> type;
+ template <class T, class ST>
+ struct queue_base<T, ST, false, true> {
+ typedef queue_base_movable_only<T, ST> type;
};
}
- template <typename ValueType>
+ template <typename ValueType, class SizeType=std::size_t>
class queue_base :
- public detail::queue_base<ValueType>::type
+ public detail::queue_base<ValueType, SizeType>::type
{
public:
typedef ValueType value_type;
- typedef std::size_t size_type;
+ typedef SizeType size_type;
// Constructors/Assignment/Destructors
virtual ~queue_base() {};
};
diff --git a/boost/thread/concurrent_queues/queue_op_status.hpp b/boost/thread/concurrent_queues/queue_op_status.hpp
index 3a8f0d994d..197650d052 100644
--- a/boost/thread/concurrent_queues/queue_op_status.hpp
+++ b/boost/thread/concurrent_queues/queue_op_status.hpp
@@ -22,7 +22,7 @@ namespace concurrent
{
BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status)
- { success = 0, empty, full, closed, busy }
+ { success = 0, empty, full, closed, busy, timeout, not_ready }
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
struct sync_queue_is_closed : std::exception
diff --git a/boost/thread/concurrent_queues/queue_views.hpp b/boost/thread/concurrent_queues/queue_views.hpp
index 1c06af8297..5a4512dd6e 100644
--- a/boost/thread/concurrent_queues/queue_views.hpp
+++ b/boost/thread/concurrent_queues/queue_views.hpp
@@ -43,27 +43,17 @@ namespace concurrent
// Modifiers
void close() { queue->close(); }
- void push(const value_type& x) { queue->push_back(x); }
+ void push(const value_type& x) { queue->push(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 try_push(const value_type& x) { return queue->try_push(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); }
+ 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_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)); }
+ 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>
@@ -88,20 +78,20 @@ namespace concurrent
void push(const value_type& x) { queue->push_front(x); }
- void pull(value_type& x) { queue->pull_front(x); };
+ void pull(value_type& x) { queue->pull(x); };
// enable_if is_nothrow_copy_movable<value_type>
- value_type pull() { return queue->pull_front(); }
+ 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_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_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_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)); }
diff --git a/boost/thread/concurrent_queues/sync_bounded_queue.hpp b/boost/thread/concurrent_queues/sync_bounded_queue.hpp
new file mode 100644
index 0000000000..e34fa56f37
--- /dev/null
+++ b/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/boost/thread/concurrent_queues/sync_deque.hpp b/boost/thread/concurrent_queues/sync_deque.hpp
new file mode 100644
index 0000000000..c84dae022a
--- /dev/null
+++ b/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/boost/thread/concurrent_queues/sync_priority_queue.hpp b/boost/thread/concurrent_queues/sync_priority_queue.hpp
new file mode 100644
index 0000000000..d604faa742
--- /dev/null
+++ b/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/boost/thread/concurrent_queues/sync_queue.hpp b/boost/thread/concurrent_queues/sync_queue.hpp
new file mode 100644
index 0000000000..7183c9cad8
--- /dev/null
+++ b/boost/thread/concurrent_queues/sync_queue.hpp
@@ -0,0 +1,328 @@
+#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 <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)
+ {
+ 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(elem, lk);
+ 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/boost/thread/concurrent_queues/sync_timed_queue.hpp b/boost/thread/concurrent_queues/sync_timed_queue.hpp
new file mode 100644
index 0000000000..8f24f43ecd
--- /dev/null
+++ b/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/boost/thread/csbl/deque.hpp b/boost/thread/csbl/deque.hpp
index 1e48903b1c..2b26a46e1a 100644
--- a/boost/thread/csbl/deque.hpp
+++ b/boost/thread/csbl/deque.hpp
@@ -19,7 +19,7 @@
// [
// _Ty=non_copyable
// ]
-#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_HDR_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
+#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
diff --git a/boost/thread/csbl/devector.hpp b/boost/thread/csbl/devector.hpp
new file mode 100644
index 0000000000..c11ad29ba1
--- /dev/null
+++ b/boost/thread/csbl/devector.hpp
@@ -0,0 +1,100 @@
+// 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 vector<T> vector_type;
+ vector<T> 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)
+ BOOST_NOEXCEPT_IF(vector<T>::allocator_traits_type::propagate_on_container_move_assignment::value)
+ {
+ 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/boost/thread/csbl/list.hpp b/boost/thread/csbl/list.hpp
index c7f10a18d5..52ff45d349 100644
--- a/boost/thread/csbl/list.hpp
+++ b/boost/thread/csbl/list.hpp
@@ -11,7 +11,7 @@
#include <boost/config.hpp>
-#if defined BOOST_THREAD_USES_BOOST_LIST || defined BOOST_NO_CXX11_HDR_LIST || defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#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
diff --git a/boost/thread/csbl/queue.hpp b/boost/thread/csbl/queue.hpp
new file mode 100644
index 0000000000..1aa645d18f
--- /dev/null
+++ b/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/boost/thread/csbl/vector.hpp b/boost/thread/csbl/vector.hpp
index d39c87d114..c77a5b143b 100644
--- a/boost/thread/csbl/vector.hpp
+++ b/boost/thread/csbl/vector.hpp
@@ -11,7 +11,7 @@
#include <boost/config.hpp>
-#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_HDR_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#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
diff --git a/boost/thread/detail/invoker.hpp b/boost/thread/detail/invoker.hpp
index 44deb1645b..7ab3b33990 100644
--- a/boost/thread/detail/invoker.hpp
+++ b/boost/thread/detail/invoker.hpp
@@ -134,7 +134,7 @@ namespace boost
//BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END
#else
-#if ! defined BOOST_MSVC
+#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)
diff --git a/boost/thread/detail/work.hpp b/boost/thread/detail/work.hpp
deleted file mode 100644
index 1e10c837bb..0000000000
--- a/boost/thread/detail/work.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// (C) Copyright 2013 Vicente J. Botet Escriba
-//
-// Distributed under the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_THREAD_DETAIL_WORK_HPP
-#define BOOST_THREAD_DETAIL_WORK_HPP
-
-
-#include <boost/thread/detail/nullary_function.hpp>
-
-namespace boost
-{
- namespace thread_detail
- {
-
- typedef detail::nullary_function<void()> work;
- }
-
-} // namespace boost
-
-#endif // BOOST_THREAD_DETAIL_MEMORY_HPP
diff --git a/boost/thread/executors/basic_thread_pool.hpp b/boost/thread/executors/basic_thread_pool.hpp
index 11283ddf42..64ba1e90e0 100644
--- a/boost/thread/executors/basic_thread_pool.hpp
+++ b/boost/thread/executors/basic_thread_pool.hpp
@@ -14,7 +14,7 @@
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/scoped_thread.hpp>
-#include <boost/thread/sync_queue.hpp>
+#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/csbl/vector.hpp>
@@ -36,7 +36,7 @@ namespace executors
typedef csbl::vector<thread_t> thread_vector;
/// the thread safe work queue
- sync_queue<work > work_queue;
+ concurrent::sync_queue<work > work_queue;
/// A move aware vector
thread_vector threads;
@@ -48,22 +48,19 @@ namespace executors
*/
bool try_executing_one()
{
- work task;
try
{
- if (work_queue.try_pull_front(task) == queue_op_status::success)
+ work task;
+ if (work_queue.try_pull(task) == queue_op_status::success)
{
task();
return true;
}
return false;
}
- catch (std::exception& )
- {
- return false;
- }
catch (...)
{
+ std::terminate();
return false;
}
}
@@ -90,17 +87,14 @@ namespace executors
for(;;)
{
work task;
- queue_op_status st = work_queue.wait_pull_front(task);
+ queue_op_status st = work_queue.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
}
}
- catch (std::exception& )
- {
- return;
- }
catch (...)
{
+ std::terminate();
return;
}
}
@@ -134,7 +128,7 @@ namespace executors
*
* \b Throws: Whatever exception is thrown while initializing the needed resources.
*/
- basic_thread_pool(unsigned const thread_count = thread::hardware_concurrency())
+ basic_thread_pool(unsigned const thread_count = thread::hardware_concurrency()+1)
{
try
{
@@ -275,18 +269,18 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
- work_queue.push_back(work(closure));
+ work_queue.push(work(closure));
}
#endif
void submit(void (*closure)())
{
- work_queue.push_back(work(closure));
+ work_queue.push(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
- work_queue.push_back(work(boost::forward<Closure>(closure)));
+ work_queue.push(work(boost::forward<Closure>(closure)));
}
/**
diff --git a/boost/thread/executors/detail/priority_executor_base.hpp b/boost/thread/executors/detail/priority_executor_base.hpp
new file mode 100644
index 0000000000..2191c0b37a
--- /dev/null
+++ b/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/boost/thread/executors/detail/scheduled_executor_base.hpp b/boost/thread/executors/detail/scheduled_executor_base.hpp
new file mode 100644
index 0000000000..ec0038f7e3
--- /dev/null
+++ b/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/boost/thread/executors/inline_executor.hpp b/boost/thread/executors/inline_executor.hpp
index bc6bd9fe7e..5dd523184e 100644
--- a/boost/thread/executors/inline_executor.hpp
+++ b/boost/thread/executors/inline_executor.hpp
@@ -26,6 +26,7 @@ namespace executors
/// 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.
@@ -66,16 +67,22 @@ namespace executors
*/
void close()
{
+ lock_guard<mutex> lk(mtx_);
closed_ = true;
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
- bool closed()
+ 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.
@@ -93,21 +100,54 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
- if (closed()) return;
- 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)())
{
- if (closed()) return;
- 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)
{
- if (closed()) return;
- closure();
+ {
+ lock_guard<mutex> lk(mtx_);
+ if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
+ }
+ try
+ {
+ closure();
+ }
+ catch (...)
+ {
+ std::terminate();
+ return;
+ }
}
/**
diff --git a/boost/thread/executors/loop_executor.hpp b/boost/thread/executors/loop_executor.hpp
index c2798b4461..e9eadadf9e 100644
--- a/boost/thread/executors/loop_executor.hpp
+++ b/boost/thread/executors/loop_executor.hpp
@@ -14,7 +14,7 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
-#include <boost/thread/sync_queue.hpp>
+#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -31,7 +31,7 @@ namespace executors
typedef executors::work work;
private:
/// the thread safe work queue
- sync_queue<work > work_queue;
+ concurrent::sync_queue<work > work_queue;
public:
/**
@@ -44,19 +44,16 @@ namespace executors
work task;
try
{
- if (work_queue.try_pull_front(task) == queue_op_status::success)
+ if (work_queue.try_pull(task) == queue_op_status::success)
{
task();
return true;
}
return false;
}
- catch (std::exception& )
- {
- return false;
- }
catch (...)
{
+ std::terminate();
return false;
}
}
@@ -74,19 +71,7 @@ namespace executors
}
- /**
- * The main loop of the worker thread
- */
- void worker_thread()
- {
- while (!closed())
- {
- schedule_one_or_yield();
- }
- while (try_executing_one())
- {
- }
- }
+
public:
/// loop_executor is not copyable.
@@ -112,9 +97,19 @@ namespace executors
}
/**
- * loop
+ * The main loop of the worker thread
*/
- void loop() { 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.
@@ -148,18 +143,18 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
- work_queue.push_back(work(closure));
+ work_queue.push(work(closure));
}
#endif
void submit(void (*closure)())
{
- work_queue.push_back(work(closure));
+ work_queue.push(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
- work_queue.push_back(work(boost::forward<Closure>(closure)));
+ work_queue.push(work(boost::forward<Closure>(closure)));
}
/**
diff --git a/boost/thread/executors/scheduled_thread_pool.hpp b/boost/thread/executors/scheduled_thread_pool.hpp
new file mode 100644
index 0000000000..408013b283
--- /dev/null
+++ b/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/boost/thread/executors/scheduler.hpp b/boost/thread/executors/scheduler.hpp
new file mode 100644
index 0000000000..5796a7d394
--- /dev/null
+++ b/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/boost/thread/executors/scheduling_adaptor.hpp b/boost/thread/executors/scheduling_adaptor.hpp
new file mode 100644
index 0000000000..ac0a0acbce
--- /dev/null
+++ b/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/boost/thread/executors/serial_executor.hpp b/boost/thread/executors/serial_executor.hpp
index dae1014b47..6f4266668f 100644
--- a/boost/thread/executors/serial_executor.hpp
+++ b/boost/thread/executors/serial_executor.hpp
@@ -12,7 +12,7 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
-#include <boost/thread/sync_queue.hpp>
+#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/executors/generic_executor_ref.hpp>
#include <boost/thread/future.hpp>
@@ -33,7 +33,7 @@ namespace executors
typedef scoped_thread<> thread_t;
/// the thread safe work queue
- sync_queue<work > work_queue;
+ concurrent::sync_queue<work > work_queue;
generic_executor_ref ex;
thread_t thr;
@@ -43,8 +43,13 @@ namespace executors
try_executing_one_task(work& task, boost::promise<void> &p)
: task(task), p(p) {}
void operator()() {
- task(); // if task() throws promise is not set but as the the program terminates and should terminate there is no need to use try-catch here.
- p.set_value();
+ try {
+ task();
+ p.set_value();
+ } catch (...)
+ {
+ p.set_exception(current_exception());
+ }
}
};
public:
@@ -52,7 +57,7 @@ namespace executors
* \par Returns
* The underlying executor wrapped on a generic executor reference.
*/
- generic_executor_ref underlying_executor() BOOST_NOEXCEPT { return ex; }
+ generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex; }
/**
* Effects: try to execute one task.
@@ -64,27 +69,19 @@ namespace executors
work task;
try
{
- if (work_queue.try_pull_front(task) == queue_op_status::success)
+ if (work_queue.try_pull(task) == queue_op_status::success)
{
boost::promise<void> p;
try_executing_one_task tmp(task,p);
ex.submit(tmp);
-// ex.submit([&task, &p]()
-// {
-// task(); // if task() throws promise is not set but as the the program terminates and should terminate there is no need to use try-catch here.
-// p.set_value();
-// });
p.get_future().wait();
return true;
}
return false;
}
- catch (std::exception& )
- {
- return false;
- }
catch (...)
{
+ std::terminate();
return false;
}
}
@@ -136,7 +133,7 @@ namespace executors
*/
~serial_executor()
{
- // signal to all the worker thread that there will be no more submissions.
+ // signal to the worker thread that there will be no more submissions.
close();
}
@@ -173,18 +170,18 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
- work_queue.push_back(work(closure));
+ work_queue.push(work(closure));
}
#endif
void submit(void (*closure)())
{
- work_queue.push_back(work(closure));
+ work_queue.push(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_RV_REF(Closure) closure)
{
- work_queue.push_back(work(boost::forward<Closure>(closure)));
+ work_queue.push(work(boost::forward<Closure>(closure)));
}
/**
diff --git a/boost/thread/executors/serial_executor_cont.hpp b/boost/thread/executors/serial_executor_cont.hpp
new file mode 100644
index 0000000000..1c4cc14aad
--- /dev/null
+++ b/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_RV_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/boost/thread/executors/thread_executor.hpp b/boost/thread/executors/thread_executor.hpp
index 9fc3362fde..a8cd5c212f 100644
--- a/boost/thread/executors/thread_executor.hpp
+++ b/boost/thread/executors/thread_executor.hpp
@@ -15,6 +15,8 @@
#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/config/abi_prefix.hpp>
@@ -28,6 +30,11 @@ namespace executors
/// 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.
@@ -52,7 +59,7 @@ namespace executors
{
}
/**
- * \b Effects: Destroys the inline executor.
+ * \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.
*/
@@ -60,6 +67,7 @@ namespace executors
{
// signal to all the worker thread that there will be no more submissions.
close();
+ // all the scoped threads will join before destroying
}
/**
@@ -68,16 +76,22 @@ namespace executors
*/
void close()
{
+ lock_guard<mutex> lk(mtx_);
closed_ = true;
}
/**
* \b Returns: whether the pool is closed for submissions.
*/
- bool closed()
+ 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.
@@ -95,24 +109,30 @@ namespace executors
template <typename Closure>
void submit(Closure & closure)
{
- if (closed()) return;
+ lock_guard<mutex> lk(mtx_);
+ if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
+ threads_.reserve(threads_.size() + 1);
thread th(closure);
- th.detach();
+ threads_.push_back(thread_t(boost::move(th)));
}
#endif
void submit(void (*closure)())
{
- if (closed()) return;
+ lock_guard<mutex> lk(mtx_);
+ if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
+ threads_.reserve(threads_.size() + 1);
thread th(closure);
- th.detach();
+ threads_.push_back(thread_t(boost::move(th)));
}
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
- if (closed()) return;
+ 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));
- th.detach();
+ threads_.push_back(thread_t(boost::move(th)));
}
/**
diff --git a/boost/thread/executors/work.hpp b/boost/thread/executors/work.hpp
index df1512cd95..bdaf7651b9 100644
--- a/boost/thread/executors/work.hpp
+++ b/boost/thread/executors/work.hpp
@@ -8,36 +8,23 @@
#define BOOST_THREAD_EXECUTORS_WORK_HPP
#include <boost/thread/detail/config.hpp>
-
-#if ! defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE \
- && ! defined BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
-#define BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
-//#define BOOST_THREAD_EXECUTORS_WORK_DONT_ACCEPT_MOVABLE
-#endif
-
-#if defined BOOST_THREAD_EXECUTORS_WORK_ACCEPTS_MOVABLE
-
#include <boost/thread/detail/nullary_function.hpp>
+#include <boost/thread/csbl/functional.hpp>
namespace boost
{
namespace executors
{
typedef detail::nullary_function<void()> work;
- }
-} // namespace boost
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef detail::nullary_function<void()> work_pq;
+ //typedef csbl::function<void()> work_pq;
#else
-#include <boost/thread/csbl/functional.hpp>
-
-namespace boost
-{
- namespace executors
- {
- typedef csbl::function<void()> work;
+ typedef csbl::function<void()> work_pq;
+#endif
}
} // namespace boost
-#endif
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP
diff --git a/boost/thread/experimental/config/inline_namespace.hpp b/boost/thread/experimental/config/inline_namespace.hpp
new file mode 100644
index 0000000000..9c3b081fbe
--- /dev/null
+++ b/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/boost/thread/experimental/exception_list.hpp b/boost/thread/experimental/exception_list.hpp
new file mode 100644
index 0000000000..748bfa85ee
--- /dev/null
+++ b/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/boost/thread/experimental/parallel/v1/exception_list.hpp b/boost/thread/experimental/parallel/v1/exception_list.hpp
new file mode 100644
index 0000000000..e4d3354f1c
--- /dev/null
+++ b/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/boost/thread/experimental/parallel/v1/inline_namespace.hpp b/boost/thread/experimental/parallel/v1/inline_namespace.hpp
new file mode 100644
index 0000000000..a607e53c46
--- /dev/null
+++ b/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/boost/thread/experimental/parallel/v2/inline_namespace.hpp b/boost/thread/experimental/parallel/v2/inline_namespace.hpp
new file mode 100644
index 0000000000..52d8e2904e
--- /dev/null
+++ b/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/boost/thread/experimental/parallel/v2/task_region.hpp b/boost/thread/experimental/parallel/v2/task_region.hpp
new file mode 100755
index 0000000000..3a278c500f
--- /dev/null
+++ b/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& ex)
+ {
+ }
+#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/boost/thread/experimental/task_region.hpp b/boost/thread/experimental/task_region.hpp
new file mode 100644
index 0000000000..9b60d8b19e
--- /dev/null
+++ b/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/boost/thread/future.hpp b/boost/thread/future.hpp
index a1e69c355a..e6e22363aa 100644
--- a/boost/thread/future.hpp
+++ b/boost/thread/future.hpp
@@ -1,5 +1,5 @@
// (C) Copyright 2008-10 Anthony Williams
-// (C) Copyright 2011-2014 Vicente J. Botet Escriba
+// (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
@@ -15,49 +15,52 @@
#ifndef BOOST_NO_EXCEPTIONS
-#include <boost/core/scoped_enum.hpp>
-#include <stdexcept>
-#include <iostream>
-#include <boost/thread/exceptional_ptr.hpp>
+#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/thread_time.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/condition_variable.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/exception_ptr.hpp>
-#include <boost/shared_ptr.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread_only.hpp>
+#include <boost/thread/thread_time.hpp>
+
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
#include <boost/optional.hpp>
#else
#include <boost/thread/csbl/memory/unique_ptr.hpp>
-//#include <boost/move/make_unique.hpp>
#endif
-#include <boost/type_traits/is_fundamental.hpp>
-#include <boost/thread/detail/is_convertible.hpp>
-#include <boost/type_traits/decay.hpp>
-#include <boost/type_traits/is_void.hpp>
-#include <boost/type_traits/conditional.hpp>
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include <algorithm>
-#include <boost/function.hpp>
+
+#include <boost/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/scoped_array.hpp>
#include <boost/enable_shared_from_this.hpp>
-#include <boost/core/enable_if.hpp>
-
-#include <list>
+#include <boost/exception_ptr.hpp>
+#include <boost/function.hpp>
#include <boost/next_prior.hpp>
-#include <vector>
+#include <boost/scoped_array.hpp>
+#include <boost/shared_ptr.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>
-#include <boost/thread/future_error_code.hpp>
-#ifdef BOOST_THREAD_USES_CHRONO
-#include <boost/chrono/system_clocks.hpp>
-#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#include <boost/thread/detail/memory.hpp>
@@ -67,14 +70,16 @@
#endif
#endif
-#include <boost/utility/result_of.hpp>
-#include <boost/thread/thread_only.hpp>
-
#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
#include <boost/thread/csbl/tuple.hpp>
#include <boost/thread/csbl/vector.hpp>
#endif
+#include <algorithm>
+#include <list>
+#include <vector>
+#include <utility>
+
#if defined BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_FUTURE future
#else
@@ -83,134 +88,26 @@
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
- any = async | deferred
- }
- BOOST_SCOPED_ENUM_DECLARE_END(launch)
-
- //enum class future_status
- BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status)
- {
- ready,
- timeout,
- deferred
- }
- BOOST_SCOPED_ENUM_DECLARE_END(future_status)
-
- 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))
- {}
- };
-
- namespace future_state
- {
- enum state { uninitialized, waiting, ready, moved, deferred };
- }
-
namespace detail
{
struct relocker
{
boost::unique_lock<boost::mutex>& lock_;
- bool unlocked_;
relocker(boost::unique_lock<boost::mutex>& lk):
lock_(lk)
{
lock_.unlock();
- unlocked_=true;
}
~relocker()
{
- if (unlocked_) {
+ if (! lock_.owns_lock()) {
lock_.lock();
}
}
void lock() {
- if (unlocked_) {
+ if (! lock_.owns_lock()) {
lock_.lock();
- unlocked_=false;
}
}
private:
@@ -220,36 +117,72 @@ namespace boost
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_;
- launch policy_;
bool is_constructed;
+ std::size_t cnt_;
+ 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.
- continuation_ptr_type continuation_ptr;
+ continuations_type continuations;
// This declaration should be only included conditionally, but is included to maintain the same layout.
- virtual void launch_continuation(boost::unique_lock<boost::mutex>&)
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base>)
{
}
shared_state_base():
done(false),
+ is_valid_(true),
is_deferred_(false),
- policy_(launch::none),
is_constructed(false),
- continuation_ptr()
+ cnt_(0),
+ policy_(launch::none),
+ continuations()
{}
virtual ~shared_state_base()
+ {
+ BOOST_ASSERT(cnt_==0);
+ }
+ virtual void block_if_needed(boost::unique_lock<boost::mutex>&)
{}
+ 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 inc(boost::unique_lock<boost::mutex>&) { ++cnt_; }
+ void inc() { boost::unique_lock<boost::mutex> lk(this->mutex); inc(lk); }
+
+ void dec(boost::unique_lock<boost::mutex>& lk) {
+ if (--cnt_ == 0) {
+ block_if_needed(lk);
+ }
+ }
+ void dec() { boost::unique_lock<boost::mutex> lk(this->mutex); dec(lk); }
+
void set_deferred()
{
is_deferred_ = true;
@@ -267,14 +200,14 @@ namespace boost
policy_ = launch::executor;
}
#endif
- waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
+ 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 remove_external_waiter(waiter_list::iterator it)
+ void unnotify_when_ready(notify_when_ready_handle it)
{
boost::lock_guard<boost::mutex> lock(this->mutex);
external_waiters.erase(it);
@@ -283,10 +216,14 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
void do_continuation(boost::unique_lock<boost::mutex>& lock)
{
- if (continuation_ptr) {
- continuation_ptr_type this_continuation_ptr = continuation_ptr;
- continuation_ptr.reset();
- this_continuation_ptr->launch_continuation(lock);
+ 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) {
+ boost::unique_lock<boost::mutex> cont_lock((*it)->mutex);
+ (*it)->launch_continuation(cont_lock, *it);
+ }
}
}
#else
@@ -295,9 +232,9 @@ namespace boost
}
#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
- void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
+ virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
{
- continuation_ptr= continuation;
+ continuations.push_back(continuation);
if (done) {
do_continuation(lock);
}
@@ -373,12 +310,17 @@ namespace boost
}
}
- virtual void wait(bool rethrow=true)
+ virtual void wait(boost::unique_lock<boost::mutex>& lock, bool rethrow=true)
{
- boost::unique_lock<boost::mutex> lock(this->mutex);
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)
{
@@ -431,27 +373,6 @@ namespace boost
mark_exceptional_finish_internal(boost::current_exception(), lock);
}
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- void mark_interrupted_finish()
- {
- boost::unique_lock<boost::mutex> lock(this->mutex);
- exception = boost::copy_exception(boost::thread_interrupted());
- mark_finished_internal(lock);
- }
-
- void set_interrupted_at_thread_exit()
- {
- unique_lock<boost::mutex> lk(this->mutex);
- if (has_value(lk))
- {
- throw_exception(promise_already_satisfied());
- }
- exception = boost::copy_exception(boost::thread_interrupted());
- this->is_constructed = true;
- detail::make_ready_at_thread_exit(shared_from_this());
- }
-#endif
-
void set_exception_at_thread_exit(exception_ptr e)
{
unique_lock<boost::mutex> lk(this->mutex);
@@ -481,20 +402,22 @@ namespace boost
return done && exception;
}
- bool has_exception(unique_lock<boost::mutex>&) const
- {
- return done && exception;
- }
-
- bool is_deferred(boost::lock_guard<boost::mutex>&) const {
- return is_deferred_;
- }
-
launch launch_policy(boost::unique_lock<boost::mutex>&) const
{
return policy_;
}
+ future_state::state get_state(boost::unique_lock<boost::mutex>& lk) 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);
@@ -511,10 +434,6 @@ namespace boost
exception_ptr get_exception_ptr()
{
boost::unique_lock<boost::mutex> lock(this->mutex);
- return get_exception_ptr(lock);
- }
- exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock)
- {
wait_internal(lock, false);
return exception;
}
@@ -580,21 +499,29 @@ namespace boost
void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
{
-#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
result = boost::move(result_);
-#else
+#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
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
+ 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_)
{
@@ -613,21 +540,29 @@ namespace boost
#endif
}
- storage_type& get_storage(boost::unique_lock<boost::mutex>& lock)
+ storage_type& get_storage(boost::unique_lock<boost::mutex>& lk)
{
- wait_internal(lock);
+ wait_internal(lk);
return result;
}
- virtual move_dest_type get()
+ virtual move_dest_type get(boost::unique_lock<boost::mutex>& lk)
{
- boost::unique_lock<boost::mutex> lock(this->mutex);
- return boost::move(*get_storage(lock));
+ 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()
+ virtual shared_future_get_result_type get_sh(boost::unique_lock<boost::mutex>& lk)
{
- boost::unique_lock<boost::mutex> lock(this->mutex);
- return *get_storage(lock);
+ 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_)
@@ -705,19 +640,27 @@ namespace boost
mark_finished_with_result_internal(result_, lock);
}
- virtual T& get()
+ virtual T& get(boost::unique_lock<boost::mutex>& lock)
{
- boost::unique_lock<boost::mutex> lock(this->mutex);
wait_internal(lock);
return *result;
}
+ T& get()
+ {
+ boost::unique_lock<boost::mutex> lk(this->mutex);
+ return get(lk);
+ }
- virtual T& get_sh()
+ virtual T& get_sh(boost::unique_lock<boost::mutex>& lock)
{
- boost::unique_lock<boost::mutex> lock(this->mutex);
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_)
{
@@ -755,17 +698,25 @@ namespace boost
mark_finished_with_result_internal(lock);
}
- virtual void get()
+ virtual void get(boost::unique_lock<boost::mutex>& lock)
{
- boost::unique_lock<boost::mutex> lock(this->mutex);
this->wait_internal(lock);
}
-
- virtual void get_sh()
+ 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()
{
@@ -801,15 +752,23 @@ namespace boost
this->set_async();
}
+ virtual void block_if_needed(boost::unique_lock<boost::mutex>& lk)
+ {
+ this->wait(lk, false);
+ }
+
~future_async_shared_state_base()
{
join();
}
- virtual void wait(bool rethrow)
+ virtual void wait(boost::unique_lock<boost::mutex>& lk, bool rethrow)
{
- join();
- this->base_type::wait(rethrow);
+ {
+ relocker rlk(lk);
+ join();
+ }
+ this->base_type::wait(lk, rethrow);
}
};
@@ -819,23 +778,23 @@ namespace boost
template<typename Rp, typename Fp>
struct future_async_shared_state: future_async_shared_state_base<Rp>
{
- explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
+ future_async_shared_state()
+ {
+ }
+
+ void init(BOOST_THREAD_FWD_REF(Fp) f)
{
- this->thr_ = thread(&future_async_shared_state::run, this, boost::forward<Fp>(f));
+ shared_ptr<boost::detail::shared_state_base> that = this->shared_from_this();
+ this->thr_ = thread(&future_async_shared_state::run, that, boost::forward<Fp>(f));
}
- static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
+ static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f)
{
+ future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get());
try
{
that->mark_finished_with_result(f());
}
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- that->mark_interrupted_finish();
- }
-#endif
catch(...)
{
that->mark_exceptional_finish();
@@ -846,24 +805,19 @@ namespace boost
template<typename Fp>
struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void>
{
- explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
+ void init(BOOST_THREAD_FWD_REF(Fp) f)
{
- this->thr_ = thread(&future_async_shared_state::run, this, boost::move(f));
+ this->thr_ = thread(&future_async_shared_state::run, this->shared_from_this(), boost::move(f));
}
- static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
+ static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f)
{
+ future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get());
try
{
f();
that->mark_finished_with_result();
}
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- that->mark_interrupted_finish();
- }
-#endif
catch(...)
{
that->mark_exceptional_finish();
@@ -874,23 +828,18 @@ namespace boost
template<typename Rp, typename Fp>
struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&>
{
- explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
+ void init(BOOST_THREAD_FWD_REF(Fp) f)
{
- this->thr_ = thread(&future_async_shared_state::run, this, boost::move(f));
+ this->thr_ = thread(&future_async_shared_state::run, this->shared_from_this(), boost::move(f));
}
- static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
+ static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f)
{
+ future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get());
try
{
that->mark_finished_with_result(f());
}
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- that->mark_interrupted_finish();
- }
-#endif
catch(...)
{
that->mark_exceptional_finish();
@@ -991,13 +940,13 @@ namespace boost
struct registered_waiter
{
boost::shared_ptr<detail::shared_state_base> future_;
- detail::shared_state_base::waiter_list::iterator wait_iterator;
+ 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::waiter_list::iterator wait_iterator_,
+ detail::shared_state_base::notify_when_ready_handle handle_,
count_type index_):
- future_(a_future),wait_iterator(wait_iterator_),index(index_)
+ future_(a_future),handle(handle_),index(index_)
{}
};
@@ -1035,7 +984,7 @@ namespace boost
};
boost::condition_variable_any cv;
- std::vector<registered_waiter> futures;
+ std::vector<registered_waiter> futures_;
count_type future_count;
public:
@@ -1048,11 +997,11 @@ namespace boost
{
if(f.future_)
{
- registered_waiter waiter(f.future_,f.future_->register_external_waiter(cv),future_count);
+ registered_waiter waiter(f.future_,f.future_->notify_when_ready(cv),future_count);
try {
- futures.push_back(waiter);
+ futures_.push_back(waiter);
} catch(...) {
- f.future_->remove_external_waiter(waiter.wait_iterator);
+ f.future_->unnotify_when_ready(waiter.handle);
throw;
}
}
@@ -1069,14 +1018,14 @@ namespace boost
count_type wait()
{
- all_futures_lock lk(futures);
+ all_futures_lock lk(futures_);
for(;;)
{
- for(count_type i=0;i<futures.size();++i)
+ for(count_type i=0;i<futures_.size();++i)
{
- if(futures[i].future_->done)
+ if(futures_[i].future_->done)
{
- return futures[i].index;
+ return futures_[i].index;
}
}
cv.wait(lk);
@@ -1085,9 +1034,9 @@ namespace boost
~future_waiter()
{
- for(count_type i=0;i<futures.size();++i)
+ for(count_type i=0;i<futures_.size();++i)
{
- futures[i].future_->remove_external_waiter(futures[i].wait_iterator);
+ futures_[i].future_->unnotify_when_ready(futures_[i].handle);
}
}
};
@@ -1101,93 +1050,28 @@ namespace boost
class shared_future;
template<typename T>
- struct is_future_type
- {
- BOOST_STATIC_CONSTANT(bool, value=false);
- typedef void type;
- };
-
- template<typename T>
- struct is_future_type<BOOST_THREAD_FUTURE<T> >
+ struct is_future_type<BOOST_THREAD_FUTURE<T> > : true_type
{
- BOOST_STATIC_CONSTANT(bool, value=true);
- typedef T type;
};
template<typename T>
- struct is_future_type<shared_future<T> >
+ struct is_future_type<shared_future<T> > : true_type
{
- BOOST_STATIC_CONSTANT(bool, value=true);
- typedef T type;
};
- 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)
-
- 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());
- }
+// 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>
@@ -1252,6 +1136,7 @@ namespace boost
/// 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>
@@ -1277,15 +1162,13 @@ namespace boost
future_ = p.get_future().future_;
}
-
future_ptr future_;
basic_future(future_ptr a_future):
future_(a_future)
{
+ if (a_future) a_future->inc();
}
- // Copy construction from a shared_future
- explicit basic_future(const shared_future<R>&) BOOST_NOEXCEPT;
public:
typedef future_state::state state;
@@ -1298,9 +1181,12 @@ namespace boost
basic_future(exceptional_ptr const& ex)
: future_(make_exceptional_future_ptr(ex))
{
+ future_->inc();
}
- ~basic_future() {}
+ ~basic_future() {
+ if (future_) future_->dec();
+ }
basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT:
future_(BOOST_THREAD_RV(other).future_)
@@ -1309,6 +1195,9 @@ namespace boost
}
basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT
{
+ if (this->future_) {
+ this->future_->dec();
+ }
future_=BOOST_THREAD_RV(other).future_;
BOOST_THREAD_RV(other).future_.reset();
return *this;
@@ -1318,6 +1207,14 @@ namespace boost
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_)
@@ -1332,6 +1229,10 @@ namespace boost
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();
@@ -1357,7 +1258,7 @@ namespace boost
bool valid() const BOOST_NOEXCEPT
{
- return future_ != 0;
+ return future_ != 0 && future_->valid();
}
void wait() const
@@ -1369,6 +1270,34 @@ namespace boost
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
@@ -1516,6 +1445,10 @@ namespace boost
}
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))));
@@ -1551,32 +1484,42 @@ namespace boost
// retrieving the value
move_dest_type get()
{
- if(!this->future_)
+ 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());
}
- future_ptr fut_=this->future_;
#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
- this->future_.reset();
+ this->future_->invalidate(lk);
#endif
- return fut_->get();
+ 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_)
+
+ 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(false);
- future_ptr fut_=this->future_;
+ this->future_->wait(lk, false);
#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
- this->future_.reset();
+ this->future_->invalidate(lk);
#endif
- if (fut_->has_value()) {
- return fut_->get();
+
+ if (this->future_->has_value(lk)) {
+ return this->future_->get(lk);
}
else {
return boost::move(v);
@@ -1587,17 +1530,21 @@ namespace boost
typename boost::disable_if< is_void<R2>, move_dest_type>::type
get_or(R2 const& v) // EXTENSION
{
- if(!this->future_)
+ if (this->future_ == 0)
{
boost::throw_exception(future_uninitialized());
}
- this->future_->wait(false);
- future_ptr fut_=this->future_;
+ 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_.reset();
+ this->future_->invalidate(lk);
#endif
- if (fut_->has_value()) {
- return fut_->get();
+ if (this->future_->has_value(lk)) {
+ return this->future_->get(lk);
}
else {
return v;
@@ -1736,43 +1683,55 @@ namespace boost
// retrieving the value
move_dest_type get()
{
- if(!this->future_)
+ 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());
}
- future_ptr fut_=this->future_;
#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
- this->future_.reset();
+ this->future_->invalidate(lk);
#endif
- return fut_->get();
+ return this->future_->get(lk);
}
move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
{
- if(!this->future_)
+ if (this->future_ == 0)
{
boost::throw_exception(future_uninitialized());
}
- this->future_->wait(false);
- future_ptr fut_=this->future_;
+ 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_.reset();
+ this->future_->invalidate(lk);
#endif
- if (fut_->has_value()) return fut_->get();
+ 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_)
+ if (this->future_ == 0)
{
boost::throw_exception(future_uninitialized());
}
- this->future_->wait(false);
- future_ptr fut_=this->future_;
+ 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_.reset();
+ this->future_->invalidate(lk);
#endif
- if (fut_->has_value()) return fut_->get();
+ if (this->future_->has_value(lk)) return this->future_->get(lk);
else return v;
}
@@ -1836,7 +1795,7 @@ namespace boost
typedef R value_type; // EXTENSION
shared_future(shared_future const& other):
- base_type(other)
+ base_type(other.future_)
{}
typedef future_state::state state;
@@ -1851,14 +1810,19 @@ namespace boost
shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other)
{
- shared_future(other).swap(*this);
+ if (other.future_) {
+ other.future_->inc();
+ }
+ if (this->future_) {
+ this->future_->dec();
+ }
+ 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))))
{
- BOOST_THREAD_RV(other).future_.reset();
}
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))))
@@ -1887,7 +1851,7 @@ namespace boost
return this->future_->run_if_is_deferred_or_ready();
}
// retrieving the value
- typename detail::shared_state<R>::shared_future_get_result_type get()
+ typename detail::shared_state<R>::shared_future_get_result_type get() const
{
if(!this->future_)
{
@@ -1898,15 +1862,14 @@ namespace boost
template <typename R2>
typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
- get_or(BOOST_THREAD_RV_REF(R2) v) // EXTENSION
+ get_or(BOOST_THREAD_RV_REF(R2) v) const // EXTENSION
{
if(!this->future_)
{
boost::throw_exception(future_uninitialized());
}
- future_ptr fut_=this->future_;
- fut_->wait();
- if (fut_->has_value()) return fut_->get_sh();
+ this->future_->wait();
+ if (this->future_->has_value()) return this->future_->get_sh();
else return boost::move(v);
}
@@ -1928,16 +1891,6 @@ namespace boost
BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
- namespace detail
- {
- /// Copy construction from a shared_future
- template <typename R>
- inline basic_future<R>::basic_future(const shared_future<R>& other) BOOST_NOEXCEPT
- : future_(other.future_)
- {
- }
- }
-
template <typename R>
class promise
{
@@ -2077,6 +2030,22 @@ namespace boost
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();
@@ -2503,7 +2472,10 @@ namespace boost
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;
@@ -2591,6 +2563,11 @@ namespace boost
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)
{
@@ -2606,12 +2583,6 @@ namespace boost
this->set_value_at_thread_exit(f());
}
#endif
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->set_interrupted_at_thread_exit();
- }
-#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -2638,12 +2609,6 @@ namespace boost
#endif
}
#endif
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->mark_interrupted_finish();
- }
-#endif
catch(...)
{
this->mark_exceptional_finish();
@@ -2678,6 +2643,11 @@ namespace boost
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)
{
@@ -2693,12 +2663,6 @@ namespace boost
this->set_value_at_thread_exit(f());
}
#endif
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->set_interrupted_at_thread_exit();
- }
-#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -2721,12 +2685,6 @@ namespace boost
this->mark_finished_with_result(res);
}
#endif
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->mark_interrupted_finish();
- }
-#endif
catch(...)
{
this->mark_exceptional_finish();
@@ -2754,18 +2712,21 @@ namespace boost
{
private:
task_shared_state(task_shared_state&);
- public:
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
- R (*f)(BOOST_THREAD_RV_REF(ArgTypes) ... );
- task_shared_state(R (*f_)(BOOST_THREAD_RV_REF(ArgTypes) ... )):
- f(f_)
- {}
+ typedef R (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... );
#else
- R (*f)();
- task_shared_state(R (*f_)()):
+ typedef R (*CallableType)();
+#endif
+ public:
+ CallableType f;
+ task_shared_state(CallableType f_):
f(f_)
{}
-#endif
+
+ 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)
@@ -2783,12 +2744,6 @@ namespace boost
this->set_value_at_thread_exit(boost::move(r));
}
#endif
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->set_interrupted_at_thread_exit();
- }
-#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -2812,12 +2767,6 @@ namespace boost
this->mark_finished_with_result(boost::move(res));
}
#endif
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->mark_interrupted_finish();
- }
-#endif
catch(...)
{
this->mark_exceptional_finish();
@@ -2844,16 +2793,19 @@ namespace boost
task_shared_state(task_shared_state&);
public:
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
- R& (*f)(BOOST_THREAD_RV_REF(ArgTypes) ... );
- task_shared_state(R& (*f_)(BOOST_THREAD_RV_REF(ArgTypes) ... )):
- f(f_)
- {}
+ typedef R& (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... );
#else
- R& (*f)();
- task_shared_state(R& (*f_)()):
+ typedef R& (*CallableType)();
+#endif
+ CallableType f;
+ task_shared_state(CallableType f_):
f(f_)
{}
-#endif
+
+ 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)
@@ -2870,12 +2822,6 @@ namespace boost
this->set_value_at_thread_exit(f());
}
#endif
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->set_interrupted_at_thread_exit();
- }
-#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -2898,12 +2844,6 @@ namespace boost
this->mark_finished_with_result(f());
}
#endif
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->mark_interrupted_finish();
- }
-#endif
catch(...)
{
this->mark_exceptional_finish();
@@ -2930,6 +2870,7 @@ namespace boost
private:
task_shared_state(task_shared_state&);
public:
+ typedef F CallableType;
F f;
task_shared_state(F const& f_):
f(f_)
@@ -2937,7 +2878,10 @@ namespace boost
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)
{
@@ -2953,12 +2897,6 @@ namespace boost
#endif
this->set_value_at_thread_exit();
}
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->set_interrupted_at_thread_exit();
- }
-#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -2980,12 +2918,6 @@ namespace boost
#endif
this->mark_finished_with_result();
}
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->mark_interrupted_finish();
- }
-#endif
catch(...)
{
this->mark_exceptional_finish();
@@ -3011,12 +2943,20 @@ namespace boost
{
private:
task_shared_state(task_shared_state&);
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ typedef void (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes)...);
+#else
+ typedef void (*CallableType)();
+#endif
public:
- void (*f)();
- task_shared_state(void (*f_)()):
+ 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)
{
@@ -3032,12 +2972,6 @@ namespace boost
#endif
this->set_value_at_thread_exit();
}
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->set_interrupted_at_thread_exit();
- }
-#endif
catch(...)
{
this->set_exception_at_thread_exit(current_exception());
@@ -3059,12 +2993,6 @@ namespace boost
#endif
this->mark_finished_with_result();
}
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- catch(thread_interrupted& )
- {
- this->mark_interrupted_finish();
- }
-#endif
catch(...)
{
this->mark_exceptional_finish();
@@ -3277,11 +3205,7 @@ namespace boost
A2 a2(a);
typedef thread_detail::allocator_destructor<A2> D;
-#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) );
-#else
- task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) );
-#endif
future_obtained = false;
}
@@ -3314,6 +3238,9 @@ namespace boost
void reset() {
if (!valid())
throw future_error(system::make_error_code(future_errc::no_state));
+
+ // As if *this = packaged_task(task->callable());
+
task->reset();
future_obtained=false;
}
@@ -3415,7 +3342,8 @@ namespace detail
BOOST_THREAD_FUTURE<Rp>
make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
shared_ptr<future_async_shared_state<Rp, Fp> >
- h(new future_async_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
+ h(new future_async_shared_state<Rp, Fp>());
+ h->init(boost::forward<Fp>(f));
return BOOST_THREAD_FUTURE<Rp>(h);
}
}
@@ -3602,10 +3530,6 @@ namespace detail {
void operator()() {
try {
that->mark_finished_with_result(f_());
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(...) {
that->mark_exceptional_finish();
}
@@ -3653,10 +3577,6 @@ namespace detail {
try {
f_();
that->mark_finished_with_result();
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(...) {
that->mark_exceptional_finish();
}
@@ -3702,10 +3622,6 @@ namespace detail {
void operator()() {
try {
that->mark_finished_with_result(f_());
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
} catch(...) {
that->mark_exceptional_finish();
}
@@ -3728,9 +3644,12 @@ namespace detail {
ex.submit(boost::move(t));
}
- ~future_executor_shared_state() {
- this->wait(false);
+ virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk)
+ {
+ this->wait(lk, false);
}
+
+ ~future_executor_shared_state() {}
};
////////////////////////////////
@@ -3929,14 +3848,80 @@ namespace detail {
////////////////////////////////
// make_ready_future
////////////////////////////////
- template <typename T>
- BOOST_THREAD_FUTURE<typename decay<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) {
- typedef typename decay<T>::type future_value_type;
+ 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<future_value_type>(value));
+ 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;
@@ -3945,11 +3930,11 @@ namespace detail {
return BOOST_THREAD_MAKE_RV_REF(p.get_future());
}
-#if defined BOOST_THREAD_USES_MOVE
+#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 BOOST_THREAD_MAKE_RV_REF(p.get_future());
+ return p.get_future();
}
#endif
@@ -4038,31 +4023,30 @@ namespace detail
{
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: parent(boost::move(f)),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
}
- void launch_continuation(boost::unique_lock<boost::mutex>& ) {
- this->thr_ = thread(&future_async_continuation_shared_state::run, this);
+
+ void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) {
+ this->thr_ = thread(&future_async_continuation_shared_state::run, that);
}
- static void run(future_async_continuation_shared_state* that) {
+ static void run(shared_ptr<boost::detail::shared_state_base> that_) {
+ future_async_continuation_shared_state* that = dynamic_cast<future_async_continuation_shared_state*>(that_.get());
try {
that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
}
~future_async_continuation_shared_state() {
- this->join();
}
};
@@ -4071,33 +4055,31 @@ namespace detail
{
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: parent(boost::move(f)),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
}
- void launch_continuation(boost::unique_lock<boost::mutex>& ) {
- this->thr_ = thread(&future_async_continuation_shared_state::run, this);
+ void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) {
+ this->thr_ = thread(&future_async_continuation_shared_state::run, that);
}
- static void run(future_async_continuation_shared_state* that) {
+ static void run(shared_ptr<boost::detail::shared_state_base> that_) {
+ future_async_continuation_shared_state* that = dynamic_cast<future_async_continuation_shared_state*>(that_.get());
try {
that->continuation(boost::move(that->parent));
that->mark_finished_with_result();
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
}
- ~future_async_continuation_shared_state() {
- this->join();
- }
+ ~future_async_continuation_shared_state() {}
+
};
/////////////////////////
@@ -4105,12 +4087,16 @@ namespace detail
/////////////////////////
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
- template <typename Ex>
+ template <typename FutureExecutorContinuationSharedState>
struct run_it {
- Ex* that;
+ shared_ptr<boost::detail::shared_state_base> that_;
- run_it(Ex* that) : that (that) {}
- void operator()() { that->run(that); }
+ run_it(shared_ptr<boost::detail::shared_state_base> that) : that_ (that) {}
+ void operator()()
+ {
+ FutureExecutorContinuationSharedState* that = dynamic_cast<FutureExecutorContinuationSharedState*>(that_.get());
+ that->run(that_);
+ }
};
template<typename Ex, typename F, typename Rp, typename Fp>
@@ -4119,34 +4105,37 @@ namespace detail
Ex* ex;
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: ex(&ex), parent(boost::move(f)),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
this->set_executor();
}
- void launch_continuation(boost::unique_lock<boost::mutex>& ) {
- run_it<future_executor_continuation_shared_state> fct(this);
+ void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that ) {
+ relocker relock(lck);
+ run_it<future_executor_continuation_shared_state> fct(that);
ex->submit(fct);
}
- static void run(future_executor_continuation_shared_state* that) {
+ static void run(shared_ptr<boost::detail::shared_state_base> that_) {
+ future_executor_continuation_shared_state* that = dynamic_cast<future_executor_continuation_shared_state*>(that_.get());
try {
that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
}
- ~future_executor_continuation_shared_state() {
- this->wait(false);
+ virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk)
+ {
+ this->wait(lk, false);
}
+
+ ~future_executor_continuation_shared_state() {}
};
template<typename Ex, typename F, typename Fp>
@@ -4155,35 +4144,38 @@ namespace detail
Ex* ex;
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: ex(&ex), parent(boost::move(f)),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
this->set_executor();
}
- void launch_continuation(boost::unique_lock<boost::mutex>& ) {
- run_it<future_executor_continuation_shared_state> fct(this);
+ void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that ) {
+ relocker relock(lck);
+ run_it<future_executor_continuation_shared_state> fct(that);
ex->submit(fct);
}
- static void run(future_executor_continuation_shared_state* that) {
+ static void run(shared_ptr<boost::detail::shared_state_base> that_) {
+ future_executor_continuation_shared_state* that = dynamic_cast<future_executor_continuation_shared_state*>(that_.get());
try {
that->continuation(boost::move(that->parent));
that->mark_finished_with_result();
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
}
- ~future_executor_continuation_shared_state() {
- this->wait(false);
+ virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk)
+ {
+ this->wait(lk, false);
}
+
+ ~future_executor_continuation_shared_state() {}
};
#endif
@@ -4196,32 +4188,29 @@ namespace detail
{
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
: parent(f),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
}
- void launch_continuation(boost::unique_lock<boost::mutex>& ) {
- this->thr_ = thread(&shared_future_async_continuation_shared_state::run, this);
+ void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) {
+ this->thr_ = thread(&shared_future_async_continuation_shared_state::run, that);
}
- static void run(shared_future_async_continuation_shared_state* that) {
+ static void run(shared_ptr<boost::detail::shared_state_base> that_) {
+ shared_future_async_continuation_shared_state* that = dynamic_cast<shared_future_async_continuation_shared_state*>(that_.get());
try {
that->mark_finished_with_result(that->continuation(that->parent));
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
}
- ~shared_future_async_continuation_shared_state() {
- this->join();
- }
+ ~shared_future_async_continuation_shared_state() {}
};
template<typename F, typename Fp>
@@ -4229,33 +4218,30 @@ namespace detail
{
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
: parent(f),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
}
- void launch_continuation(boost::unique_lock<boost::mutex>& ) {
- this->thr_ = thread(&shared_future_async_continuation_shared_state::run, this);
+ void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) {
+ this->thr_ = thread(&shared_future_async_continuation_shared_state::run, that);
}
- static void run(shared_future_async_continuation_shared_state* that) {
+ static void run(shared_ptr<boost::detail::shared_state_base> that_) {
+ shared_future_async_continuation_shared_state* that = dynamic_cast<shared_future_async_continuation_shared_state*>(that_.get());
try {
that->continuation(that->parent);
that->mark_finished_with_result();
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
}
- ~shared_future_async_continuation_shared_state() {
- this->join();
- }
+ ~shared_future_async_continuation_shared_state() {}
};
/////////////////////////
@@ -4269,34 +4255,37 @@ namespace detail
Ex* ex;
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c)
: ex(&ex), parent(f),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
this->set_executor();
}
- void launch_continuation(boost::unique_lock<boost::mutex>& ) {
- run_it<shared_future_executor_continuation_shared_state> fct(this);
+ void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that) {
+ relocker relock(lck);
+ run_it<shared_future_executor_continuation_shared_state> fct(that);
ex->submit(fct);
}
- static void run(shared_future_executor_continuation_shared_state* that) {
+ static void run(shared_ptr<boost::detail::shared_state_base> that_) {
+ shared_future_executor_continuation_shared_state* that = dynamic_cast<shared_future_executor_continuation_shared_state*>(that_.get());
try {
that->mark_finished_with_result(that->continuation(that->parent));
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
}
- ~shared_future_executor_continuation_shared_state() {
- this->wait(false);
+ virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk)
+ {
+ this->wait(lk, false);
}
+
+ ~shared_future_executor_continuation_shared_state() {}
};
template<typename Ex, typename F, typename Fp>
@@ -4305,34 +4294,37 @@ namespace detail
Ex* ex;
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c)
: ex(&ex), parent(f),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
}
- void launch_continuation(boost::unique_lock<boost::mutex>& ) {
- run_it<shared_future_executor_continuation_shared_state> fct(this);
+ void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that) {
+ relocker relock(lck);
+ run_it<shared_future_executor_continuation_shared_state> fct(that);
ex->submit(fct);
}
- static void run(shared_future_executor_continuation_shared_state* that) {
+ static void run(shared_ptr<boost::detail::shared_state_base> that_) {
+ shared_future_executor_continuation_shared_state* that = dynamic_cast<shared_future_executor_continuation_shared_state*>(that_.get());
try {
that->continuation(that->parent);
that->mark_finished_with_result();
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
}
- ~shared_future_executor_continuation_shared_state() {
- this->wait(false);
+ virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk)
+ {
+ this->wait(lk, false);
}
+
+ ~shared_future_executor_continuation_shared_state() {}
};
#endif
//////////////////////////
@@ -4343,15 +4335,21 @@ namespace detail
{
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: parent(boost::move(f)),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
this->set_deferred();
}
- virtual void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>&lk, shared_ptr<shared_state_base> ) {
+ if (this->is_deferred_) {
+ this->is_deferred_=false;
+ this->execute(lk);
+ }
}
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
@@ -4373,15 +4371,23 @@ namespace detail
{
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: parent(boost::move(f)),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
this->set_deferred();
}
- virtual void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ ~future_deferred_continuation_shared_state() {
+ }
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) {
+ if (this->is_deferred_) {
+ this->is_deferred_=false;
+ this->execute(lk);
+ }
}
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
@@ -4406,15 +4412,21 @@ namespace detail
{
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
: parent(f),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
this->set_deferred();
}
- virtual void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) {
+ if (this->is_deferred_) {
+ this->is_deferred_=false;
+ this->execute(lk);
+ }
}
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
@@ -4436,15 +4448,21 @@ namespace detail
{
F parent;
Fp continuation;
+ shared_ptr<shared_state_base> centinel;
public:
shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
: parent(f),
- continuation(boost::move(c)) {
+ continuation(boost::move(c)),
+ centinel(parent.future_) {
this->set_deferred();
}
- virtual void launch_continuation(boost::unique_lock<boost::mutex>& ) {
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) {
+ if (this->is_deferred_) {
+ this->is_deferred_=false;
+ this->execute(lk);
+ }
}
virtual void execute(boost::unique_lock<boost::mutex>& lck) {
@@ -4471,7 +4489,9 @@ namespace detail
BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) {
shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> >
h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
+ lock.lock();
h->parent.future_->set_continuation_ptr(h, lock);
+ lock.unlock();
return BOOST_THREAD_FUTURE<Rp>(h);
}
@@ -4485,7 +4505,9 @@ namespace detail
BOOST_THREAD_FWD_REF(Fp) c) {
shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> >
h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
+ lock.lock();
h->parent.future_->set_continuation_ptr(h, lock);
+ lock.unlock();
return BOOST_THREAD_FUTURE<Rp>(h);
}
@@ -4502,7 +4524,9 @@ namespace detail
BOOST_THREAD_FWD_REF(Fp) c) {
shared_ptr<future_executor_continuation_shared_state<Ex,F,Rp, Fp> >
h(new future_executor_continuation_shared_state<Ex, F,Rp, Fp>(ex, boost::move(f), boost::forward<Fp>(c)));
+ lock.lock();
h->parent.future_->set_continuation_ptr(h, lock);
+ lock.unlock();
return BOOST_THREAD_FUTURE<Rp>(h);
}
@@ -4518,7 +4542,10 @@ namespace detail
F f, BOOST_THREAD_FWD_REF(Fp) c) {
shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Fp> >
h(new shared_future_deferred_continuation_shared_state<F, Rp, Fp>(f, boost::forward<Fp>(c)));
+ lock.lock();
h->parent.future_->set_continuation_ptr(h, lock);
+ lock.unlock();
+
return BOOST_THREAD_FUTURE<Rp>(h);
}
////////////////////////////////
@@ -4531,7 +4558,9 @@ namespace detail
BOOST_THREAD_FWD_REF(Fp) c) {
shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Fp> >
h(new shared_future_async_continuation_shared_state<F,Rp, Fp>(f, boost::forward<Fp>(c)));
+ lock.lock();
h->parent.future_->set_continuation_ptr(h, lock);
+ lock.unlock();
return BOOST_THREAD_FUTURE<Rp>(h);
}
@@ -4546,7 +4575,9 @@ namespace detail
BOOST_THREAD_FWD_REF(Fp) c) {
shared_ptr<shared_future_executor_continuation_shared_state<Ex, F, Rp, Fp> >
h(new shared_future_executor_continuation_shared_state<Ex, F, Rp, Fp>(ex, f, boost::forward<Fp>(c)));
+ lock.lock();
h->parent.future_->set_continuation_ptr(h, lock);
+ lock.unlock();
return BOOST_THREAD_FUTURE<Rp>(h);
}
@@ -4567,14 +4598,18 @@ namespace detail
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (underlying_cast<int>(policy) & int(launch::async)) {
+ lock.unlock();
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
lock, boost::move(*this), boost::forward<F>(func)
)));
} else if (underlying_cast<int>(policy) & int(launch::deferred)) {
+ this->future_->wait_internal(lock);
+ lock.unlock();
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
lock, boost::move(*this), boost::forward<F>(func)
)));
} else {
+ lock.unlock();
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
lock, boost::move(*this), boost::forward<F>(func)
)));
@@ -4589,6 +4624,7 @@ namespace detail
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ lock.unlock();
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type, F>(ex,
lock, boost::move(*this), boost::forward<F>(func)
)));
@@ -4603,6 +4639,77 @@ namespace detail
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) {
+ lock.unlock();
+ return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ );
+ } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) {
+ this->future_->wait_internal(lock);
+ lock.unlock();
+ return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ );
+ } else {
+ lock.unlock();
+ return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ );
+ }
+ }
+
+ ////////////////////////////////
+ // template<typename 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(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());
+
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ if (underlying_cast<int>(policy) & int(launch::async)) {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ )));
+ } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ )));
+ } else {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ )));
+ }
+ }
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ template <typename 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());
+
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type, F>(ex,
+ lock, boost::move(*this), boost::forward<F>(func)
+ )));
+ }
+#endif
+ template <typename 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) {
+ 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());
+
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) {
return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
lock, boost::move(*this), boost::forward<F>(func)
);
@@ -4618,6 +4725,11 @@ namespace detail
}
}
+ ////////////////////////////////
+ // 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>
@@ -4627,16 +4739,19 @@ namespace detail
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)) {
+ lock.unlock();
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
lock, *this, boost::forward<F>(func)
)));
} else if (underlying_cast<int>(policy) & int(launch::deferred)) {
+ this->future_->wait_internal(lock);
+ lock.unlock();
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
lock, *this, boost::forward<F>(func)
)));
} else {
+ lock.unlock();
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
lock, *this, boost::forward<F>(func)
)));
@@ -4652,6 +4767,7 @@ namespace detail
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ lock.unlock();
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type, F>(ex,
lock, *this, boost::forward<F>(func)
)));
@@ -4668,13 +4784,16 @@ namespace detail
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) {
+ lock.unlock();
return boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
lock, *this, boost::forward<F>(func));
} else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) {
this->future_->wait_internal(lock);
+ lock.unlock();
return boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
lock, *this, boost::forward<F>(func));
} else {
+ lock.unlock();
return boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
lock, *this, boost::forward<F>(func));
}
@@ -4704,7 +4823,7 @@ namespace detail
: value_(v)
{}
- T operator()(BOOST_THREAD_FUTURE<T> fut) {
+ T operator()(BOOST_THREAD_FUTURE<T> fut) const {
return fut.get_or(value_);
}
@@ -4751,14 +4870,21 @@ namespace detail
return boost::move(r);
}
- virtual void wait(bool ) { // todo see if rethrow must be used
- boost::unique_lock<boost::mutex> lk(this->mutex);
+ virtual void wait(boost::unique_lock<boost::mutex>& lk, bool ) { // todo see if rethrow must be used
parent_value(lk).wait();
}
- virtual Rp get() {
- boost::unique_lock<boost::mutex> lk(this->mutex);
+ virtual Rp get(boost::unique_lock<boost::mutex>& lk) {
return parent_value(lk).get();
}
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ typedef shared_ptr<shared_state_base> continuation_ptr_type;
+
+ virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
+ {
+ boost::unique_lock<boost::mutex> lk(parent.future_->mutex);
+ parent.future_->set_continuation_ptr(continuation, lk);
+ }
+#endif
};
template <class F, class Rp>
@@ -4766,7 +4892,9 @@ namespace detail
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)));
+ lock.lock();
h->parent.future_->set_continuation_ptr(h, lock);
+ lock.unlock();
return BOOST_THREAD_FUTURE<Rp>(h);
}
}
@@ -4781,6 +4909,7 @@ namespace detail
{
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ lock.unlock();
return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
}
#endif
@@ -4807,14 +4936,11 @@ namespace detail
typedef typename F::value_type value_type;
vector_type vec_;
- static void run(future_when_all_vector_shared_state* that) {
+ static void run(shared_ptr<boost::detail::shared_state_base> that_) {
+ future_when_all_vector_shared_state* that = dynamic_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_));
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -4833,10 +4959,10 @@ namespace detail
void init() {
if (! run_deferred())
{
- future_when_all_vector_shared_state::run(this);
+ future_when_all_vector_shared_state::run(this->shared_from_this());
return;
}
- this->thr_ = thread(&future_when_all_vector_shared_state::run, this);
+ this->thr_ = thread(&future_when_all_vector_shared_state::run, this->shared_from_this());
}
public:
@@ -4844,13 +4970,11 @@ namespace detail
future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
: vec_(std::make_move_iterator(first), std::make_move_iterator(last))
{
- init();
}
future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
: vec_(boost::move(v))
{
- init();
}
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -4862,12 +4986,10 @@ namespace detail
vec_.push_back(boost::forward<T>(futures)),'0'
)..., '0'
}; //second part of magic unpacker
- init();
}
#endif
- ~future_when_all_vector_shared_state() {
- this->join();
- }
+
+ ~future_when_all_vector_shared_state() {}
};
////////////////////////////////
@@ -4880,15 +5002,12 @@ namespace detail
typedef typename F::value_type value_type;
vector_type vec_;
- static void run(future_when_any_vector_shared_state* that)
+ static void run(shared_ptr<boost::detail::shared_state_base> that_)
{
+ future_when_any_vector_shared_state* that = dynamic_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_));
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -4906,11 +5025,11 @@ namespace detail
void init() {
if (run_deferred())
{
- future_when_any_vector_shared_state::run(this);
+ future_when_any_vector_shared_state::run(this->shared_from_this());
return;
}
- this->thr_ = thread(&future_when_any_vector_shared_state::run, this);
+ this->thr_ = thread(&future_when_any_vector_shared_state::run, this->shared_from_this());
}
public:
@@ -4918,13 +5037,11 @@ namespace detail
future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
: vec_(std::make_move_iterator(first), std::make_move_iterator(last))
{
- init();
}
future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
: vec_(boost::move(v))
{
- init();
}
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -4940,13 +5057,10 @@ namespace detail
)...,
'0'
}; //second part of magic unpacker
- init();
}
#endif
- ~future_when_any_vector_shared_state() {
- this->join();
- }
+ ~future_when_any_vector_shared_state() {}
};
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -4987,16 +5101,13 @@ namespace detail
Tuple tup_;
typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
- static void run(future_when_all_tuple_shared_state* that) {
+ static void run(shared_ptr<boost::detail::shared_state_base> that_) {
+ future_when_all_tuple_shared_state* that = dynamic_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_));
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -5018,23 +5129,21 @@ namespace detail
void init() {
if (! run_deferred())
{
- future_when_all_tuple_shared_state::run(this);
+ future_when_all_tuple_shared_state::run(this->shared_from_this());
return;
}
- this->thr_ = thread(&future_when_all_tuple_shared_state::run, this);
+ this->thr_ = thread(&future_when_all_tuple_shared_state::run, this->shared_from_this());
}
public:
template< typename F, typename ...Fs>
future_when_all_tuple_shared_state(values_tag, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures) :
tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
{
- init();
- }
- ~future_when_all_tuple_shared_state() {
- this->join();
}
+ ~future_when_all_tuple_shared_state() {}
+
};
@@ -5060,17 +5169,14 @@ namespace detail
Tuple tup_;
typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
- static void run(future_when_any_tuple_shared_state* that)
+ static void run(shared_ptr<boost::detail::shared_state_base> that_)
{
+ future_when_any_tuple_shared_state* that = dynamic_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_));
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- } catch(thread_interrupted& ) {
- that->mark_interrupted_finish();
-#endif
} catch(...) {
that->mark_exceptional_finish();
}
@@ -5089,11 +5195,11 @@ namespace detail
void init() {
if (run_deferred())
{
- future_when_any_tuple_shared_state::run(this);
+ future_when_any_tuple_shared_state::run(this->shared_from_this());
return;
}
- this->thr_ = thread(&future_when_any_tuple_shared_state::run, this);
+ this->thr_ = thread(&future_when_any_tuple_shared_state::run, this->shared_from_this());
}
public:
@@ -5103,12 +5209,9 @@ namespace detail
) :
tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
{
- init();
}
- ~future_when_any_tuple_shared_state() {
- this->join();
- }
+ ~future_when_any_tuple_shared_state() {}
};
#endif
@@ -5126,6 +5229,7 @@ namespace detail
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);
}
@@ -5142,6 +5246,7 @@ namespace detail
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
@@ -5158,6 +5263,7 @@ namespace detail
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);
}
@@ -5174,6 +5280,7 @@ namespace detail
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
diff --git a/boost/thread/futures/future_error.hpp b/boost/thread/futures/future_error.hpp
new file mode 100644
index 0000000000..6212deece3
--- /dev/null
+++ b/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/boost/thread/future_error_code.hpp b/boost/thread/futures/future_error_code.hpp
index 6fe95541b7..7c8b6f2696 100644
--- a/boost/thread/future_error_code.hpp
+++ b/boost/thread/futures/future_error_code.hpp
@@ -1,12 +1,12 @@
// (C) Copyright 2008-10 Anthony Williams
-// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+// (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_FUTURE_ERROR_CODE_HPP
-#define BOOST_THREAD_FUTURE_ERROR_CODE_HPP
+#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>
diff --git a/boost/thread/futures/future_status.hpp b/boost/thread/futures/future_status.hpp
new file mode 100644
index 0000000000..383ac4673c
--- /dev/null
+++ b/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/boost/thread/futures/is_future_type.hpp b/boost/thread/futures/is_future_type.hpp
new file mode 100644
index 0000000000..df7a680faa
--- /dev/null
+++ b/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/boost/thread/futures/launch.hpp b/boost/thread/futures/launch.hpp
new file mode 100644
index 0000000000..b457020aaa
--- /dev/null
+++ b/boost/thread/futures/launch.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_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
+ any = async | deferred
+ }
+ BOOST_SCOPED_ENUM_DECLARE_END(launch)
+}
+
+#endif // header
diff --git a/boost/thread/futures/wait_for_all.hpp b/boost/thread/futures/wait_for_all.hpp
new file mode 100644
index 0000000000..90cc2b77cb
--- /dev/null
+++ b/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/boost/thread/futures/wait_for_any.hpp b/boost/thread/futures/wait_for_any.hpp
new file mode 100644
index 0000000000..b869a4318a
--- /dev/null
+++ b/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/boost/thread/latch.hpp b/boost/thread/latch.hpp
index 6caf521910..8fa9d963de 100644
--- a/boost/thread/latch.hpp
+++ b/boost/thread/latch.hpp
@@ -27,7 +27,7 @@ namespace boost
/// Effect: Decrement the count. Unlocks the lock and notify anyone waiting if we reached zero.
/// Returns: true if count_ reached the value 0.
/// @ThreadSafe ensured by the @c lk parameter
- bool count_down(unique_lock<mutex> &lk)
+ bool count_down(unique_lock<mutex> &)
/// pre_condition (count_ > 0)
{
BOOST_ASSERT(count_ > 0);
diff --git a/boost/thread/pthread/mutex.hpp b/boost/thread/pthread/mutex.hpp
index 3e9af2a833..9ac808b6f4 100644
--- a/boost/thread/pthread/mutex.hpp
+++ b/boost/thread/pthread/mutex.hpp
@@ -1,12 +1,13 @@
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
-// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+// (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>
@@ -26,13 +27,12 @@
#endif
#include <boost/thread/detail/delete.hpp>
-#ifdef _POSIX_TIMEOUTS
-#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
+#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
-#endif
#include <boost/config/abi_prefix.hpp>
@@ -123,10 +123,12 @@ namespace boost
void unlock()
{
int res = posix::pthread_mutex_unlock(&m);
- if (res)
- {
- boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
- }
+ (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()
@@ -219,10 +221,12 @@ namespace boost
void unlock()
{
int res = posix::pthread_mutex_unlock(&m);
- if (res)
- {
- boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
- }
+ (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()
diff --git a/boost/thread/pthread/recursive_mutex.hpp b/boost/thread/pthread/recursive_mutex.hpp
index 9330d77de9..4caae0b5df 100644
--- a/boost/thread/pthread/recursive_mutex.hpp
+++ b/boost/thread/pthread/recursive_mutex.hpp
@@ -27,16 +27,19 @@
#endif
#include <boost/thread/detail/delete.hpp>
-#ifdef _POSIX_TIMEOUTS
-#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L
+#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
-#endif
+#if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
+ || defined __ANDROID__
+#define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
+#endif
-#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
+#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#endif
@@ -48,7 +51,7 @@ namespace boost
{
private:
pthread_mutex_t m;
-#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
+#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_cond_t cond;
bool is_locked;
pthread_t owner;
@@ -58,7 +61,7 @@ namespace boost
BOOST_THREAD_NO_COPYABLE(recursive_mutex)
recursive_mutex()
{
-#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
+#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr);
@@ -99,12 +102,12 @@ namespace boost
~recursive_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
-#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
+#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
-#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
+#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
diff --git a/boost/thread/pthread/thread_data.hpp b/boost/thread/pthread/thread_data.hpp
index 801f470b46..dc8ba0fb1b 100644
--- a/boost/thread/pthread/thread_data.hpp
+++ b/boost/thread/pthread/thread_data.hpp
@@ -25,7 +25,9 @@
#include <utility>
#if defined(__ANDROID__)
-#include <asm/page.h> // http://code.google.com/p/android/issues/detail?id=39983
+# ifndef PAGE_SIZE
+# define PAGE_SIZE 4096
+# endif
#endif
#include <pthread.h>
@@ -113,8 +115,13 @@ namespace boost
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;
@@ -134,8 +141,10 @@ namespace boost
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
@@ -250,7 +259,7 @@ namespace boost
inline
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
- return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns));
+ return boost::this_thread::no_interruption_point::hiden::sleep_for(boost::detail::to_timespec(ns));
}
#endif
#endif // BOOST_THREAD_USES_CHRONO
diff --git a/boost/thread/sync_bounded_queue.hpp b/boost/thread/sync_bounded_queue.hpp
index 63afb614ee..2024d6602e 100644
--- a/boost/thread/sync_bounded_queue.hpp
+++ b/boost/thread/sync_bounded_queue.hpp
@@ -11,712 +11,6 @@
//
//////////////////////////////////////////////////////////////////////////////
-#include <boost/thread/detail/config.hpp>
-#include <boost/thread/condition_variable.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/detail/move.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/thread/concurrent_queues/queue_op_status.hpp>
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
-#include <boost/smart_ptr/shared_ptr.hpp>
-#include <boost/smart_ptr/make_shared.hpp>
-#endif
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost
-{
-
- template <typename ValueType>
- class sync_bounded_queue
- {
- public:
- typedef ValueType value_type;
- typedef std::size_t size_type;
-
- // Constructors/Assignment/Destructors
- BOOST_THREAD_NO_COPYABLE(sync_bounded_queue)
- explicit sync_bounded_queue(size_type max_elems);
- template <typename Range>
- sync_bounded_queue(size_type max_elems, Range range);
- ~sync_bounded_queue();
-
- // Observers
- inline bool empty() const;
- inline bool full() const;
- inline size_type capacity() const;
- inline size_type size() const;
- inline bool closed() const;
-
- // Modifiers
- inline void close();
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- inline void push(const value_type& x);
- inline void push(BOOST_THREAD_RV_REF(value_type) x);
- inline bool try_push(const value_type& x);
- inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
- inline bool try_push(no_block_tag, const value_type& x);
- inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
-#endif
- inline void push_back(const value_type& x);
- inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
- inline queue_op_status try_push_back(const value_type& x);
- inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
- inline queue_op_status nonblocking_push_back(const value_type& x);
- inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
- inline queue_op_status wait_push_back(const value_type& x);
- inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
-
- // Observers/Modifiers
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- inline void pull(value_type&);
- // enable_if is_nothrow_copy_movable<value_type>
- inline value_type pull();
- inline shared_ptr<ValueType> ptr_pull();
- inline bool try_pull(value_type&);
- inline bool try_pull(no_block_tag,value_type&);
- inline shared_ptr<ValueType> try_pull();
-#endif
- inline void pull_front(value_type&);
- // enable_if is_nothrow_copy_movable<value_type>
- inline value_type pull_front();
- inline queue_op_status try_pull_front(value_type&);
- inline queue_op_status nonblocking_pull_front(value_type&);
-
- inline queue_op_status wait_pull_front(ValueType& elem);
-
- private:
- mutable mutex mtx_;
- condition_variable not_empty_;
- condition_variable not_full_;
- size_type waiting_full_;
- size_type waiting_empty_;
- value_type* data_;
- size_type in_;
- size_type out_;
- size_type capacity_;
- bool closed_;
-
- inline size_type inc(size_type idx) const BOOST_NOEXCEPT
- {
- return (idx + 1) % capacity_;
- }
-
- inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
- {
- return in_ == out_;
- }
- inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
- {
- return in_ == out_;
- }
- inline bool full(unique_lock<mutex>& ) const BOOST_NOEXCEPT
- {
- return (inc(in_) == out_);
- }
- inline bool full(lock_guard<mutex>& ) const BOOST_NOEXCEPT
- {
- return (inc(in_) == out_);
- }
- inline size_type capacity(lock_guard<mutex>& ) const BOOST_NOEXCEPT
- {
- return capacity_-1;
- }
- inline size_type size(lock_guard<mutex>& lk) const BOOST_NOEXCEPT
- {
- if (full(lk)) return capacity(lk);
- return ((out_+capacity(lk)-in_) % capacity(lk));
- }
-
- inline void throw_if_closed(unique_lock<mutex>&);
- inline bool closed(unique_lock<mutex>&) const;
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
- inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
- inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
- inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
-#endif
- inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
- inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
- inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
-
- inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
- inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
- inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
-
- inline void wait_until_not_empty(unique_lock<mutex>& lk);
- inline void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
- inline size_type wait_until_not_full(unique_lock<mutex>& lk);
- inline size_type wait_until_not_full(unique_lock<mutex>& lk, bool&);
-
-
- inline void notify_not_empty_if_needed(unique_lock<mutex>& lk)
- {
- if (waiting_empty_ > 0)
- {
- --waiting_empty_;
- lk.unlock();
- not_empty_.notify_one();
- }
- }
- inline void notify_not_full_if_needed(unique_lock<mutex>& lk)
- {
- if (waiting_full_ > 0)
- {
- --waiting_full_;
- lk.unlock();
- not_full_.notify_one();
- }
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- inline void pull(value_type& elem, unique_lock<mutex>& lk)
- {
- elem = boost::move(data_[out_]);
- out_ = inc(out_);
- notify_not_full_if_needed(lk);
- }
- inline value_type pull(unique_lock<mutex>& lk)
- {
- value_type elem = boost::move(data_[out_]);
- out_ = inc(out_);
- notify_not_full_if_needed(lk);
- return boost::move(elem);
- }
- inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& lk)
- {
- shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_[out_]));
- out_ = inc(out_);
- notify_not_full_if_needed(lk);
- return res;
- }
-#endif
- inline void pull_front(value_type& elem, unique_lock<mutex>& lk)
- {
- elem = boost::move(data_[out_]);
- out_ = inc(out_);
- notify_not_full_if_needed(lk);
- }
- inline value_type pull_front(unique_lock<mutex>& lk)
- {
- value_type elem = boost::move(data_[out_]);
- out_ = inc(out_);
- notify_not_full_if_needed(lk);
- return boost::move(elem);
- }
-
- inline void set_in(size_type in, unique_lock<mutex>& lk)
- {
- in_ = in;
- notify_not_empty_if_needed(lk);
- }
-
- inline void push_at(const value_type& elem, size_type in_p_1, unique_lock<mutex>& lk)
- {
- data_[in_] = elem;
- set_in(in_p_1, lk);
- }
-
- inline void push_at(BOOST_THREAD_RV_REF(value_type) elem, size_type in_p_1, unique_lock<mutex>& lk)
- {
- data_[in_] = boost::move(elem);
- set_in(in_p_1, lk);
- }
- };
-
- template <typename ValueType>
- sync_bounded_queue<ValueType>::sync_bounded_queue(typename sync_bounded_queue<ValueType>::size_type max_elems) :
- waiting_full_(0), waiting_empty_(0), data_(new value_type[max_elems + 1]), in_(0), out_(0), capacity_(max_elems + 1),
- closed_(false)
- {
- BOOST_ASSERT_MSG(max_elems >= 1, "number of elements must be > 1");
- }
-
-// template <typename ValueType>
-// template <typename Range>
-// sync_bounded_queue<ValueType>::sync_bounded_queue(size_type max_elems, Range range) :
-// waiting_full_(0), waiting_empty_(0), data_(new value_type[max_elems + 1]), in_(0), out_(0), capacity_(max_elems + 1),
-// closed_(false)
-// {
-// BOOST_ASSERT_MSG(max_elems >= 1, "number of elements must be > 1");
-// BOOST_ASSERT_MSG(max_elems == size(range), "number of elements must match range's size");
-// try
-// {
-// typedef typename Range::iterator iterator_t;
-// iterator_t first = boost::begin(range);
-// iterator_t end = boost::end(range);
-// size_type in = 0;
-// for (iterator_t cur = first; cur != end; ++cur, ++in)
-// {
-// data_[in] = *cur;
-// }
-// set_in(in);
-// }
-// catch (...)
-// {
-// delete[] data_;
-// }
-// }
-
- template <typename ValueType>
- sync_bounded_queue<ValueType>::~sync_bounded_queue()
- {
- delete[] data_;
- }
-
- template <typename ValueType>
- void sync_bounded_queue<ValueType>::close()
- {
- {
- lock_guard<mutex> lk(mtx_);
- closed_ = true;
- }
- not_empty_.notify_all();
- not_full_.notify_all();
- }
-
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::closed() const
- {
- lock_guard<mutex> lk(mtx_);
- return closed_;
- }
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::closed(unique_lock<mutex>& ) const
- {
- return closed_;
- }
-
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::empty() const
- {
- lock_guard<mutex> lk(mtx_);
- return empty(lk);
- }
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::full() const
- {
- lock_guard<mutex> lk(mtx_);
- return full(lk);
- }
-
- template <typename ValueType>
- typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::capacity() const
- {
- lock_guard<mutex> lk(mtx_);
- return capacity(lk);
- }
-
- template <typename ValueType>
- typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::size() const
- {
- lock_guard<mutex> lk(mtx_);
- return size(lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
- {
- if (empty(lk))
- {
- throw_if_closed(lk);
- return false;
- }
- pull(elem, lk);
- return true;
- }
- template <typename ValueType>
- shared_ptr<ValueType> sync_bounded_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
- {
- if (empty(lk))
- {
- throw_if_closed(lk);
- return shared_ptr<ValueType>();
- }
- return ptr_pull(lk);
- }
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::try_pull(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_pull(elem, lk);
- }
-#endif
-
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
- {
- if (empty(lk))
- {
- if (closed(lk)) return queue_op_status::closed;
- return queue_op_status::empty;
- }
- pull_front(elem, lk);
- return queue_op_status::success;
- }
-
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::try_pull_front(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_pull_front(elem, lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock())
- {
- return false;
- }
- return try_pull(elem, lk);
- }
- template <typename ValueType>
- boost::shared_ptr<ValueType> sync_bounded_queue<ValueType>::try_pull()
- {
- unique_lock<mutex> lk(mtx_);
- return try_pull(lk);
- }
-#endif
-
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::nonblocking_pull_front(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock())
- {
- return queue_op_status::busy;
- }
- return try_pull_front(elem, lk);
- }
-
- template <typename ValueType>
- void sync_bounded_queue<ValueType>::throw_if_closed(unique_lock<mutex>&)
- {
- if (closed_)
- {
- BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
- }
- }
-
- template <typename ValueType>
- void sync_bounded_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk)
- {
- for (;;)
- {
- if (out_ != in_) break;
- throw_if_closed(lk);
- ++waiting_empty_;
- not_empty_.wait(lk);
- }
- }
- template <typename ValueType>
- void sync_bounded_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk, bool & closed)
- {
- for (;;)
- {
- if (out_ != in_) break;
- if (closed_) {closed=true; return;}
- ++waiting_empty_;
- not_empty_.wait(lk);
- }
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- void sync_bounded_queue<ValueType>::pull(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk);
- pull(elem, lk);
- }
-// template <typename ValueType>
-// void sync_bounded_queue<ValueType>::pull(ValueType& elem, bool & closed)
-// {
-// unique_lock<mutex> lk(mtx_);
-// wait_until_not_empty(lk, closed);
-// if (closed) {return;}
-// pull(elem, lk);
-// }
-
- // enable if ValueType is nothrow movable
- template <typename ValueType>
- ValueType sync_bounded_queue<ValueType>::pull()
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk);
- return pull(lk);
- }
- template <typename ValueType>
- boost::shared_ptr<ValueType> sync_bounded_queue<ValueType>::ptr_pull()
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk);
- return ptr_pull(lk);
- }
-
-#endif
-
- template <typename ValueType>
- void sync_bounded_queue<ValueType>::pull_front(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk);
- pull_front(elem, lk);
- }
-
- // enable if ValueType is nothrow movable
- template <typename ValueType>
- ValueType sync_bounded_queue<ValueType>::pull_front()
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk);
- return pull_front(lk);
- }
-
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
- {
- if (empty(lk) && closed(lk)) {return queue_op_status::closed;}
- wait_until_not_empty(lk);
- pull_front(elem, lk);
- return queue_op_status::success;
- }
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return wait_pull_front(elem, lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
- {
- throw_if_closed(lk);
- size_type in_p_1 = inc(in_);
- if (in_p_1 == out_) // full()
- {
- return false;
- }
- push_at(elem, in_p_1, lk);
- return true;
- }
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::try_push(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_push(elem, lk);
- }
-
-#endif
-
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
- {
- if (closed(lk)) return queue_op_status::closed;
- size_type in_p_1 = inc(in_);
- if (in_p_1 == out_) // full()
- {
- return queue_op_status::full;
- }
- push_at(elem, in_p_1, lk);
- return queue_op_status::success;
- }
-
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::try_push_back(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_push_back(elem, lk);
- }
-
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
- {
- if (closed(lk)) return queue_op_status::closed;
- push_at(elem, wait_until_not_full(lk), lk);
- return queue_op_status::success;
- }
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::wait_push_back(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return wait_push_back(elem, lk);
- }
-
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock()) return false;
- return try_push(elem, lk);
- }
-#endif
-
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::nonblocking_push_back(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock()) return queue_op_status::busy;
- return try_push_back(elem, lk);
- }
-
- template <typename ValueType>
- typename sync_bounded_queue<ValueType>::size_type sync_bounded_queue<ValueType>::wait_until_not_full(unique_lock<mutex>& lk)
- {
- for (;;)
- {
- throw_if_closed(lk);
- size_type in_p_1 = inc(in_);
- if (in_p_1 != out_) // ! full()
- {
- return in_p_1;
- }
- ++waiting_full_;
- not_full_.wait(lk);
- }
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- void sync_bounded_queue<ValueType>::push(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- push_at(elem, wait_until_not_full(lk), lk);
- }
-#endif
- template <typename ValueType>
- void sync_bounded_queue<ValueType>::push_back(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- push_at(elem, wait_until_not_full(lk), lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
- {
- throw_if_closed(lk);
- size_type in_p_1 = inc(in_);
- if (in_p_1 == out_) // full()
- {
- return false;
- }
- push_at(boost::move(elem), in_p_1, lk);
- return true;
- }
-
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_push(boost::move(elem), lk);
- }
-#endif
-
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
- {
- if (closed(lk)) return queue_op_status::closed;
- size_type in_p_1 = inc(in_);
- if (in_p_1 == out_) // full()
- {
- return queue_op_status::full;
- }
- push_at(boost::move(elem), in_p_1, lk);
- return queue_op_status::success;
- }
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_push_back(boost::move(elem), lk);
- }
-
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
- {
- if (closed(lk)) return queue_op_status::closed;
- push_at(boost::move(elem), wait_until_not_full(lk), lk);
- return queue_op_status::success;
- }
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_push_back(boost::move(elem), lk);
- }
-
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_bounded_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock())
- {
- return false;
- }
- return try_push(boost::move(elem), lk);
- }
-#endif
- template <typename ValueType>
- queue_op_status sync_bounded_queue<ValueType>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock())
- {
- return queue_op_status::busy;
- }
- return try_push_back(boost::move(elem), lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- void sync_bounded_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_);
- push_at(boost::move(elem), wait_until_not_full(lk), lk);
- }
-#endif
- template <typename ValueType>
- void sync_bounded_queue<ValueType>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_);
- push_at(boost::move(elem), wait_until_not_full(lk), lk);
- }
-
- template <typename ValueType>
- sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
- {
- sbq.push_back(boost::move(elem));
- return sbq;
- }
-
- template <typename ValueType>
- sync_bounded_queue<ValueType>& operator<<(sync_bounded_queue<ValueType>& sbq, ValueType const&elem)
- {
- sbq.push_back(elem);
- return sbq;
- }
-
- template <typename ValueType>
- sync_bounded_queue<ValueType>& operator>>(sync_bounded_queue<ValueType>& sbq, ValueType &elem)
- {
- sbq.pull_front(elem);
- return sbq;
- }
-
-}
-
-#include <boost/config/abi_suffix.hpp>
+#include <boost/thread/concurrent_queues/sync_bounded_queue.hpp>
#endif
diff --git a/boost/thread/sync_queue.hpp b/boost/thread/sync_queue.hpp
index 5037e909ed..0d9334b478 100644
--- a/boost/thread/sync_queue.hpp
+++ b/boost/thread/sync_queue.hpp
@@ -11,653 +11,6 @@
//
//////////////////////////////////////////////////////////////////////////////
-#include <boost/thread/detail/config.hpp>
-#include <boost/thread/condition_variable.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/detail/move.hpp>
-#include <boost/thread/concurrent_queues/queue_op_status.hpp>
-
-#include <boost/throw_exception.hpp>
-#include <boost/smart_ptr/shared_ptr.hpp>
-#include <boost/smart_ptr/make_shared.hpp>
-
-#include <boost/thread/csbl/deque.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost
-{
-
- template <typename ValueType>
- class sync_queue
- {
- public:
- typedef ValueType value_type;
- typedef csbl::deque<ValueType> underlying_queue_type;
- typedef std::size_t size_type;
- typedef queue_op_status op_status;
-
- // Constructors/Assignment/Destructors
- BOOST_THREAD_NO_COPYABLE(sync_queue)
- inline sync_queue();
- //template <typename Range>
- //inline explicit sync_queue(Range range);
- inline ~sync_queue();
-
- // Observers
- inline bool empty() const;
- inline bool full() const;
- inline size_type size() const;
- inline bool closed() const;
-
- // Modifiers
- inline void close();
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- inline void push(const value_type& x);
- inline bool try_push(const value_type& x);
- inline bool try_push(no_block_tag, const value_type& x);
- inline void push(BOOST_THREAD_RV_REF(value_type) x);
- inline bool try_push(BOOST_THREAD_RV_REF(value_type) x);
- inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x);
-#endif
- inline void push_back(const value_type& x);
- inline queue_op_status try_push_back(const value_type& x);
- inline queue_op_status nonblocking_push_back(const value_type& x);
- inline queue_op_status wait_push_back(const value_type& x);
- inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
- inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
- inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
- inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
-
-
- // Observers/Modifiers
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- inline void pull(value_type&);
- inline void pull(ValueType& elem, bool & closed);
- // enable_if is_nothrow_copy_movable<value_type>
- inline value_type pull();
- inline shared_ptr<ValueType> ptr_pull();
-#endif
- inline void pull_front(value_type&);
- // enable_if is_nothrow_copy_movable<value_type>
- inline value_type pull_front();
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- inline bool try_pull(value_type&);
- inline bool try_pull(no_block_tag,value_type&);
- inline shared_ptr<ValueType> try_pull();
-#endif
- inline queue_op_status try_pull_front(value_type&);
- inline queue_op_status nonblocking_pull_front(value_type&);
- inline queue_op_status wait_pull_front(ValueType& elem);
-
- inline underlying_queue_type underlying_queue() {
- lock_guard<mutex> lk(mtx_);
- waiting_empty_ = 0;
- return boost::move(data_);
- }
-
- private:
- mutable mutex mtx_;
- condition_variable not_empty_;
- size_type waiting_empty_;
- underlying_queue_type data_;
- bool closed_;
-
- inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
- {
- return data_.empty();
- }
- inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
- {
- return data_.empty();
- }
-
- inline size_type size(lock_guard<mutex>& ) const BOOST_NOEXCEPT
- {
- return data_.size();
- }
-
- inline void throw_if_closed(unique_lock<mutex>&);
- inline bool closed(unique_lock<mutex>& lk) const;
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- inline bool try_pull(value_type& x, unique_lock<mutex>& lk);
- inline bool try_push(const value_type& x, unique_lock<mutex>& lk);
- inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
- inline shared_ptr<value_type> try_pull(unique_lock<mutex>& lk);
-#endif
- inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
- inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
- inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
- inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
- inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
- inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
-
- inline void wait_until_not_empty(unique_lock<mutex>& lk);
- inline void wait_until_not_empty(unique_lock<mutex>& lk, bool&);
-
- inline void notify_not_empty_if_needed(unique_lock<mutex>& lk)
- {
- if (waiting_empty_ > 0)
- {
- --waiting_empty_;
- lk.unlock();
- not_empty_.notify_one();
- }
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- inline void pull(value_type& elem, unique_lock<mutex>& )
- {
- elem = boost::move(data_.front());
- data_.pop_front();
- }
- inline value_type pull(unique_lock<mutex>& )
- {
- value_type e = boost::move(data_.front());
- data_.pop_front();
- return boost::move(e);
- }
- inline boost::shared_ptr<value_type> ptr_pull(unique_lock<mutex>& )
- {
- shared_ptr<value_type> res = make_shared<value_type>(boost::move(data_.front()));
- data_.pop_front();
- return res;
- }
-#endif
- inline void pull_front(value_type& elem, unique_lock<mutex>& )
- {
- elem = boost::move(data_.front());
- data_.pop_front();
- }
- inline value_type pull_front(unique_lock<mutex>& )
- {
- value_type e = boost::move(data_.front());
- data_.pop_front();
- return boost::move(e);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- inline void push(const value_type& elem, unique_lock<mutex>& lk)
- {
- data_.push_back(elem);
- notify_not_empty_if_needed(lk);
- }
-
- inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
- {
- data_.push_back(boost::move(elem));
- notify_not_empty_if_needed(lk);
- }
-#endif
- inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
- {
- data_.push_back(elem);
- notify_not_empty_if_needed(lk);
- }
-
- inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
- {
- data_.push_back(boost::move(elem));
- notify_not_empty_if_needed(lk);
- }
- };
-
- template <typename ValueType>
- sync_queue<ValueType>::sync_queue() :
- waiting_empty_(0), data_(), closed_(false)
- {
- BOOST_ASSERT(data_.empty());
- }
-
-// template <typename ValueType>
-// template <typename Range>
-// explicit sync_queue<ValueType>::sync_queue(Range range) :
-// waiting_empty_(0), data_(), closed_(false)
-// {
-// try
-// {
-// typedef typename Range::iterator iterator_t;
-// iterator_t first = boost::begin(range);
-// iterator_t end = boost::end(range);
-// for (iterator_t cur = first; cur != end; ++cur)
-// {
-// data_.push(boost::move(*cur));;
-// }
-// notify_not_empty_if_needed(lk);
-// }
-// catch (...)
-// {
-// delete[] data_;
-// }
-// }
-
- template <typename ValueType>
- sync_queue<ValueType>::~sync_queue()
- {
- }
-
- template <typename ValueType>
- void sync_queue<ValueType>::close()
- {
- {
- lock_guard<mutex> lk(mtx_);
- closed_ = true;
- }
- not_empty_.notify_all();
- }
-
- template <typename ValueType>
- bool sync_queue<ValueType>::closed() const
- {
- lock_guard<mutex> lk(mtx_);
- return closed_;
- }
- template <typename ValueType>
- bool sync_queue<ValueType>::closed(unique_lock<mutex>&) const
- {
- return closed_;
- }
-
- template <typename ValueType>
- bool sync_queue<ValueType>::empty() const
- {
- lock_guard<mutex> lk(mtx_);
- return empty(lk);
- }
- template <typename ValueType>
- bool sync_queue<ValueType>::full() const
- {
- return false;
- }
-
- template <typename ValueType>
- typename sync_queue<ValueType>::size_type sync_queue<ValueType>::size() const
- {
- lock_guard<mutex> lk(mtx_);
- return size(lk);
- }
-
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_queue<ValueType>::try_pull(ValueType& elem, unique_lock<mutex>& lk)
- {
- if (empty(lk))
- {
- throw_if_closed(lk);
- return false;
- }
- pull(elem, lk);
- return true;
- }
- template <typename ValueType>
- shared_ptr<ValueType> sync_queue<ValueType>::try_pull(unique_lock<mutex>& lk)
- {
- if (empty(lk))
- {
- throw_if_closed(lk);
- return shared_ptr<ValueType>();
- }
- return ptr_pull(lk);
- }
-#endif
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
- {
- if (empty(lk))
- {
- if (closed(lk)) return queue_op_status::closed;
- return queue_op_status::empty;
- }
- pull_front(elem, lk);
- return queue_op_status::success;
- }
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
- {
- if (empty(lk))
- {
- if (closed(lk)) return queue_op_status::closed;
- }
- bool has_been_closed = false;
- wait_until_not_empty(lk, has_been_closed);
- if (has_been_closed) return queue_op_status::closed;
- pull_front(elem, lk);
- return queue_op_status::success;
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_queue<ValueType>::try_pull(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_pull(elem, lk);
- }
-#endif
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::try_pull_front(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_pull_front(elem, lk);
- }
-
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::wait_pull_front(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return wait_pull_front(elem, lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_queue<ValueType>::try_pull(no_block_tag,ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock())
- {
- return false;
- }
- return try_pull(elem, lk);
- }
- template <typename ValueType>
- boost::shared_ptr<ValueType> sync_queue<ValueType>::try_pull()
- {
- unique_lock<mutex> lk(mtx_);
- return try_pull(lk);
- }
-#endif
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::nonblocking_pull_front(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock())
- {
- return queue_op_status::busy;
- }
- return try_pull_front(elem, lk);
- }
-
- template <typename ValueType>
- void sync_queue<ValueType>::throw_if_closed(unique_lock<mutex>&)
- {
- if (closed_)
- {
- BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
- }
- }
-
- template <typename ValueType>
- void sync_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk)
- {
- for (;;)
- {
- if (! empty(lk)) break;
- throw_if_closed(lk);
- ++waiting_empty_;
- not_empty_.wait(lk);
- }
- }
- template <typename ValueType>
- void sync_queue<ValueType>::wait_until_not_empty(unique_lock<mutex>& lk, bool & closed)
- {
- for (;;)
- {
- if (! empty(lk)) break;
- if (closed_) {closed=true; return;}
- ++waiting_empty_;
- not_empty_.wait(lk);
- }
- closed=false;
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- void sync_queue<ValueType>::pull(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk);
- pull(elem, lk);
- }
- template <typename ValueType>
- void sync_queue<ValueType>::pull(ValueType& elem, bool & closed)
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk, closed);
- if (closed) {return;}
- pull(elem, lk);
- }
-
- // enable if ValueType is nothrow movable
- template <typename ValueType>
- ValueType sync_queue<ValueType>::pull()
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk);
- return pull(lk);
- }
- template <typename ValueType>
- boost::shared_ptr<ValueType> sync_queue<ValueType>::ptr_pull()
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk);
- return ptr_pull(lk);
- }
-#endif
-
- template <typename ValueType>
- void sync_queue<ValueType>::pull_front(ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk);
- pull_front(elem, lk);
- }
-
- // enable if ValueType is nothrow movable
- template <typename ValueType>
- ValueType sync_queue<ValueType>::pull_front()
- {
- unique_lock<mutex> lk(mtx_);
- wait_until_not_empty(lk);
- return pull_front(lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_queue<ValueType>::try_push(const ValueType& elem, unique_lock<mutex>& lk)
- {
- throw_if_closed(lk);
- push(elem, lk);
- return true;
- }
-
- template <typename ValueType>
- bool sync_queue<ValueType>::try_push(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_push(elem, lk);
- }
-#endif
-
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
- {
- if (closed(lk)) return queue_op_status::closed;
- push_back(elem, lk);
- return queue_op_status::success;
- }
-
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::try_push_back(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_push_back(elem, lk);
- }
-
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
- {
- if (closed(lk)) return queue_op_status::closed;
- push_back(elem, lk);
- return queue_op_status::success;
- }
-
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::wait_push_back(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- return wait_push_back(elem, lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_queue<ValueType>::try_push(no_block_tag, const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock()) return false;
- return try_push(elem, lk);
- }
-#endif
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::nonblocking_push_back(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock()) return queue_op_status::busy;
- return try_push_back(elem, lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- void sync_queue<ValueType>::push(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- throw_if_closed(lk);
- push(elem, lk);
- }
-#endif
-
- template <typename ValueType>
- void sync_queue<ValueType>::push_back(const ValueType& elem)
- {
- unique_lock<mutex> lk(mtx_);
- throw_if_closed(lk);
- push_back(elem, lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
- {
- throw_if_closed(lk);
- push(boost::move(elem), lk);
- return true;
- }
-
- template <typename ValueType>
- bool sync_queue<ValueType>::try_push(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_push(boost::move(elem), lk);
- }
-#endif
-
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
- {
- if (closed(lk)) return queue_op_status::closed;
- push_back(boost::move(elem), lk);
- return queue_op_status::success;
- }
-
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_);
- return try_push_back(boost::move(elem), lk);
- }
-
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
- {
- if (closed(lk)) return queue_op_status::closed;
- push_back(boost::move(elem), lk);
- return queue_op_status::success;
- }
-
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_);
- return wait_push_back(boost::move(elem), lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- bool sync_queue<ValueType>::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock())
- {
- return false;
- }
- return try_push(boost::move(elem), lk);
- }
-#endif
-
- template <typename ValueType>
- queue_op_status sync_queue<ValueType>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_, try_to_lock);
- if (!lk.owns_lock())
- {
- return queue_op_status::busy;
- }
- return try_push_back(boost::move(elem), lk);
- }
-
-#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
- template <typename ValueType>
- void sync_queue<ValueType>::push(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_);
- throw_if_closed(lk);
- push(boost::move(elem), lk);
- }
-#endif
-
- template <typename ValueType>
- void sync_queue<ValueType>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
- {
- unique_lock<mutex> lk(mtx_);
- throw_if_closed(lk);
- push_back(boost::move(elem), lk);
- }
-
- template <typename ValueType>
- sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
- {
- sbq.push_back(boost::move(elem));
- return sbq;
- }
-
- template <typename ValueType>
- sync_queue<ValueType>& operator<<(sync_queue<ValueType>& sbq, ValueType const&elem)
- {
- sbq.push_back(elem);
- return sbq;
- }
-
- template <typename ValueType>
- sync_queue<ValueType>& operator>>(sync_queue<ValueType>& sbq, ValueType &elem)
- {
- sbq.pull_front(elem);
- return sbq;
- }
-
-}
-
-#include <boost/config/abi_suffix.hpp>
+#include <boost/thread/concurrent_queues/sync_queue.hpp>
#endif
diff --git a/boost/thread/user_scheduler.hpp b/boost/thread/user_scheduler.hpp
index 6305b9e26c..c551d21710 100644
--- a/boost/thread/user_scheduler.hpp
+++ b/boost/thread/user_scheduler.hpp
@@ -12,8 +12,8 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
-#include <boost/thread/sync_queue.hpp>
-#include <boost/thread/detail/work.hpp>
+#include <boost/thread/concurrent_queues/sync_queue.hpp>
+#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -39,7 +39,7 @@ namespace boost
work task;
try
{
- if (work_queue.try_pull_front(task) == queue_op_status::success)
+ if (work_queue.try_pull(task) == queue_op_status::success)
{
task();
return true;
@@ -144,23 +144,23 @@ namespace boost
void submit(Closure & closure)
{
work w ((closure));
- work_queue.push_back(boost::move(w));
+ 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_back(boost::move(w));
- //work_queue.push_back(work(closure)); // todo check why this doesn't work
+ 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_back(boost::move(w));
- //work_queue.push_back(work(boost::move(closure))); // todo check why this doesn't work
+ work_queue.push(boost::move(w));
+ //work_queue.push(work(boost::move(closure))); // todo check why this doesn't work
}
/**
diff --git a/boost/thread/win32/thread_primitives.hpp b/boost/thread/win32/thread_primitives.hpp
index 2960822f65..d9f63e6cf4 100644
--- a/boost/thread/win32/thread_primitives.hpp
+++ b/boost/thread/win32/thread_primitives.hpp
@@ -285,7 +285,6 @@ namespace boost
// Oops, we weren't called often enough, we're stuck
return 0xFFFFFFFF;
}
-#else
#endif
inline detail::gettickcount64_t GetTickCount64_()
{