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