Chris@102
|
1 #ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP
|
Chris@102
|
2 #define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP
|
Chris@102
|
3
|
Chris@102
|
4 //////////////////////////////////////////////////////////////////////////////
|
Chris@102
|
5 //
|
Chris@102
|
6 // (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost
|
Chris@102
|
7 // Software License, Version 1.0. (See accompanying file
|
Chris@102
|
8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
9 //
|
Chris@102
|
10 // See http://www.boost.org/libs/thread for documentation.
|
Chris@102
|
11 //
|
Chris@102
|
12 //////////////////////////////////////////////////////////////////////////////
|
Chris@102
|
13
|
Chris@102
|
14 #include <boost/thread/detail/config.hpp>
|
Chris@102
|
15 #include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
|
Chris@102
|
16 #include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
Chris@102
|
17 #include <boost/thread/condition_variable.hpp>
|
Chris@102
|
18 #include <boost/thread/csbl/devector.hpp>
|
Chris@102
|
19 #include <boost/thread/detail/move.hpp>
|
Chris@102
|
20 #include <boost/thread/mutex.hpp>
|
Chris@102
|
21
|
Chris@102
|
22 #include <boost/throw_exception.hpp>
|
Chris@102
|
23 #include <boost/smart_ptr/shared_ptr.hpp>
|
Chris@102
|
24 #include <boost/smart_ptr/make_shared.hpp>
|
Chris@102
|
25
|
Chris@102
|
26 #include <boost/config/abi_prefix.hpp>
|
Chris@102
|
27
|
Chris@102
|
28 namespace boost
|
Chris@102
|
29 {
|
Chris@102
|
30 namespace concurrent
|
Chris@102
|
31 {
|
Chris@102
|
32 template <class ValueType, class Container = csbl::devector<ValueType> >
|
Chris@102
|
33 class sync_deque
|
Chris@102
|
34 : public detail::sync_queue_base<ValueType, Container >
|
Chris@102
|
35 {
|
Chris@102
|
36 typedef detail::sync_queue_base<ValueType, Container > super;
|
Chris@102
|
37
|
Chris@102
|
38 public:
|
Chris@102
|
39 typedef ValueType value_type;
|
Chris@102
|
40 //typedef typename super::value_type value_type; // fixme
|
Chris@102
|
41 typedef typename super::underlying_queue_type underlying_queue_type;
|
Chris@102
|
42 typedef typename super::size_type size_type;
|
Chris@102
|
43 typedef typename super::op_status op_status;
|
Chris@102
|
44
|
Chris@102
|
45 // Constructors/Assignment/Destructors
|
Chris@102
|
46 BOOST_THREAD_NO_COPYABLE(sync_deque)
|
Chris@102
|
47 inline sync_deque();
|
Chris@102
|
48 //template <typename Range>
|
Chris@102
|
49 //inline explicit sync_deque(Range range);
|
Chris@102
|
50 inline ~sync_deque();
|
Chris@102
|
51
|
Chris@102
|
52 // Modifiers
|
Chris@102
|
53 inline void push_back(const value_type& x);
|
Chris@102
|
54 inline queue_op_status try_push_back(const value_type& x);
|
Chris@102
|
55 inline queue_op_status nonblocking_push_back(const value_type& x);
|
Chris@102
|
56 inline queue_op_status wait_push_back(const value_type& x);
|
Chris@102
|
57 inline void push_back(BOOST_THREAD_RV_REF(value_type) x);
|
Chris@102
|
58 inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
Chris@102
|
59 inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
Chris@102
|
60 inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x);
|
Chris@102
|
61
|
Chris@102
|
62 // Observers/Modifiers
|
Chris@102
|
63 inline void pull_front(value_type&);
|
Chris@102
|
64 // enable_if is_nothrow_copy_movable<value_type>
|
Chris@102
|
65 inline value_type pull_front();
|
Chris@102
|
66
|
Chris@102
|
67 inline queue_op_status try_pull_front(value_type&);
|
Chris@102
|
68 inline queue_op_status nonblocking_pull_front(value_type&);
|
Chris@102
|
69 inline queue_op_status wait_pull_front(ValueType& elem);
|
Chris@102
|
70
|
Chris@102
|
71 private:
|
Chris@102
|
72
|
Chris@102
|
73 inline queue_op_status try_pull_front(value_type& x, unique_lock<mutex>& lk);
|
Chris@102
|
74 inline queue_op_status wait_pull_front(value_type& x, unique_lock<mutex>& lk);
|
Chris@102
|
75 inline queue_op_status try_push_back(const value_type& x, unique_lock<mutex>& lk);
|
Chris@102
|
76 inline queue_op_status wait_push_back(const value_type& x, unique_lock<mutex>& lk);
|
Chris@102
|
77 inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
Chris@102
|
78 inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock<mutex>& lk);
|
Chris@102
|
79
|
Chris@102
|
80 inline void pull_front(value_type& elem, unique_lock<mutex>& )
|
Chris@102
|
81 {
|
Chris@102
|
82 elem = boost::move(super::data_.front());
|
Chris@102
|
83 super::data_.pop_front();
|
Chris@102
|
84 }
|
Chris@102
|
85 inline value_type pull_front(unique_lock<mutex>& )
|
Chris@102
|
86 {
|
Chris@102
|
87 value_type e = boost::move(super::data_.front());
|
Chris@102
|
88 super::data_.pop_front();
|
Chris@102
|
89 return boost::move(e);
|
Chris@102
|
90 }
|
Chris@102
|
91
|
Chris@102
|
92 inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
|
Chris@102
|
93 {
|
Chris@102
|
94 super::data_.push_back(elem);
|
Chris@102
|
95 super::notify_not_empty_if_needed(lk);
|
Chris@102
|
96 }
|
Chris@102
|
97
|
Chris@102
|
98 inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
|
Chris@102
|
99 {
|
Chris@102
|
100 super::data_.push_back(boost::move(elem));
|
Chris@102
|
101 super::notify_not_empty_if_needed(lk);
|
Chris@102
|
102 }
|
Chris@102
|
103 };
|
Chris@102
|
104
|
Chris@102
|
105 template <class ValueType, class Container>
|
Chris@102
|
106 sync_deque<ValueType, Container>::sync_deque() :
|
Chris@102
|
107 super()
|
Chris@102
|
108 {
|
Chris@102
|
109 }
|
Chris@102
|
110
|
Chris@102
|
111 // template <class ValueType, class Container>
|
Chris@102
|
112 // template <class Range>
|
Chris@102
|
113 // explicit sync_deque<ValueType, Container>::sync_deque(Range range) :
|
Chris@102
|
114 // data_(), closed_(false)
|
Chris@102
|
115 // {
|
Chris@102
|
116 // try
|
Chris@102
|
117 // {
|
Chris@102
|
118 // typedef typename Range::iterator iterator_t;
|
Chris@102
|
119 // iterator_t first = boost::begin(range);
|
Chris@102
|
120 // iterator_t end = boost::end(range);
|
Chris@102
|
121 // for (iterator_t cur = first; cur != end; ++cur)
|
Chris@102
|
122 // {
|
Chris@102
|
123 // data_.push(boost::move(*cur));;
|
Chris@102
|
124 // }
|
Chris@102
|
125 // notify_not_empty_if_needed(lk);
|
Chris@102
|
126 // }
|
Chris@102
|
127 // catch (...)
|
Chris@102
|
128 // {
|
Chris@102
|
129 // delete[] data_;
|
Chris@102
|
130 // }
|
Chris@102
|
131 // }
|
Chris@102
|
132
|
Chris@102
|
133 template <class ValueType, class Container>
|
Chris@102
|
134 sync_deque<ValueType, Container>::~sync_deque()
|
Chris@102
|
135 {
|
Chris@102
|
136 }
|
Chris@102
|
137
|
Chris@102
|
138 template <class ValueType, class Container>
|
Chris@102
|
139 queue_op_status sync_deque<ValueType, Container>::try_pull_front(ValueType& elem, unique_lock<mutex>& lk)
|
Chris@102
|
140 {
|
Chris@102
|
141 if (super::empty(lk))
|
Chris@102
|
142 {
|
Chris@102
|
143 if (super::closed(lk)) return queue_op_status::closed;
|
Chris@102
|
144 return queue_op_status::empty;
|
Chris@102
|
145 }
|
Chris@102
|
146 pull_front(elem, lk);
|
Chris@102
|
147 return queue_op_status::success;
|
Chris@102
|
148 }
|
Chris@102
|
149 template <class ValueType, class Container>
|
Chris@102
|
150 queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
|
Chris@102
|
151 {
|
Chris@102
|
152 if (super::empty(lk))
|
Chris@102
|
153 {
|
Chris@102
|
154 if (super::closed(lk)) return queue_op_status::closed;
|
Chris@102
|
155 }
|
Chris@102
|
156 bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
|
Chris@102
|
157 if (has_been_closed) return queue_op_status::closed;
|
Chris@102
|
158 pull_front(elem, lk);
|
Chris@102
|
159 return queue_op_status::success;
|
Chris@102
|
160 }
|
Chris@102
|
161
|
Chris@102
|
162 template <class ValueType, class Container>
|
Chris@102
|
163 queue_op_status sync_deque<ValueType, Container>::try_pull_front(ValueType& elem)
|
Chris@102
|
164 {
|
Chris@102
|
165 unique_lock<mutex> lk(super::mtx_);
|
Chris@102
|
166 return try_pull_front(elem, lk);
|
Chris@102
|
167 }
|
Chris@102
|
168
|
Chris@102
|
169 template <class ValueType, class Container>
|
Chris@102
|
170 queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem)
|
Chris@102
|
171 {
|
Chris@102
|
172 unique_lock<mutex> lk(super::mtx_);
|
Chris@102
|
173 return wait_pull_front(elem, lk);
|
Chris@102
|
174 }
|
Chris@102
|
175
|
Chris@102
|
176 template <class ValueType, class Container>
|
Chris@102
|
177 queue_op_status sync_deque<ValueType, Container>::nonblocking_pull_front(ValueType& elem)
|
Chris@102
|
178 {
|
Chris@102
|
179 unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
Chris@102
|
180 if (!lk.owns_lock())
|
Chris@102
|
181 {
|
Chris@102
|
182 return queue_op_status::busy;
|
Chris@102
|
183 }
|
Chris@102
|
184 return try_pull_front(elem, lk);
|
Chris@102
|
185 }
|
Chris@102
|
186
|
Chris@102
|
187 template <class ValueType, class Container>
|
Chris@102
|
188 void sync_deque<ValueType, Container>::pull_front(ValueType& elem)
|
Chris@102
|
189 {
|
Chris@102
|
190 unique_lock<mutex> lk(super::mtx_);
|
Chris@102
|
191 super::wait_until_not_empty(lk);
|
Chris@102
|
192 pull_front(elem, lk);
|
Chris@102
|
193 }
|
Chris@102
|
194
|
Chris@102
|
195 // enable if ValueType is nothrow movable
|
Chris@102
|
196 template <class ValueType, class Container>
|
Chris@102
|
197 ValueType sync_deque<ValueType, Container>::pull_front()
|
Chris@102
|
198 {
|
Chris@102
|
199 unique_lock<mutex> lk(super::mtx_);
|
Chris@102
|
200 super::wait_until_not_empty(lk);
|
Chris@102
|
201 return pull_front(lk);
|
Chris@102
|
202 }
|
Chris@102
|
203
|
Chris@102
|
204 template <class ValueType, class Container>
|
Chris@102
|
205 queue_op_status sync_deque<ValueType, Container>::try_push_back(const ValueType& elem, unique_lock<mutex>& lk)
|
Chris@102
|
206 {
|
Chris@102
|
207 if (super::closed(lk)) return queue_op_status::closed;
|
Chris@102
|
208 push_back(elem, lk);
|
Chris@102
|
209 return queue_op_status::success;
|
Chris@102
|
210 }
|
Chris@102
|
211
|
Chris@102
|
212 template <class ValueType, class Container>
|
Chris@102
|
213 queue_op_status sync_deque<ValueType, Container>::try_push_back(const ValueType& elem)
|
Chris@102
|
214 {
|
Chris@102
|
215 unique_lock<mutex> lk(super::mtx_);
|
Chris@102
|
216 return try_push_back(elem, lk);
|
Chris@102
|
217 }
|
Chris@102
|
218
|
Chris@102
|
219 template <class ValueType, class Container>
|
Chris@102
|
220 queue_op_status sync_deque<ValueType, Container>::wait_push_back(const ValueType& elem, unique_lock<mutex>& lk)
|
Chris@102
|
221 {
|
Chris@102
|
222 if (super::closed(lk)) return queue_op_status::closed;
|
Chris@102
|
223 push_back(elem, lk);
|
Chris@102
|
224 return queue_op_status::success;
|
Chris@102
|
225 }
|
Chris@102
|
226
|
Chris@102
|
227 template <class ValueType, class Container>
|
Chris@102
|
228 queue_op_status sync_deque<ValueType, Container>::wait_push_back(const ValueType& elem)
|
Chris@102
|
229 {
|
Chris@102
|
230 unique_lock<mutex> lk(super::mtx_);
|
Chris@102
|
231 return wait_push_back(elem, lk);
|
Chris@102
|
232 }
|
Chris@102
|
233
|
Chris@102
|
234 template <class ValueType, class Container>
|
Chris@102
|
235 queue_op_status sync_deque<ValueType, Container>::nonblocking_push_back(const ValueType& elem)
|
Chris@102
|
236 {
|
Chris@102
|
237 unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
Chris@102
|
238 if (!lk.owns_lock()) return queue_op_status::busy;
|
Chris@102
|
239 return try_push_back(elem, lk);
|
Chris@102
|
240 }
|
Chris@102
|
241
|
Chris@102
|
242 template <class ValueType, class Container>
|
Chris@102
|
243 void sync_deque<ValueType, Container>::push_back(const ValueType& elem)
|
Chris@102
|
244 {
|
Chris@102
|
245 unique_lock<mutex> lk(super::mtx_);
|
Chris@102
|
246 super::throw_if_closed(lk);
|
Chris@102
|
247 push_back(elem, lk);
|
Chris@102
|
248 }
|
Chris@102
|
249
|
Chris@102
|
250 template <class ValueType, class Container>
|
Chris@102
|
251 queue_op_status sync_deque<ValueType, Container>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
|
Chris@102
|
252 {
|
Chris@102
|
253 if (super::closed(lk)) return queue_op_status::closed;
|
Chris@102
|
254 push_back(boost::move(elem), lk);
|
Chris@102
|
255 return queue_op_status::success;
|
Chris@102
|
256 }
|
Chris@102
|
257
|
Chris@102
|
258 template <class ValueType, class Container>
|
Chris@102
|
259 queue_op_status sync_deque<ValueType, Container>::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
Chris@102
|
260 {
|
Chris@102
|
261 unique_lock<mutex> lk(super::mtx_);
|
Chris@102
|
262 return try_push_back(boost::move(elem), lk);
|
Chris@102
|
263 }
|
Chris@102
|
264
|
Chris@102
|
265 template <class ValueType, class Container>
|
Chris@102
|
266 queue_op_status sync_deque<ValueType, Container>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock<mutex>& lk)
|
Chris@102
|
267 {
|
Chris@102
|
268 if (super::closed(lk)) return queue_op_status::closed;
|
Chris@102
|
269 push_back(boost::move(elem), lk);
|
Chris@102
|
270 return queue_op_status::success;
|
Chris@102
|
271 }
|
Chris@102
|
272
|
Chris@102
|
273 template <class ValueType, class Container>
|
Chris@102
|
274 queue_op_status sync_deque<ValueType, Container>::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
Chris@102
|
275 {
|
Chris@102
|
276 unique_lock<mutex> lk(super::mtx_);
|
Chris@102
|
277 return wait_push_back(boost::move(elem), lk);
|
Chris@102
|
278 }
|
Chris@102
|
279
|
Chris@102
|
280 template <class ValueType, class Container>
|
Chris@102
|
281 queue_op_status sync_deque<ValueType, Container>::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
Chris@102
|
282 {
|
Chris@102
|
283 unique_lock<mutex> lk(super::mtx_, try_to_lock);
|
Chris@102
|
284 if (!lk.owns_lock())
|
Chris@102
|
285 {
|
Chris@102
|
286 return queue_op_status::busy;
|
Chris@102
|
287 }
|
Chris@102
|
288 return try_push_back(boost::move(elem), lk);
|
Chris@102
|
289 }
|
Chris@102
|
290
|
Chris@102
|
291 template <class ValueType, class Container>
|
Chris@102
|
292 void sync_deque<ValueType, Container>::push_back(BOOST_THREAD_RV_REF(ValueType) elem)
|
Chris@102
|
293 {
|
Chris@102
|
294 unique_lock<mutex> lk(super::mtx_);
|
Chris@102
|
295 super::throw_if_closed(lk);
|
Chris@102
|
296 push_back(boost::move(elem), lk);
|
Chris@102
|
297 }
|
Chris@102
|
298
|
Chris@102
|
299 template <class ValueType, class Container>
|
Chris@102
|
300 sync_deque<ValueType, Container>& operator<<(sync_deque<ValueType, Container>& sbq, BOOST_THREAD_RV_REF(ValueType) elem)
|
Chris@102
|
301 {
|
Chris@102
|
302 sbq.push_back(boost::move(elem));
|
Chris@102
|
303 return sbq;
|
Chris@102
|
304 }
|
Chris@102
|
305
|
Chris@102
|
306 template <class ValueType, class Container>
|
Chris@102
|
307 sync_deque<ValueType, Container>& operator<<(sync_deque<ValueType, Container>& sbq, ValueType const&elem)
|
Chris@102
|
308 {
|
Chris@102
|
309 sbq.push_back(elem);
|
Chris@102
|
310 return sbq;
|
Chris@102
|
311 }
|
Chris@102
|
312
|
Chris@102
|
313 template <class ValueType, class Container>
|
Chris@102
|
314 sync_deque<ValueType, Container>& operator>>(sync_deque<ValueType, Container>& sbq, ValueType &elem)
|
Chris@102
|
315 {
|
Chris@102
|
316 sbq.pull_front(elem);
|
Chris@102
|
317 return sbq;
|
Chris@102
|
318 }
|
Chris@102
|
319
|
Chris@102
|
320 }
|
Chris@102
|
321 using concurrent::sync_deque;
|
Chris@102
|
322
|
Chris@102
|
323 }
|
Chris@102
|
324
|
Chris@102
|
325 #include <boost/config/abi_suffix.hpp>
|
Chris@102
|
326
|
Chris@102
|
327 #endif
|