Chris@102: #ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP Chris@102: #define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost Chris@102: // Software License, Version 1.0. (See accompanying file Chris@102: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: // See http://www.boost.org/libs/thread for documentation. Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #include Chris@102: Chris@102: namespace boost Chris@102: { Chris@102: namespace concurrent Chris@102: { Chris@102: template > Chris@102: class sync_deque Chris@102: : public detail::sync_queue_base Chris@102: { Chris@102: typedef detail::sync_queue_base super; Chris@102: Chris@102: public: Chris@102: typedef ValueType value_type; Chris@102: //typedef typename super::value_type value_type; // fixme Chris@102: typedef typename super::underlying_queue_type underlying_queue_type; Chris@102: typedef typename super::size_type size_type; Chris@102: typedef typename super::op_status op_status; Chris@102: Chris@102: // Constructors/Assignment/Destructors Chris@102: BOOST_THREAD_NO_COPYABLE(sync_deque) Chris@102: inline sync_deque(); Chris@102: //template Chris@102: //inline explicit sync_deque(Range range); Chris@102: inline ~sync_deque(); Chris@102: Chris@102: // Modifiers Chris@102: inline void push_back(const value_type& x); Chris@102: inline queue_op_status try_push_back(const value_type& x); Chris@102: inline queue_op_status nonblocking_push_back(const value_type& x); Chris@102: inline queue_op_status wait_push_back(const value_type& x); Chris@102: inline void push_back(BOOST_THREAD_RV_REF(value_type) x); Chris@102: inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x); Chris@102: inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x); Chris@102: inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x); Chris@102: Chris@102: // Observers/Modifiers Chris@102: inline void pull_front(value_type&); Chris@102: // enable_if is_nothrow_copy_movable Chris@102: inline value_type pull_front(); Chris@102: Chris@102: inline queue_op_status try_pull_front(value_type&); Chris@102: inline queue_op_status nonblocking_pull_front(value_type&); Chris@102: inline queue_op_status wait_pull_front(ValueType& elem); Chris@102: Chris@102: private: Chris@102: Chris@102: inline queue_op_status try_pull_front(value_type& x, unique_lock& lk); Chris@102: inline queue_op_status wait_pull_front(value_type& x, unique_lock& lk); Chris@102: inline queue_op_status try_push_back(const value_type& x, unique_lock& lk); Chris@102: inline queue_op_status wait_push_back(const value_type& x, unique_lock& lk); Chris@102: inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock& lk); Chris@102: inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock& lk); Chris@102: Chris@102: inline void pull_front(value_type& elem, unique_lock& ) Chris@102: { Chris@102: elem = boost::move(super::data_.front()); Chris@102: super::data_.pop_front(); Chris@102: } Chris@102: inline value_type pull_front(unique_lock& ) Chris@102: { Chris@102: value_type e = boost::move(super::data_.front()); Chris@102: super::data_.pop_front(); Chris@102: return boost::move(e); Chris@102: } Chris@102: Chris@102: inline void push_back(const value_type& elem, unique_lock& lk) Chris@102: { Chris@102: super::data_.push_back(elem); Chris@102: super::notify_not_empty_if_needed(lk); Chris@102: } Chris@102: Chris@102: inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock& lk) Chris@102: { Chris@102: super::data_.push_back(boost::move(elem)); Chris@102: super::notify_not_empty_if_needed(lk); Chris@102: } Chris@102: }; Chris@102: Chris@102: template Chris@102: sync_deque::sync_deque() : Chris@102: super() Chris@102: { Chris@102: } Chris@102: Chris@102: // template Chris@102: // template Chris@102: // explicit sync_deque::sync_deque(Range range) : Chris@102: // data_(), closed_(false) Chris@102: // { Chris@102: // try Chris@102: // { Chris@102: // typedef typename Range::iterator iterator_t; Chris@102: // iterator_t first = boost::begin(range); Chris@102: // iterator_t end = boost::end(range); Chris@102: // for (iterator_t cur = first; cur != end; ++cur) Chris@102: // { Chris@102: // data_.push(boost::move(*cur));; Chris@102: // } Chris@102: // notify_not_empty_if_needed(lk); Chris@102: // } Chris@102: // catch (...) Chris@102: // { Chris@102: // delete[] data_; Chris@102: // } Chris@102: // } Chris@102: Chris@102: template Chris@102: sync_deque::~sync_deque() Chris@102: { Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::try_pull_front(ValueType& elem, unique_lock& lk) Chris@102: { Chris@102: if (super::empty(lk)) Chris@102: { Chris@102: if (super::closed(lk)) return queue_op_status::closed; Chris@102: return queue_op_status::empty; Chris@102: } Chris@102: pull_front(elem, lk); Chris@102: return queue_op_status::success; Chris@102: } Chris@102: template Chris@102: queue_op_status sync_deque::wait_pull_front(ValueType& elem, unique_lock& lk) Chris@102: { Chris@102: if (super::empty(lk)) Chris@102: { Chris@102: if (super::closed(lk)) return queue_op_status::closed; Chris@102: } Chris@102: bool has_been_closed = super::wait_until_not_empty_or_closed(lk); Chris@102: if (has_been_closed) return queue_op_status::closed; Chris@102: pull_front(elem, lk); Chris@102: return queue_op_status::success; Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::try_pull_front(ValueType& elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_); Chris@102: return try_pull_front(elem, lk); Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::wait_pull_front(ValueType& elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_); Chris@102: return wait_pull_front(elem, lk); Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::nonblocking_pull_front(ValueType& elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_, try_to_lock); Chris@102: if (!lk.owns_lock()) Chris@102: { Chris@102: return queue_op_status::busy; Chris@102: } Chris@102: return try_pull_front(elem, lk); Chris@102: } Chris@102: Chris@102: template Chris@102: void sync_deque::pull_front(ValueType& elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_); Chris@102: super::wait_until_not_empty(lk); Chris@102: pull_front(elem, lk); Chris@102: } Chris@102: Chris@102: // enable if ValueType is nothrow movable Chris@102: template Chris@102: ValueType sync_deque::pull_front() Chris@102: { Chris@102: unique_lock lk(super::mtx_); Chris@102: super::wait_until_not_empty(lk); Chris@102: return pull_front(lk); Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::try_push_back(const ValueType& elem, unique_lock& lk) Chris@102: { Chris@102: if (super::closed(lk)) return queue_op_status::closed; Chris@102: push_back(elem, lk); Chris@102: return queue_op_status::success; Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::try_push_back(const ValueType& elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_); Chris@102: return try_push_back(elem, lk); Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::wait_push_back(const ValueType& elem, unique_lock& lk) Chris@102: { Chris@102: if (super::closed(lk)) return queue_op_status::closed; Chris@102: push_back(elem, lk); Chris@102: return queue_op_status::success; Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::wait_push_back(const ValueType& elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_); Chris@102: return wait_push_back(elem, lk); Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::nonblocking_push_back(const ValueType& elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_, try_to_lock); Chris@102: if (!lk.owns_lock()) return queue_op_status::busy; Chris@102: return try_push_back(elem, lk); Chris@102: } Chris@102: Chris@102: template Chris@102: void sync_deque::push_back(const ValueType& elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_); Chris@102: super::throw_if_closed(lk); Chris@102: push_back(elem, lk); Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock& lk) Chris@102: { Chris@102: if (super::closed(lk)) return queue_op_status::closed; Chris@102: push_back(boost::move(elem), lk); Chris@102: return queue_op_status::success; Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_); Chris@102: return try_push_back(boost::move(elem), lk); Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock& lk) Chris@102: { Chris@102: if (super::closed(lk)) return queue_op_status::closed; Chris@102: push_back(boost::move(elem), lk); Chris@102: return queue_op_status::success; Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_); Chris@102: return wait_push_back(boost::move(elem), lk); Chris@102: } Chris@102: Chris@102: template Chris@102: queue_op_status sync_deque::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_, try_to_lock); Chris@102: if (!lk.owns_lock()) Chris@102: { Chris@102: return queue_op_status::busy; Chris@102: } Chris@102: return try_push_back(boost::move(elem), lk); Chris@102: } Chris@102: Chris@102: template Chris@102: void sync_deque::push_back(BOOST_THREAD_RV_REF(ValueType) elem) Chris@102: { Chris@102: unique_lock lk(super::mtx_); Chris@102: super::throw_if_closed(lk); Chris@102: push_back(boost::move(elem), lk); Chris@102: } Chris@102: Chris@102: template Chris@102: sync_deque& operator<<(sync_deque& sbq, BOOST_THREAD_RV_REF(ValueType) elem) Chris@102: { Chris@102: sbq.push_back(boost::move(elem)); Chris@102: return sbq; Chris@102: } Chris@102: Chris@102: template Chris@102: sync_deque& operator<<(sync_deque& sbq, ValueType const&elem) Chris@102: { Chris@102: sbq.push_back(elem); Chris@102: return sbq; Chris@102: } Chris@102: Chris@102: template Chris@102: sync_deque& operator>>(sync_deque& sbq, ValueType &elem) Chris@102: { Chris@102: sbq.pull_front(elem); Chris@102: return sbq; Chris@102: } Chris@102: Chris@102: } Chris@102: using concurrent::sync_deque; Chris@102: Chris@102: } Chris@102: Chris@102: #include Chris@102: Chris@102: #endif