]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/test/strand.cpp
5 // Copyright (c) 2003-2016 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_service.hpp>
21 #include <boost/asio/detail/thread.hpp>
22 #include "unit_test.hpp"
24 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
25 # include <boost/asio/deadline_timer.hpp>
26 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
27 # include <boost/asio/steady_timer.hpp>
28 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
30 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
31 # include <boost/bind.hpp>
32 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
33 # include <functional>
34 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
36 using namespace boost::asio
;
38 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
39 namespace bindns
= boost
;
40 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
41 namespace bindns
= std
;
44 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
45 typedef deadline_timer timer
;
46 namespace chronons
= boost::posix_time
;
47 #elif defined(BOOST_ASIO_HAS_STD_CHRONO)
48 typedef steady_timer timer
;
49 namespace chronons
= std::chrono
;
50 #elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
51 typedef steady_timer timer
;
52 namespace chronons
= boost::chrono
;
53 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
55 void increment(int* count
)
60 void increment_without_lock(io_service::strand
* s
, int* count
)
62 BOOST_ASIO_CHECK(!s
->running_in_this_thread());
64 int original_count
= *count
;
66 s
->dispatch(bindns::bind(increment
, count
));
68 // No other functions are currently executing through the locking dispatcher,
69 // so the previous call to dispatch should have successfully nested.
70 BOOST_ASIO_CHECK(*count
== original_count
+ 1);
73 void increment_with_lock(io_service::strand
* s
, int* count
)
75 BOOST_ASIO_CHECK(s
->running_in_this_thread());
77 int original_count
= *count
;
79 s
->dispatch(bindns::bind(increment
, count
));
81 // The current function already holds the strand's lock, so the
82 // previous call to dispatch should have successfully nested.
83 BOOST_ASIO_CHECK(*count
== original_count
+ 1);
86 void sleep_increment(io_service
* ios
, int* count
)
88 timer
t(*ios
, chronons::seconds(2));
94 void start_sleep_increments(io_service
* ios
, io_service::strand
* s
, int* count
)
96 // Give all threads a chance to start.
97 timer
t(*ios
, chronons::seconds(2));
100 // Start three increments.
101 s
->post(bindns::bind(sleep_increment
, ios
, count
));
102 s
->post(bindns::bind(sleep_increment
, ios
, count
));
103 s
->post(bindns::bind(sleep_increment
, ios
, count
));
106 void throw_exception()
111 void io_service_run(io_service
* ios
)
119 io_service::strand
s(ios
);
122 ios
.post(bindns::bind(increment_without_lock
, &s
, &count
));
124 // No handlers can be called until run() is called.
125 BOOST_ASIO_CHECK(count
== 0);
129 // The run() call will not return until all work has finished.
130 BOOST_ASIO_CHECK(count
== 1);
134 s
.post(bindns::bind(increment_with_lock
, &s
, &count
));
136 // No handlers can be called until run() is called.
137 BOOST_ASIO_CHECK(count
== 0);
141 // The run() call will not return until all work has finished.
142 BOOST_ASIO_CHECK(count
== 1);
146 ios
.post(bindns::bind(start_sleep_increments
, &ios
, &s
, &count
));
147 boost::asio::detail::thread
thread1(bindns::bind(io_service_run
, &ios
));
148 boost::asio::detail::thread
thread2(bindns::bind(io_service_run
, &ios
));
150 // Check all events run one after another even though there are two threads.
151 timer
timer1(ios
, chronons::seconds(3));
153 BOOST_ASIO_CHECK(count
== 0);
154 timer1
.expires_at(timer1
.expires_at() + chronons::seconds(2));
156 BOOST_ASIO_CHECK(count
== 1);
157 timer1
.expires_at(timer1
.expires_at() + chronons::seconds(2));
159 BOOST_ASIO_CHECK(count
== 2);
164 // The run() calls will not return until all work has finished.
165 BOOST_ASIO_CHECK(count
== 3);
168 int exception_count
= 0;
170 s
.post(throw_exception
);
171 s
.post(bindns::bind(increment
, &count
));
172 s
.post(bindns::bind(increment
, &count
));
173 s
.post(throw_exception
);
174 s
.post(bindns::bind(increment
, &count
));
176 // No handlers can be called until run() is called.
177 BOOST_ASIO_CHECK(count
== 0);
178 BOOST_ASIO_CHECK(exception_count
== 0);
193 // The run() calls will not return until all work has finished.
194 BOOST_ASIO_CHECK(count
== 3);
195 BOOST_ASIO_CHECK(exception_count
== 2);
200 // Check for clean shutdown when handlers posted through an orphaned strand
204 s2
.post(bindns::bind(increment
, &count
));
205 s2
.post(bindns::bind(increment
, &count
));
206 s2
.post(bindns::bind(increment
, &count
));
209 // No handlers can be called until run() is called.
210 BOOST_ASIO_CHECK(count
== 0);
213 BOOST_ASIO_TEST_SUITE
216 BOOST_ASIO_TEST_CASE(strand_test
)