• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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