1 #ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP
2 #define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP
4 //////////////////////////////////////////////////////////////////////////////
6 // (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost
7 // Software License, Version 1.0. (See accompanying file
8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 // See http://www.boost.org/libs/thread for documentation.
12 //////////////////////////////////////////////////////////////////////////////
14 #include <boost/thread/detail/config.hpp>
15 #include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
16 #include <boost/thread/concurrent_queues/queue_op_status.hpp>
17 #include <boost/thread/condition_variable.hpp>
18 #include <boost/thread/csbl/devector.hpp>
19 #include <boost/thread/detail/move.hpp>
20 #include <boost/thread/mutex.hpp>
22 #include <boost/throw_exception.hpp>
23 #include <boost/smart_ptr/shared_ptr.hpp>
24 #include <boost/smart_ptr/make_shared.hpp>
26 #include <boost/config/abi_prefix.hpp>
32 template <class ValueType, class Container = csbl::devector<ValueType> >
34 : public detail::sync_queue_base<ValueType, Container >
36 typedef detail::sync_queue_base<ValueType, Container > super;
39 typedef ValueType value_type;
40 //typedef typename super::value_type value_type; // fixme
41 typedef typename super::underlying_queue_type underlying_queue_type;
42 typedef typename super::size_type size_type;
43 typedef typename super::op_status op_status;
45 // Constructors/Assignment/Destructors
46 BOOST_THREAD_NO_COPYABLE(sync_deque)
48 //template <typename Range>
49 //inline explicit sync_deque(Range range);
53 inline void push_back(const value_type& x);
54 inline queue_op_status try_push_back(const value_type& x);
55 inline queue_op_status nonblocking_push_back(const value_type& x);
56 inline queue_op_status wait_push_back(const value_type& x);
57 inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
58 inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
59 inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
60 inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
62 // Observers/Modifiers
63 inline void pull_front(value_type&);
64 // enable_if is_nothrow_copy_movable<value_type>
65 inline value_type pull_front();
67 inline queue_op_status try_pull_front(value_type&);
68 inline queue_op_status nonblocking_pull_front(value_type&);
69 inline queue_op_status wait_pull_front(ValueType& elem);
73 inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
74 inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
75 inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
76 inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
77 inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
78 inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
80 inline void pull_front(value_type& elem, unique_lock<mutex>& )
82 elem = boost::move(super::data_.front());
83 super::data_.pop_front();
85 inline value_type pull_front(unique_lock<mutex>& )
87 value_type e = boost::move(super::data_.front());
88 super::data_.pop_front();
89 return boost::move(e);
92 inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
94 super::data_.push_back(elem);
95 super::notify_not_empty_if_needed(lk);
98 inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
100 super::data_.push_back(boost::move(elem));
101 super::notify_not_empty_if_needed(lk);
105 template <class ValueType, class Container>
106 sync_deque<ValueType, Container>::sync_deque() :
111 // template <class ValueType, class Container>
112 // template <class Range>
113 // explicit sync_deque<ValueType, Container>::sync_deque(Range range) :
114 // data_(), closed_(false)
118 // typedef typename Range::iterator iterator_t;
119 // iterator_t first = boost::begin(range);
120 // iterator_t end = boost::end(range);
121 // for (iterator_t cur = first; cur != end; ++cur)
123 // data_.push(boost::move(*cur));;
125 // notify_not_empty_if_needed(lk);
133 template <class ValueType, class Container>
134 sync_deque<ValueType, Container>::~sync_deque()
138 template <class ValueType, class Container>
139 queue_op_status sync_deque<ValueType, Container>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
141 if (super::empty(lk))
143 if (super::closed(lk)) return queue_op_status::closed;
144 return queue_op_status::empty;
146 pull_front(elem, lk);
147 return queue_op_status::success;
149 template <class ValueType, class Container>
150 queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
152 if (super::empty(lk))
154 if (super::closed(lk)) return queue_op_status::closed;
156 bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
157 if (has_been_closed) return queue_op_status::closed;
158 pull_front(elem, lk);
159 return queue_op_status::success;
162 template <class ValueType, class Container>
163 queue_op_status sync_deque<ValueType, Container>::try_pull_front(ValueType& elem)
165 unique_lock<mutex> lk(super::mtx_);
166 return try_pull_front(elem, lk);
169 template <class ValueType, class Container>
170 queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem)
172 unique_lock<mutex> lk(super::mtx_);
173 return wait_pull_front(elem, lk);
176 template <class ValueType, class Container>
177 queue_op_status sync_deque<ValueType, Container>::nonblocking_pull_front(ValueType& elem)
179 unique_lock<mutex> lk(super::mtx_, try_to_lock);
182 return queue_op_status::busy;
184 return try_pull_front(elem, lk);
187 template <class ValueType, class Container>
188 void sync_deque<ValueType, Container>::pull_front(ValueType& elem)
190 unique_lock<mutex> lk(super::mtx_);
191 super::wait_until_not_empty(lk);
192 pull_front(elem, lk);
195 // enable if ValueType is nothrow movable
196 template <class ValueType, class Container>
197 ValueType sync_deque<ValueType, Container>::pull_front()
199 unique_lock<mutex> lk(super::mtx_);
200 super::wait_until_not_empty(lk);
201 return pull_front(lk);
204 template <class ValueType, class Container>
205 queue_op_status sync_deque<ValueType, Container>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
207 if (super::closed(lk)) return queue_op_status::closed;
209 return queue_op_status::success;
212 template <class ValueType, class Container>
213 queue_op_status sync_deque<ValueType, Container>::try_push_back(const ValueType& elem)
215 unique_lock<mutex> lk(super::mtx_);
216 return try_push_back(elem, lk);
219 template <class ValueType, class Container>
220 queue_op_status sync_deque<ValueType, Container>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
222 if (super::closed(lk)) return queue_op_status::closed;
224 return queue_op_status::success;
227 template <class ValueType, class Container>
228 queue_op_status sync_deque<ValueType, Container>::wait_push_back(const ValueType& elem)
230 unique_lock<mutex> lk(super::mtx_);
231 return wait_push_back(elem, lk);
234 template <class ValueType, class Container>
235 queue_op_status sync_deque<ValueType, Container>::nonblocking_push_back(const ValueType& elem)
237 unique_lock<mutex> lk(super::mtx_, try_to_lock);
238 if (!lk.owns_lock()) return queue_op_status::busy;
239 return try_push_back(elem, lk);
242 template <class ValueType, class Container>
243 void sync_deque<ValueType, Container>::push_back(const ValueType& elem)
245 unique_lock<mutex> lk(super::mtx_);
246 super::throw_if_closed(lk);
250 template <class ValueType, class Container>
251 queue_op_status sync_deque<ValueType, Container>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
253 if (super::closed(lk)) return queue_op_status::closed;
254 push_back(boost::move(elem), lk);
255 return queue_op_status::success;
258 template <class ValueType, class Container>
259 queue_op_status sync_deque<ValueType, Container>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
261 unique_lock<mutex> lk(super::mtx_);
262 return try_push_back(boost::move(elem), lk);
265 template <class ValueType, class Container>
266 queue_op_status sync_deque<ValueType, Container>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
268 if (super::closed(lk)) return queue_op_status::closed;
269 push_back(boost::move(elem), lk);
270 return queue_op_status::success;
273 template <class ValueType, class Container>
274 queue_op_status sync_deque<ValueType, Container>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
276 unique_lock<mutex> lk(super::mtx_);
277 return wait_push_back(boost::move(elem), lk);
280 template <class ValueType, class Container>
281 queue_op_status sync_deque<ValueType, Container>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
283 unique_lock<mutex> lk(super::mtx_, try_to_lock);
286 return queue_op_status::busy;
288 return try_push_back(boost::move(elem), lk);
291 template <class ValueType, class Container>
292 void sync_deque<ValueType, Container>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
294 unique_lock<mutex> lk(super::mtx_);
295 super::throw_if_closed(lk);
296 push_back(boost::move(elem), lk);
299 template <class ValueType, class Container>
300 sync_deque<ValueType, Container>& operator<<(sync_deque<ValueType, Container>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
302 sbq.push_back(boost::move(elem));
306 template <class ValueType, class Container>
307 sync_deque<ValueType, Container>& operator<<(sync_deque<ValueType, Container>& sbq, ValueType const&elem)
313 template <class ValueType, class Container>
314 sync_deque<ValueType, Container>& operator>>(sync_deque<ValueType, Container>& sbq, ValueType &elem)
316 sbq.pull_front(elem);
321 using concurrent::sync_deque;
325 #include <boost/config/abi_suffix.hpp>