]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/test/io_context_strand.cpp
2 // io_context_strand.cpp
3 // ~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2022 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/io_context_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/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()
242 #if !defined(BOOST_ASIO_NO_DEPRECATED)
244 io_context::strand
s(ioc
);
247 s
.wrap(bindns::bind(increment
, &count
))();
249 // No handlers can be called until run() is called.
250 BOOST_ASIO_CHECK(count
== 0);
255 // The run() calls will not return until all work has finished.
256 BOOST_ASIO_CHECK(count
== 1);
259 s
.wrap(increment
)(&count
);
261 // No handlers can be called until run() is called.
262 BOOST_ASIO_CHECK(count
== 0);
267 // The run() calls will not return until all work has finished.
268 BOOST_ASIO_CHECK(count
== 1);
271 s
.wrap(increment_by_a
)(&count
, 1);
273 // No handlers can be called until run() is called.
274 BOOST_ASIO_CHECK(count
== 0);
279 // The run() calls will not return until all work has finished.
280 BOOST_ASIO_CHECK(count
== 1);
283 s
.wrap(increment_by_a_b
)(&count
, 1, 2);
285 // No handlers can be called until run() is called.
286 BOOST_ASIO_CHECK(count
== 0);
291 // The run() calls will not return until all work has finished.
292 BOOST_ASIO_CHECK(count
== 3);
295 s
.wrap(increment_by_a_b_c
)(&count
, 1, 2, 3);
297 // No handlers can be called until run() is called.
298 BOOST_ASIO_CHECK(count
== 0);
303 // The run() calls will not return until all work has finished.
304 BOOST_ASIO_CHECK(count
== 6);
307 s
.wrap(increment_by_a_b_c_d
)(&count
, 1, 2, 3, 4);
309 // No handlers can be called until run() is called.
310 BOOST_ASIO_CHECK(count
== 0);
315 // The run() calls will not return until all work has finished.
316 BOOST_ASIO_CHECK(count
== 10);
317 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
320 BOOST_ASIO_TEST_SUITE
323 BOOST_ASIO_TEST_CASE(strand_test
)
324 BOOST_ASIO_TEST_CASE(strand_wrap_test
)