]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/test/strand.cpp
5 // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 // Disable autolinking for unit tests.
12 #if !defined(BOOST_ALL_NO_LIB)
13 #define BOOST_ALL_NO_LIB 1
14 #endif // !defined(BOOST_ALL_NO_LIB)
16 // Test that header file is self-contained.
17 #include <boost/asio/strand.hpp>
20 #include <boost/asio/io_context.hpp>
21 #include <boost/asio/dispatch.hpp>
22 #include <boost/asio/post.hpp>
23 #include <boost/asio/detail/thread.hpp>
24 #include "unit_test.hpp"
26 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
27 # include <boost/asio/deadline_timer.hpp>
28 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
29 # include <boost/asio/steady_timer.hpp>
30 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
32 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
33 # include <boost/bind.hpp>
34 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
35 # include <functional>
36 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
38 using namespace boost::asio
;
40 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
41 namespace bindns
= boost
;
42 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
43 namespace bindns
= std
;
46 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
47 typedef deadline_timer timer
;
48 namespace chronons
= boost::posix_time
;
49 #elif defined(BOOST_ASIO_HAS_CHRONO)
50 typedef steady_timer timer
;
51 namespace chronons
= boost::asio::chrono
;
52 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
54 void increment(int* count
)
59 void increment_without_lock(io_context::strand
* s
, int* count
)
61 BOOST_ASIO_CHECK(!s
->running_in_this_thread());
63 int original_count
= *count
;
65 dispatch(*s
, bindns::bind(increment
, count
));
67 // No other functions are currently executing through the locking dispatcher,
68 // so the previous call to dispatch should have successfully nested.
69 BOOST_ASIO_CHECK(*count
== original_count
+ 1);
72 void increment_with_lock(io_context::strand
* s
, int* count
)
74 BOOST_ASIO_CHECK(s
->running_in_this_thread());
76 int original_count
= *count
;
78 dispatch(*s
, bindns::bind(increment
, count
));
80 // The current function already holds the strand's lock, so the
81 // previous call to dispatch should have successfully nested.
82 BOOST_ASIO_CHECK(*count
== original_count
+ 1);
85 void sleep_increment(io_context
* ioc
, int* count
)
87 timer
t(*ioc
, chronons::seconds(2));
93 void increment_by_a(int* count
, int a
)
98 void increment_by_a_b(int* count
, int a
, int b
)
103 void increment_by_a_b_c(int* count
, int a
, int b
, int c
)
105 (*count
) += a
+ b
+ c
;
108 void increment_by_a_b_c_d(int* count
, int a
, int b
, int c
, int d
)
110 (*count
) += a
+ b
+ c
+ d
;
113 void start_sleep_increments(io_context
* ioc
, io_context::strand
* s
, int* count
)
115 // Give all threads a chance to start.
116 timer
t(*ioc
, chronons::seconds(2));
119 // Start three increments.
120 post(*s
, bindns::bind(sleep_increment
, ioc
, count
));
121 post(*s
, bindns::bind(sleep_increment
, ioc
, count
));
122 post(*s
, bindns::bind(sleep_increment
, ioc
, count
));
125 void throw_exception()
130 void io_context_run(io_context
* ioc
)
138 io_context::strand
s(ioc
);
141 post(ioc
, bindns::bind(increment_without_lock
, &s
, &count
));
143 // No handlers can be called until run() is called.
144 BOOST_ASIO_CHECK(count
== 0);
148 // The run() call will not return until all work has finished.
149 BOOST_ASIO_CHECK(count
== 1);
153 post(s
, bindns::bind(increment_with_lock
, &s
, &count
));
155 // No handlers can be called until run() is called.
156 BOOST_ASIO_CHECK(count
== 0);
160 // The run() call will not return until all work has finished.
161 BOOST_ASIO_CHECK(count
== 1);
165 post(ioc
, bindns::bind(start_sleep_increments
, &ioc
, &s
, &count
));
166 boost::asio::detail::thread
thread1(bindns::bind(io_context_run
, &ioc
));
167 boost::asio::detail::thread
thread2(bindns::bind(io_context_run
, &ioc
));
169 // Check all events run one after another even though there are two threads.
170 timer
timer1(ioc
, chronons::seconds(3));
172 BOOST_ASIO_CHECK(count
== 0);
173 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
174 timer1
.expires_at(timer1
.expires_at() + chronons::seconds(2));
175 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
176 timer1
.expires_at(timer1
.expiry() + chronons::seconds(2));
177 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
179 BOOST_ASIO_CHECK(count
== 1);
180 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
181 timer1
.expires_at(timer1
.expires_at() + chronons::seconds(2));
182 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
183 timer1
.expires_at(timer1
.expiry() + chronons::seconds(2));
184 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
186 BOOST_ASIO_CHECK(count
== 2);
191 // The run() calls will not return until all work has finished.
192 BOOST_ASIO_CHECK(count
== 3);
195 int exception_count
= 0;
197 post(s
, throw_exception
);
198 post(s
, bindns::bind(increment
, &count
));
199 post(s
, bindns::bind(increment
, &count
));
200 post(s
, throw_exception
);
201 post(s
, bindns::bind(increment
, &count
));
203 // No handlers can be called until run() is called.
204 BOOST_ASIO_CHECK(count
== 0);
205 BOOST_ASIO_CHECK(exception_count
== 0);
220 // The run() calls will not return until all work has finished.
221 BOOST_ASIO_CHECK(count
== 3);
222 BOOST_ASIO_CHECK(exception_count
== 2);
227 // Check for clean shutdown when handlers posted through an orphaned strand
230 io_context::strand
s2(ioc
);
231 post(s2
, bindns::bind(increment
, &count
));
232 post(s2
, bindns::bind(increment
, &count
));
233 post(s2
, bindns::bind(increment
, &count
));
236 // No handlers can be called until run() is called.
237 BOOST_ASIO_CHECK(count
== 0);
240 void strand_wrap_test()
243 io_context::strand
s(ioc
);
246 s
.wrap(bindns::bind(increment
, &count
))();
248 // No handlers can be called until run() is called.
249 BOOST_ASIO_CHECK(count
== 0);
254 // The run() calls will not return until all work has finished.
255 BOOST_ASIO_CHECK(count
== 1);
258 s
.wrap(increment
)(&count
);
260 // No handlers can be called until run() is called.
261 BOOST_ASIO_CHECK(count
== 0);
266 // The run() calls will not return until all work has finished.
267 BOOST_ASIO_CHECK(count
== 1);
270 s
.wrap(increment_by_a
)(&count
, 1);
272 // No handlers can be called until run() is called.
273 BOOST_ASIO_CHECK(count
== 0);
278 // The run() calls will not return until all work has finished.
279 BOOST_ASIO_CHECK(count
== 1);
282 s
.wrap(increment_by_a_b
)(&count
, 1, 2);
284 // No handlers can be called until run() is called.
285 BOOST_ASIO_CHECK(count
== 0);
290 // The run() calls will not return until all work has finished.
291 BOOST_ASIO_CHECK(count
== 3);
294 s
.wrap(increment_by_a_b_c
)(&count
, 1, 2, 3);
296 // No handlers can be called until run() is called.
297 BOOST_ASIO_CHECK(count
== 0);
302 // The run() calls will not return until all work has finished.
303 BOOST_ASIO_CHECK(count
== 6);
306 s
.wrap(increment_by_a_b_c_d
)(&count
, 1, 2, 3, 4);
308 // No handlers can be called until run() is called.
309 BOOST_ASIO_CHECK(count
== 0);
314 // The run() calls will not return until all work has finished.
315 BOOST_ASIO_CHECK(count
== 10);
318 BOOST_ASIO_TEST_SUITE
321 BOOST_ASIO_TEST_CASE(strand_test
)
322 BOOST_ASIO_TEST_CASE(strand_wrap_test
)