1 // Copyright (C) 2013 Vicente J. Botet Escriba
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)
6 // <boost/thread/sync_queue.hpp>
12 #include <boost/config.hpp>
13 #if ! defined BOOST_NO_CXX11_DECLTYPE
14 #define BOOST_RESULT_OF_USE_DECLTYPE
17 #define BOOST_THREAD_VERSION 4
18 //#define BOOST_THREAD_QUEUE_DEPRECATE_OLD
20 #include <boost/thread/sync_queue.hpp>
21 #include <boost/thread/future.hpp>
22 #include <boost/thread/barrier.hpp>
24 #include <boost/detail/lightweight_test.hpp>
26 #ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
29 boost::sync_queue<int> *q_;
32 call_push(boost::sync_queue<int> *q, boost::barrier *go) :
36 typedef void result_type;
39 go_->count_down_and_wait();
47 boost::sync_queue<int> *q_;
50 call_pull(boost::sync_queue<int> *q, boost::barrier *go) :
54 typedef int result_type;
57 go_->count_down_and_wait();
63 template <typename ValueType>
66 boost::sync_queue<ValueType> *q_;
69 call_push_back(boost::sync_queue<ValueType> *q, boost::barrier *go) :
73 typedef void result_type;
76 go_->count_down_and_wait();
81 template <typename ValueType>
82 struct call_pull_front
84 boost::sync_queue<ValueType> *q_;
87 call_pull_front(boost::sync_queue<ValueType> *q, boost::barrier *go) :
91 typedef ValueType result_type;
92 ValueType operator()()
94 go_->count_down_and_wait();
95 return q_->pull_front();
99 template <typename ValueType>
100 struct call_wait_pull_front
102 boost::sync_queue<ValueType> *q_;
105 call_wait_pull_front(boost::sync_queue<ValueType> *q, boost::barrier *go) :
109 typedef boost::queue_op_status result_type;
110 boost::queue_op_status operator()(ValueType& v)
113 return q_->wait_pull_front(v);
117 #ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
118 void test_concurrent_push_and_pull_on_empty_queue()
120 boost::sync_queue<int> q;
122 boost::barrier go(2);
124 boost::future<void> push_done;
125 boost::future<int> pull_done;
129 push_done=boost::async(boost::launch::async,
130 #if ! defined BOOST_NO_CXX11_LAMBDAS
140 pull_done=boost::async(boost::launch::async,
141 #if ! defined BOOST_NO_CXX11_LAMBDAS
153 BOOST_TEST_EQ(pull_done.get(), 42);
154 BOOST_TEST(q.empty());
162 void test_concurrent_push_on_empty_queue()
164 boost::sync_queue<int> q;
165 const unsigned int n = 3;
166 boost::barrier go(n);
167 boost::future<void> push_done[n];
171 for (unsigned int i =0; i< n; ++i)
172 push_done[i]=boost::async(boost::launch::async,
173 #if ! defined BOOST_NO_CXX11_LAMBDAS
184 for (unsigned int i = 0; i < n; ++i)
187 BOOST_TEST(!q.empty());
188 for (unsigned int i =0; i< n; ++i)
189 BOOST_TEST_EQ(q.pull(), 42);
190 BOOST_TEST(q.empty());
199 void test_concurrent_pull_on_queue()
201 boost::sync_queue<int> q;
202 const unsigned int n = 3;
203 boost::barrier go(n);
205 boost::future<int> pull_done[n];
209 for (unsigned int i =0; i< n; ++i)
212 for (unsigned int i =0; i< n; ++i)
213 pull_done[i]=boost::async(boost::launch::async,
214 #if ! defined BOOST_NO_CXX11_LAMBDAS
225 for (unsigned int i = 0; i < n; ++i)
226 BOOST_TEST_EQ(pull_done[i].get(), 42);
227 BOOST_TEST(q.empty());
236 void test_concurrent_push_back_and_pull_front_on_empty_queue()
238 boost::sync_queue<int> q;
240 boost::barrier go(2);
242 boost::future<void> push_done;
243 boost::future<int> pull_done;
247 push_done=boost::async(boost::launch::async,
248 call_push_back<int>(&q,&go));
249 pull_done=boost::async(boost::launch::async,
250 call_pull_front<int>(&q,&go));
253 BOOST_TEST_EQ(pull_done.get(), 42);
254 BOOST_TEST(q.empty());
262 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
263 void test_concurrent_push_back_and_wait_pull_front_on_empty_queue()
265 boost::sync_queue<int> q;
266 const unsigned int n = 3;
267 boost::barrier go(n);
269 boost::future<boost::queue_op_status> pull_done[n];
274 for (unsigned int i =0; i< n; ++i)
275 pull_done[i]=boost::async(boost::launch::async,
276 call_wait_pull_front<int>(&q,&go),
277 boost::ref(results[i]));
279 for (unsigned int i =0; i< n; ++i)
282 for (unsigned int i = 0; i < n; ++i) {
283 BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success);
284 BOOST_TEST_EQ(results[i], 42);
286 BOOST_TEST(q.empty());
294 void test_concurrent_wait_pull_front_and_close_on_empty_queue()
296 boost::sync_queue<int> q;
297 const unsigned int n = 3;
298 boost::barrier go(n);
300 boost::future<boost::queue_op_status> pull_done[n];
305 for (unsigned int i =0; i< n; ++i)
306 pull_done[i]=boost::async(boost::launch::async,
307 call_wait_pull_front<int>(&q,&go),
308 boost::ref(results[i]));
312 for (unsigned int i = 0; i < n; ++i) {
313 BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed);
315 BOOST_TEST(q.empty());
324 void test_concurrent_push_back_on_empty_queue()
326 boost::sync_queue<int> q;
327 const unsigned int n = 3;
328 boost::barrier go(n);
329 boost::future<void> push_done[n];
333 for (unsigned int i =0; i< n; ++i)
334 push_done[i]=boost::async(boost::launch::async,
335 call_push_back<int>(&q,&go));
344 for (unsigned int i = 0; i < n; ++i)
354 BOOST_TEST(!q.empty());
355 for (unsigned int i =0; i< n; ++i)
356 BOOST_TEST_EQ(q.pull_front(), 42);
357 BOOST_TEST(q.empty());
366 void test_concurrent_pull_front_on_queue()
368 boost::sync_queue<int> q;
369 const unsigned int n = 3;
370 boost::barrier go(n);
372 boost::future<int> pull_done[n];
376 for (unsigned int i =0; i< n; ++i)
379 for (unsigned int i =0; i< n; ++i)
380 pull_done[i]=boost::async(boost::launch::async,
381 #if ! defined BOOST_NO_CXX11_LAMBDAS
385 return q.pull_front();
388 call_pull_front<int>(&q,&go)
392 for (unsigned int i = 0; i < n; ++i)
393 BOOST_TEST_EQ(pull_done[i].get(), 42);
394 BOOST_TEST(q.empty());
404 #ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD
405 test_concurrent_push_and_pull_on_empty_queue();
406 test_concurrent_push_on_empty_queue();
407 test_concurrent_pull_on_queue();
409 test_concurrent_push_back_and_pull_front_on_empty_queue();
410 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
411 test_concurrent_push_back_and_wait_pull_front_on_empty_queue();
412 test_concurrent_wait_pull_front_and_close_on_empty_queue();
414 test_concurrent_push_back_on_empty_queue();
415 test_concurrent_pull_front_on_queue();
416 return boost::report_errors();