1 // Copyright (C) 2014 Ian Forbed
2 // Copyright (C) 2014,2015 Vicente J. Botet Escriba
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7
8 #include <boost/config.hpp>
9 #if ! defined BOOST_NO_CXX11_DECLTYPE
10 #define BOOST_RESULT_OF_USE_DECLTYPE
11 #endif
12
13 #define BOOST_THREAD_VERSION 4
14 #define BOOST_THREAD_PROVIDES_EXECUTORS
15
16 #include <iostream>
17
18 #include <boost/thread.hpp>
19 #include <boost/chrono.hpp>
20 #include <boost/thread/concurrent_queues/sync_priority_queue.hpp>
21
22 #include <boost/detail/lightweight_test.hpp>
23 #include "../../../timming.hpp"
24
25 using namespace boost::chrono;
26 typedef boost::chrono::milliseconds ms;
27 typedef boost::chrono::nanoseconds ns;
28
29 typedef boost::concurrent::sync_priority_queue<int> sync_pq;
30
31 class non_copyable
32 {
33 BOOST_THREAD_MOVABLE_ONLY(non_copyable)
34 int val;
35 public:
non_copyable(int v)36 non_copyable(int v) : val(v){}
non_copyable(BOOST_RV_REF (non_copyable)x)37 non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {}
operator =(BOOST_RV_REF (non_copyable)x)38 non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; }
operator ==(non_copyable const & x) const39 bool operator==(non_copyable const& x) const {return val==x.val;}
40 template <typename OSTREAM>
operator <<(OSTREAM & os,non_copyable const & x)41 friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x )
42 {
43 os << x.val;
44 return os;
45 }
operator <(const non_copyable & other) const46 bool operator <(const non_copyable& other) const
47 {
48 return val < other.val;
49 }
50 };
51
52 const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
53
test_pull_for()54 void test_pull_for()
55 {
56 sync_pq pq;
57 steady_clock::time_point start = steady_clock::now();
58 int val;
59 boost::queue_op_status st = pq.pull_for(milliseconds(500), val);
60 ns d = steady_clock::now() - start - milliseconds(500);
61 BOOST_THREAD_TEST_IT(d, ns(max_diff));
62 BOOST_TEST(boost::queue_op_status::timeout == st);
63 }
64
test_pull_until()65 void test_pull_until()
66 {
67 sync_pq pq;
68 steady_clock::time_point start = steady_clock::now();
69 int val;
70 boost::queue_op_status st = pq.pull_until(start + milliseconds(500), val);
71 ns d = steady_clock::now() - start - milliseconds(500);
72 BOOST_THREAD_TEST_IT(d, ns(max_diff));
73 BOOST_TEST(boost::queue_op_status::timeout == st);
74 }
75
test_nonblocking_pull()76 void test_nonblocking_pull()
77 {
78 sync_pq pq;
79 steady_clock::time_point start = steady_clock::now();
80 int val;
81 boost::queue_op_status st = pq.nonblocking_pull(val);
82 ns d = steady_clock::now() - start;
83 BOOST_THREAD_TEST_IT(d, ns(max_diff));
84 BOOST_TEST(boost::queue_op_status::empty == st);
85 }
86
test_pull_for_when_not_empty()87 void test_pull_for_when_not_empty()
88 {
89 sync_pq pq;
90 pq.push(1);
91 steady_clock::time_point start = steady_clock::now();
92 int val;
93 boost::queue_op_status st = pq.pull_for(milliseconds(500), val);
94 ns d = steady_clock::now() - start;
95 BOOST_THREAD_TEST_IT(d, ns(max_diff));
96 BOOST_TEST(boost::queue_op_status::success == st);
97 BOOST_TEST(1 == val);
98 }
99
test_pull_until_when_not_empty()100 void test_pull_until_when_not_empty()
101 {
102 sync_pq pq;
103 pq.push(1);
104 steady_clock::time_point start = steady_clock::now();
105 int val;
106 boost::queue_op_status st = pq.pull_until(start + milliseconds(500), val);
107 ns d = steady_clock::now() - start;
108 BOOST_THREAD_TEST_IT(d, ns(max_diff));
109 BOOST_TEST(boost::queue_op_status::success == st);
110 BOOST_TEST(1 == val);
111 }
112
main()113 int main()
114 {
115 sync_pq pq;
116 BOOST_TEST(pq.empty());
117 BOOST_TEST(!pq.closed());
118 BOOST_TEST_EQ(pq.size(), std::size_t(0));
119
120 for(int i = 1; i <= 5; i++){
121 pq.push(i);
122 BOOST_TEST(!pq.empty());
123 BOOST_TEST_EQ(pq.size(), std::size_t(i));
124 }
125
126 for(int i = 6; i <= 10; i++){
127 boost::queue_op_status succ = pq.try_push(i);
128 BOOST_TEST(succ == boost::queue_op_status::success );
129 BOOST_TEST(!pq.empty());
130 BOOST_TEST_EQ(pq.size(), std::size_t(i));
131 }
132
133 for(int i = 10; i > 5; i--){
134 int val = pq.pull();
135 BOOST_TEST_EQ(val, i);
136 }
137
138 // for(int i = 5; i > 0; i--){
139 // boost::optional<int> val = pq.try_pull();
140 // BOOST_TEST(val);
141 // BOOST_TEST_EQ(*val, i);
142 // }
143
144 // BOOST_TEST(pq.empty());
145 pq.close();
146 BOOST_TEST(pq.closed());
147
148 test_pull_for();
149 test_pull_until();
150 test_nonblocking_pull();
151
152 test_pull_for_when_not_empty();
153 //test_pull_until_when_not_empty();
154
155 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
156 {
157 // empty queue try_push rvalue/non-copyable succeeds
158 boost::concurrent::sync_priority_queue<non_copyable> q;
159 BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1)));
160 BOOST_TEST(! q.empty());
161 BOOST_TEST(! q.full());
162 BOOST_TEST_EQ(q.size(), 1u);
163 BOOST_TEST(! q.closed());
164 }
165 {
166 //fixme
167 // empty queue try_push rvalue/non-copyable succeeds
168 boost::concurrent::sync_priority_queue<non_copyable> q;
169 non_copyable nc(1);
170 BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc)));
171 BOOST_TEST(! q.empty());
172 BOOST_TEST(! q.full());
173 BOOST_TEST_EQ(q.size(), 1u);
174 BOOST_TEST(! q.closed());
175 }
176 #endif
177
178 {
179 // empty queue try_push lvalue succeeds
180 boost::concurrent::sync_priority_queue<int> q;
181 int i=1;
182 BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
183 BOOST_TEST(! q.empty());
184 BOOST_TEST(! q.full());
185 BOOST_TEST_EQ(q.size(), 1u);
186 BOOST_TEST(! q.closed());
187 }
188 #if 0
189 {
190 // empty queue try_push rvalue succeeds
191 boost::concurrent::sync_priority_queue<int> q;
192 BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1));
193 BOOST_TEST(! q.empty());
194 BOOST_TEST(! q.full());
195 BOOST_TEST_EQ(q.size(), 1u);
196 BOOST_TEST(! q.closed());
197 }
198 {
199 // empty queue nonblocking_push rvalue/non-copyable succeeds
200 boost::concurrent::sync_priority_queue<non_copyable> q;
201 BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1)));
202 BOOST_TEST(! q.empty());
203 BOOST_TEST(! q.full());
204 BOOST_TEST_EQ(q.size(), 1u);
205 BOOST_TEST(! q.closed());
206 }
207 {
208 // empty queue nonblocking_push rvalue/non-copyable succeeds
209 boost::concurrent::sync_priority_queue<non_copyable> q;
210 non_copyable nc(1);
211 BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc)));
212 BOOST_TEST(! q.empty());
213 BOOST_TEST(! q.full());
214 BOOST_TEST_EQ(q.size(), 1u);
215 BOOST_TEST(! q.closed());
216 }
217 #endif
218
219 {
220 // 1-element queue pull succeed
221 boost::concurrent::sync_priority_queue<int> q;
222 q.push(1);
223 int i;
224 i=q.pull();
225 BOOST_TEST_EQ(i, 1);
226 BOOST_TEST(q.empty());
227 BOOST_TEST(! q.full());
228 BOOST_TEST_EQ(q.size(), 0u);
229 BOOST_TEST(! q.closed());
230 }
231 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
232 {
233 // 1-element queue pull succeed
234 boost::concurrent::sync_priority_queue<non_copyable> q;
235 non_copyable nc1(1);
236 q.push(boost::move(nc1));
237 non_copyable nc2(2);
238 nc2=q.pull();
239 BOOST_TEST_EQ(nc1, nc2);
240 BOOST_TEST(q.empty());
241 BOOST_TEST(! q.full());
242 BOOST_TEST_EQ(q.size(), 0u);
243 BOOST_TEST(! q.closed());
244 }
245 #endif
246
247 {
248 // 1-element queue pull succeed
249 boost::concurrent::sync_priority_queue<int> q;
250 q.push(1);
251 int i = q.pull();
252 BOOST_TEST_EQ(i, 1);
253 BOOST_TEST(q.empty());
254 BOOST_TEST(! q.full());
255 BOOST_TEST_EQ(q.size(), 0u);
256 BOOST_TEST(! q.closed());
257 }
258 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
259 {
260 // 1-element queue pull succeed
261 boost::concurrent::sync_priority_queue<non_copyable> q;
262 non_copyable nc1(1);
263 q.push(boost::move(nc1));
264 non_copyable nc = q.pull();
265 BOOST_TEST_EQ(nc, nc1);
266 BOOST_TEST(q.empty());
267 BOOST_TEST(! q.full());
268 BOOST_TEST_EQ(q.size(), 0u);
269 BOOST_TEST(! q.closed());
270 }
271 #endif
272
273 {
274 // 1-element queue try_pull succeed
275 boost::concurrent::sync_priority_queue<int> q;
276 q.push(1);
277 int i;
278 BOOST_TEST(boost::queue_op_status::success == q.try_pull(i));
279 BOOST_TEST_EQ(i, 1);
280 BOOST_TEST(q.empty());
281 BOOST_TEST(! q.full());
282 BOOST_TEST_EQ(q.size(), 0u);
283 BOOST_TEST(! q.closed());
284 }
285 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
286 {
287 // 1-element queue try_pull succeed
288 boost::concurrent::sync_priority_queue<non_copyable> q;
289 non_copyable nc1(1);
290 q.push(boost::move(nc1));
291 non_copyable nc(2);
292 BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc));
293 BOOST_TEST_EQ(nc, nc1);
294 BOOST_TEST(q.empty());
295 BOOST_TEST(! q.full());
296 BOOST_TEST_EQ(q.size(), 0u);
297 BOOST_TEST(! q.closed());
298 }
299 #endif
300 {
301 // 1-element queue nonblocking_pull succeed
302 boost::concurrent::sync_priority_queue<int> q;
303 q.push(1);
304 int i;
305 BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i));
306 BOOST_TEST_EQ(i, 1);
307 BOOST_TEST(q.empty());
308 BOOST_TEST(! q.full());
309 BOOST_TEST_EQ(q.size(), 0u);
310 BOOST_TEST(! q.closed());
311 }
312 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
313 {
314 // 1-element queue nonblocking_pull succeed
315 boost::concurrent::sync_priority_queue<non_copyable> q;
316 non_copyable nc1(1);
317 q.push(boost::move(nc1));
318 non_copyable nc(2);
319 BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc));
320 BOOST_TEST_EQ(nc, nc1);
321 BOOST_TEST(q.empty());
322 BOOST_TEST(! q.full());
323 BOOST_TEST_EQ(q.size(), 0u);
324 BOOST_TEST(! q.closed());
325 }
326 {
327 // 1-element queue wait_pull succeed
328 boost::concurrent::sync_priority_queue<non_copyable> q;
329 non_copyable nc1(1);
330 q.push(boost::move(nc1));
331 non_copyable nc(2);
332 BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
333 BOOST_TEST_EQ(nc, nc1);
334 BOOST_TEST(q.empty());
335 BOOST_TEST(! q.full());
336 BOOST_TEST_EQ(q.size(), 0u);
337 BOOST_TEST(! q.closed());
338 }
339 #endif
340 {
341 // 1-element queue wait_pull succeed
342 boost::concurrent::sync_priority_queue<int> q;
343 q.push(1);
344 int i;
345 BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
346 BOOST_TEST_EQ(i, 1);
347 BOOST_TEST(q.empty());
348 BOOST_TEST(! q.full());
349 BOOST_TEST_EQ(q.size(), 0u);
350 BOOST_TEST(! q.closed());
351 }
352 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
353 {
354 // 1-element queue wait_pull succeed
355 boost::concurrent::sync_priority_queue<non_copyable> q;
356 non_copyable nc1(1);
357 q.push(boost::move(nc1));
358 non_copyable nc(2);
359 BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc));
360 BOOST_TEST_EQ(nc, nc1);
361 BOOST_TEST(q.empty());
362 BOOST_TEST(! q.full());
363 BOOST_TEST_EQ(q.size(), 0u);
364 BOOST_TEST(! q.closed());
365 }
366 #endif
367
368 {
369 // closed invariants
370 boost::concurrent::sync_priority_queue<int> q;
371 q.close();
372 BOOST_TEST(q.empty());
373 BOOST_TEST(! q.full());
374 BOOST_TEST_EQ(q.size(), 0u);
375 BOOST_TEST(q.closed());
376 }
377 {
378 // closed queue push fails
379 boost::concurrent::sync_priority_queue<int> q;
380 q.close();
381 try {
382 q.push(1);
383 BOOST_TEST(false); // fixme
384 } catch (...) {
385 BOOST_TEST(q.empty());
386 BOOST_TEST(! q.full());
387 BOOST_TEST_EQ(q.size(), 0u);
388 BOOST_TEST(q.closed());
389 }
390 }
391 {
392 // 1-element closed queue pull succeed
393 boost::concurrent::sync_priority_queue<int> q;
394 q.push(1);
395 q.close();
396 int i;
397 i=q.pull();
398 BOOST_TEST_EQ(i, 1);
399 BOOST_TEST(q.empty());
400 BOOST_TEST(! q.full());
401 BOOST_TEST_EQ(q.size(), 0u);
402 BOOST_TEST(q.closed());
403 }
404 {
405 // 1-element closed queue wait_pull succeed
406 boost::concurrent::sync_priority_queue<int> q;
407 q.push(1);
408 q.close();
409 int i;
410 BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i));
411 BOOST_TEST_EQ(i, 1);
412 BOOST_TEST(q.empty());
413 BOOST_TEST(! q.full());
414 BOOST_TEST_EQ(q.size(), 0u);
415 BOOST_TEST(q.closed());
416 }
417 {
418 // closed empty queue wait_pull fails
419 boost::concurrent::sync_priority_queue<int> q;
420 q.close();
421 BOOST_TEST(q.empty());
422 BOOST_TEST(q.closed());
423 int i;
424 BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i));
425 BOOST_TEST(q.empty());
426 BOOST_TEST(q.closed());
427 }
428 return boost::report_errors();
429 }
430