]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp
1 // Copyright (C) 2014 Ian Forbed
2 // Copyright (C) 2014 Vicente J. Botet Escriba
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)
8 #include <boost/config.hpp>
9 #if ! defined BOOST_NO_CXX11_DECLTYPE
10 #define BOOST_RESULT_OF_USE_DECLTYPE
13 #define BOOST_THREAD_VERSION 4
14 #define BOOST_THREAD_PROVIDES_EXECUTORS
18 #include <boost/thread/thread.hpp>
19 #include <boost/thread/barrier.hpp>
20 #include <boost/thread/concurrent_queues/sync_priority_queue.hpp>
22 #include <boost/core/lightweight_test.hpp>
25 #pragma warning(disable: 4127) // conditional expression is constant
28 typedef boost::concurrent::sync_priority_queue
<int> sync_pq
;
30 int call_pull(sync_pq
* q
, boost::barrier
* go
)
37 void call_push(sync_pq
* q
, boost::barrier
* go
, int val
)
43 void test_pull(const int n
)
46 BOOST_TEST(pq
.empty());
47 for(int i
= 0; i
< n
; i
++)
51 BOOST_TEST(!pq
.empty());
52 BOOST_TEST_EQ(pq
.size(), std::size_t(n
));
54 BOOST_TEST(pq
.closed());
56 boost::thread_group tg
;
57 for(int i
= 0; i
< n
; i
++)
59 tg
.create_thread(boost::bind(call_pull
, &pq
, &b
));
62 BOOST_TEST(pq
.empty());
65 void test_push(const int n
)
68 BOOST_TEST(pq
.empty());
71 boost::thread_group tg
;
72 for(int i
= 0; i
< n
; i
++)
74 tg
.create_thread(boost::bind(call_push
, &pq
, &b
, i
));
77 BOOST_TEST(!pq
.empty());
78 BOOST_TEST_EQ(pq
.size(), std::size_t(n
));
81 void test_both(const int n
)
84 BOOST_TEST(pq
.empty());
86 boost::barrier
b(2*n
);
87 boost::thread_group tg
;
88 for(int i
= 0; i
< n
; i
++)
90 tg
.create_thread(boost::bind(call_pull
, &pq
, &b
));
91 tg
.create_thread(boost::bind(call_push
, &pq
, &b
, i
));
94 BOOST_TEST(pq
.empty());
95 BOOST_TEST_EQ(pq
.size(), std::size_t(0));
98 void push_range(sync_pq
* q
, const int begin
, const int end
)
100 for(int i
= begin
; i
< end
; i
++)
104 void atomic_pull(sync_pq
* q
, boost::atomic
<int>* sum
)
109 const int val
= q
->pull();
112 catch(std::exception
& ){
119 * This test computes the sum of the first N integers upto $limit using
120 * $n threads for the push operation and $n threads for the pull and count
121 * operation. The push operation push a range of numbers on the queue while
122 * the pull operation pull from the queue and increments an atomic int.
123 * At the end of execution the value of atomic<int> $sum should be the same
124 * as n*(n+1)/2 as this is the closed form solution to this problem.
126 void compute_sum(const int n
)
128 const int limit
= 1000;
130 BOOST_TEST(pq
.empty());
131 boost::atomic
<int> sum(0);
132 boost::thread_group tg1
;
133 boost::thread_group tg2
;
134 for(int i
= 0; i
< n
; i
++)
136 tg1
.create_thread(boost::bind(push_range
, &pq
, i
*(limit
/n
)+1, (i
+1)*(limit
/n
)+1));
137 tg2
.create_thread(boost::bind(atomic_pull
, &pq
, &sum
));
140 pq
.close(); //Wait until all enqueuing is done before closing.
141 BOOST_TEST(pq
.closed());
143 BOOST_TEST(pq
.empty());
144 BOOST_TEST_EQ(sum
.load(), limit
*(limit
+1)/2);
147 void move_between_queues(sync_pq
* q1
, sync_pq
* q2
)
151 const int val
= q1
->pull();
154 catch(std::exception
& ){
161 * This test computes the sum of the first N integers upto $limit by moving
162 * numbers between 2 sync_priority_queues. A range of numbers are pushed onto
163 * one queue by $n threads while $n threads pull from this queue and push onto
164 * another sync_pq. At the end the main thread ensures the the values in the
165 * second queue are in proper order and then sums all the values from this
166 * queue. The sum should match n*(n+1)/2, the closed form solution to this
169 void sum_with_moving(const int n
)
171 const int limit
= 1000;
174 BOOST_TEST(pq1
.empty());
175 BOOST_TEST(pq2
.empty());
176 boost::thread_group tg1
;
177 boost::thread_group tg2
;
178 for(int i
= 0; i
< n
; i
++)
180 tg1
.create_thread(boost::bind(push_range
, &pq1
, i
*(limit
/n
)+1, (i
+1)*(limit
/n
)+1));
181 tg2
.create_thread(boost::bind(move_between_queues
, &pq1
, &pq2
));
184 pq1
.close(); //Wait until all enqueuing is done before closing.
185 BOOST_TEST(pq1
.closed());
187 BOOST_TEST(pq1
.empty());
188 BOOST_TEST(!pq2
.empty());
190 for(int i
= 1000; i
> 0; i
--){
191 const int val
= pq2
.pull();
192 BOOST_TEST_EQ(i
,val
);
195 BOOST_TEST(pq2
.empty());
196 BOOST_TEST_EQ(sum
, limit
*(limit
+1)/2);
201 for(int i
= 1; i
<= 64; i
*= 2)
207 //These numbers must divide 1000
218 return boost::report_errors();