]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/test/io_service.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/io_service.hpp>
20 #include <boost/asio/detail/thread.hpp>
21 #include "unit_test.hpp"
23 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
24 # include <boost/asio/deadline_timer.hpp>
25 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
26 # include <boost/asio/steady_timer.hpp>
27 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
29 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
30 # include <boost/bind.hpp>
31 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
32 # include <functional>
33 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
35 using namespace boost::asio
;
37 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
38 namespace bindns
= boost
;
39 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
40 namespace bindns
= std
;
43 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
44 typedef deadline_timer timer
;
45 namespace chronons
= boost::posix_time
;
46 #elif defined(BOOST_ASIO_HAS_STD_CHRONO)
47 typedef steady_timer timer
;
48 namespace chronons
= std::chrono
;
49 #elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
50 typedef steady_timer timer
;
51 namespace chronons
= boost::chrono
;
52 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
54 void increment(int* count
)
59 void decrement_to_zero(io_service
* ios
, int* count
)
65 int before_value
= *count
;
66 ios
->post(bindns::bind(decrement_to_zero
, ios
, count
));
68 // Handler execution cannot nest, so count value should remain unchanged.
69 BOOST_ASIO_CHECK(*count
== before_value
);
73 void nested_decrement_to_zero(io_service
* ios
, int* count
)
79 ios
->dispatch(bindns::bind(nested_decrement_to_zero
, ios
, count
));
81 // Handler execution is nested, so count value should now be zero.
82 BOOST_ASIO_CHECK(*count
== 0);
86 void sleep_increment(io_service
* ios
, int* count
)
88 timer
t(*ios
, chronons::seconds(2));
92 ios
->post(bindns::bind(sleep_increment
, ios
, count
));
95 void start_sleep_increments(io_service
* ios
, int* count
)
97 // Give all threads a chance to start.
98 timer
t(*ios
, chronons::seconds(2));
101 // Start the first of three increments.
102 ios
->post(bindns::bind(sleep_increment
, ios
, count
));
105 void throw_exception()
110 void io_service_run(io_service
* ios
)
115 void io_service_test()
120 ios
.post(bindns::bind(increment
, &count
));
122 // No handlers can be called until run() is called.
123 BOOST_ASIO_CHECK(!ios
.stopped());
124 BOOST_ASIO_CHECK(count
== 0);
128 // The run() call will not return until all work has finished.
129 BOOST_ASIO_CHECK(ios
.stopped());
130 BOOST_ASIO_CHECK(count
== 1);
134 ios
.post(bindns::bind(increment
, &count
));
135 ios
.post(bindns::bind(increment
, &count
));
136 ios
.post(bindns::bind(increment
, &count
));
137 ios
.post(bindns::bind(increment
, &count
));
138 ios
.post(bindns::bind(increment
, &count
));
140 // No handlers can be called until run() is called.
141 BOOST_ASIO_CHECK(!ios
.stopped());
142 BOOST_ASIO_CHECK(count
== 0);
146 // The run() call will not return until all work has finished.
147 BOOST_ASIO_CHECK(ios
.stopped());
148 BOOST_ASIO_CHECK(count
== 5);
152 io_service::work
* w
= new io_service::work(ios
);
153 ios
.post(bindns::bind(&io_service::stop
, &ios
));
154 BOOST_ASIO_CHECK(!ios
.stopped());
157 // The only operation executed should have been to stop run().
158 BOOST_ASIO_CHECK(ios
.stopped());
159 BOOST_ASIO_CHECK(count
== 0);
162 ios
.post(bindns::bind(increment
, &count
));
165 // No handlers can be called until run() is called.
166 BOOST_ASIO_CHECK(!ios
.stopped());
167 BOOST_ASIO_CHECK(count
== 0);
171 // The run() call will not return until all work has finished.
172 BOOST_ASIO_CHECK(ios
.stopped());
173 BOOST_ASIO_CHECK(count
== 1);
177 ios
.post(bindns::bind(decrement_to_zero
, &ios
, &count
));
179 // No handlers can be called until run() is called.
180 BOOST_ASIO_CHECK(!ios
.stopped());
181 BOOST_ASIO_CHECK(count
== 10);
185 // The run() call will not return until all work has finished.
186 BOOST_ASIO_CHECK(ios
.stopped());
187 BOOST_ASIO_CHECK(count
== 0);
191 ios
.post(bindns::bind(nested_decrement_to_zero
, &ios
, &count
));
193 // No handlers can be called until run() is called.
194 BOOST_ASIO_CHECK(!ios
.stopped());
195 BOOST_ASIO_CHECK(count
== 10);
199 // The run() call will not return until all work has finished.
200 BOOST_ASIO_CHECK(ios
.stopped());
201 BOOST_ASIO_CHECK(count
== 0);
205 ios
.dispatch(bindns::bind(nested_decrement_to_zero
, &ios
, &count
));
207 // No handlers can be called until run() is called, even though nested
208 // delivery was specifically allowed in the previous call.
209 BOOST_ASIO_CHECK(!ios
.stopped());
210 BOOST_ASIO_CHECK(count
== 10);
214 // The run() call will not return until all work has finished.
215 BOOST_ASIO_CHECK(ios
.stopped());
216 BOOST_ASIO_CHECK(count
== 0);
221 BOOST_ASIO_CHECK(!ios
.stopped());
222 ios
.post(bindns::bind(start_sleep_increments
, &ios
, &count
));
223 ios
.post(bindns::bind(start_sleep_increments
, &ios
, &count2
));
224 boost::asio::detail::thread
thread1(bindns::bind(io_service_run
, &ios
));
225 boost::asio::detail::thread
thread2(bindns::bind(io_service_run
, &ios
));
229 // The run() calls will not return until all work has finished.
230 BOOST_ASIO_CHECK(ios
.stopped());
231 BOOST_ASIO_CHECK(count
== 3);
232 BOOST_ASIO_CHECK(count2
== 3);
236 ios
.dispatch(ios2
.wrap(bindns::bind(decrement_to_zero
, &ios2
, &count
)));
238 BOOST_ASIO_CHECK(!ios
.stopped());
241 // No decrement_to_zero handlers can be called until run() is called on the
242 // second io_service object.
243 BOOST_ASIO_CHECK(ios
.stopped());
244 BOOST_ASIO_CHECK(count
== 10);
248 // The run() call will not return until all work has finished.
249 BOOST_ASIO_CHECK(count
== 0);
252 int exception_count
= 0;
254 ios
.post(&throw_exception
);
255 ios
.post(bindns::bind(increment
, &count
));
256 ios
.post(bindns::bind(increment
, &count
));
257 ios
.post(&throw_exception
);
258 ios
.post(bindns::bind(increment
, &count
));
260 // No handlers can be called until run() is called.
261 BOOST_ASIO_CHECK(!ios
.stopped());
262 BOOST_ASIO_CHECK(count
== 0);
263 BOOST_ASIO_CHECK(exception_count
== 0);
278 // The run() calls will not return until all work has finished.
279 BOOST_ASIO_CHECK(ios
.stopped());
280 BOOST_ASIO_CHECK(count
== 3);
281 BOOST_ASIO_CHECK(exception_count
== 2);
284 class test_service
: public boost::asio::io_service::service
287 static boost::asio::io_service::id id
;
288 test_service(boost::asio::io_service
& s
)
289 : boost::asio::io_service::service(s
) {}
291 virtual void shutdown_service() {}
294 boost::asio::io_service::id
test_service::id
;
296 void io_service_service_test()
298 boost::asio::io_service ios1
;
299 boost::asio::io_service ios2
;
300 boost::asio::io_service ios3
;
302 // Implicit service registration.
304 boost::asio::use_service
<test_service
>(ios1
);
306 BOOST_ASIO_CHECK(boost::asio::has_service
<test_service
>(ios1
));
308 test_service
* svc1
= new test_service(ios1
);
311 boost::asio::add_service(ios1
, svc1
);
312 BOOST_ASIO_ERROR("add_service did not throw");
314 catch (boost::asio::service_already_exists
&)
319 // Explicit service registration.
321 test_service
* svc2
= new test_service(ios2
);
322 boost::asio::add_service(ios2
, svc2
);
324 BOOST_ASIO_CHECK(boost::asio::has_service
<test_service
>(ios2
));
325 BOOST_ASIO_CHECK(&boost::asio::use_service
<test_service
>(ios2
) == svc2
);
327 test_service
* svc3
= new test_service(ios2
);
330 boost::asio::add_service(ios2
, svc3
);
331 BOOST_ASIO_ERROR("add_service did not throw");
333 catch (boost::asio::service_already_exists
&)
338 // Explicit registration with invalid owner.
340 test_service
* svc4
= new test_service(ios2
);
343 boost::asio::add_service(ios3
, svc4
);
344 BOOST_ASIO_ERROR("add_service did not throw");
346 catch (boost::asio::invalid_service_owner
&)
351 BOOST_ASIO_CHECK(!boost::asio::has_service
<test_service
>(ios3
));
354 BOOST_ASIO_TEST_SUITE
357 BOOST_ASIO_TEST_CASE(io_service_test
)
358 BOOST_ASIO_TEST_CASE(io_service_service_test
)