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/deadline_timer.hpp>
19 #include "unit_test.hpp"
21 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
23 #include <boost/bind.hpp>
24 #include "archetypes/async_result.hpp"
25 #include <boost/asio/io_service.hpp>
26 #include <boost/asio/placeholders.hpp>
27 #include <boost/asio/detail/thread.hpp>
29 using namespace boost::posix_time
;
31 void increment(int* count
)
36 void decrement_to_zero(boost::asio::deadline_timer
* t
, int* count
)
42 int before_value
= *count
;
44 t
->expires_at(t
->expires_at() + seconds(1));
45 t
->async_wait(boost::bind(decrement_to_zero
, t
, count
));
47 // Completion cannot nest, so count value should remain unchanged.
48 BOOST_ASIO_CHECK(*count
== before_value
);
52 void increment_if_not_cancelled(int* count
,
53 const boost::system::error_code
& ec
)
59 void cancel_timer(boost::asio::deadline_timer
* t
)
61 std::size_t num_cancelled
= t
->cancel();
62 BOOST_ASIO_CHECK(num_cancelled
== 1);
65 void cancel_one_timer(boost::asio::deadline_timer
* t
)
67 std::size_t num_cancelled
= t
->cancel_one();
68 BOOST_ASIO_CHECK(num_cancelled
== 1);
73 #if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
74 return microsec_clock::universal_time();
75 #else // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
76 return second_clock::universal_time();
77 #endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
80 void deadline_timer_test()
82 boost::asio::io_service ios
;
87 boost::asio::deadline_timer
t1(ios
, seconds(1));
90 // The timer must block until after its expiry time.
92 ptime expected_end
= start
+ seconds(1);
93 BOOST_ASIO_CHECK(expected_end
< end
|| expected_end
== end
);
97 boost::asio::deadline_timer
t2(ios
, seconds(1) + microseconds(500000));
100 // The timer must block until after its expiry time.
102 expected_end
= start
+ seconds(1) + microseconds(500000);
103 BOOST_ASIO_CHECK(expected_end
< end
|| expected_end
== end
);
105 t2
.expires_at(t2
.expires_at() + seconds(1));
108 // The timer must block until after its expiry time.
110 expected_end
+= seconds(1);
111 BOOST_ASIO_CHECK(expected_end
< end
|| expected_end
== end
);
115 t2
.expires_from_now(seconds(1) + microseconds(200000));
118 // The timer must block until after its expiry time.
120 expected_end
= start
+ seconds(1) + microseconds(200000);
121 BOOST_ASIO_CHECK(expected_end
< end
|| expected_end
== end
);
125 boost::asio::deadline_timer
t3(ios
, seconds(5));
126 t3
.async_wait(boost::bind(increment
, &count
));
128 // No completions can be delivered until run() is called.
129 BOOST_ASIO_CHECK(count
== 0);
133 // The run() call will not return until all operations have finished, and
134 // this should not be until after the timer's expiry time.
135 BOOST_ASIO_CHECK(count
== 1);
137 expected_end
= start
+ seconds(1);
138 BOOST_ASIO_CHECK(expected_end
< end
|| expected_end
== end
);
143 boost::asio::deadline_timer
t4(ios
, seconds(1));
144 t4
.async_wait(boost::bind(decrement_to_zero
, &t4
, &count
));
146 // No completions can be delivered until run() is called.
147 BOOST_ASIO_CHECK(count
== 3);
152 // The run() call will not return until all operations have finished, and
153 // this should not be until after the timer's final expiry time.
154 BOOST_ASIO_CHECK(count
== 0);
156 expected_end
= start
+ seconds(3);
157 BOOST_ASIO_CHECK(expected_end
< end
|| expected_end
== end
);
162 boost::asio::deadline_timer
t5(ios
, seconds(10));
163 t5
.async_wait(boost::bind(increment_if_not_cancelled
, &count
,
164 boost::asio::placeholders::error
));
165 boost::asio::deadline_timer
t6(ios
, seconds(1));
166 t6
.async_wait(boost::bind(cancel_timer
, &t5
));
168 // No completions can be delivered until run() is called.
169 BOOST_ASIO_CHECK(count
== 0);
174 // The timer should have been cancelled, so count should not have changed.
175 // The total run time should not have been much more than 1 second (and
176 // certainly far less than 10 seconds).
177 BOOST_ASIO_CHECK(count
== 0);
179 expected_end
= start
+ seconds(2);
180 BOOST_ASIO_CHECK(end
< expected_end
);
182 // Wait on the timer again without cancelling it. This time the asynchronous
183 // wait should run to completion and increment the counter.
184 t5
.async_wait(boost::bind(increment_if_not_cancelled
, &count
,
185 boost::asio::placeholders::error
));
190 // The timer should not have been cancelled, so count should have changed.
191 // The total time since the timer was created should be more than 10 seconds.
192 BOOST_ASIO_CHECK(count
== 1);
194 expected_end
= start
+ seconds(10);
195 BOOST_ASIO_CHECK(expected_end
< end
|| expected_end
== end
);
200 // Start two waits on a timer, one of which will be cancelled. The one
201 // which is not cancelled should still run to completion and increment the
203 boost::asio::deadline_timer
t7(ios
, seconds(3));
204 t7
.async_wait(boost::bind(increment_if_not_cancelled
, &count
,
205 boost::asio::placeholders::error
));
206 t7
.async_wait(boost::bind(increment_if_not_cancelled
, &count
,
207 boost::asio::placeholders::error
));
208 boost::asio::deadline_timer
t8(ios
, seconds(1));
209 t8
.async_wait(boost::bind(cancel_one_timer
, &t7
));
214 // One of the waits should not have been cancelled, so count should have
215 // changed. The total time since the timer was created should be more than 3
217 BOOST_ASIO_CHECK(count
== 1);
219 expected_end
= start
+ seconds(3);
220 BOOST_ASIO_CHECK(expected_end
< end
|| expected_end
== end
);
223 void timer_handler(const boost::system::error_code
&)
227 void deadline_timer_cancel_test()
229 static boost::asio::io_service io_service
;
232 boost::asio::deadline_timer t
;
233 timer() : t(io_service
) { t
.expires_at(boost::posix_time::pos_infin
); }
236 timers
[2].t
.async_wait(&timer_handler
);
237 timers
[41].t
.async_wait(&timer_handler
);
238 for (int i
= 10; i
< 20; ++i
)
239 timers
[i
].t
.async_wait(&timer_handler
);
241 BOOST_ASIO_CHECK(timers
[2].t
.cancel() == 1);
242 BOOST_ASIO_CHECK(timers
[41].t
.cancel() == 1);
243 for (int i
= 10; i
< 20; ++i
)
244 BOOST_ASIO_CHECK(timers
[i
].t
.cancel() == 1);
247 struct custom_allocation_timer_handler
249 custom_allocation_timer_handler(int* count
) : count_(count
) {}
250 void operator()(const boost::system::error_code
&) {}
254 void* asio_handler_allocate(std::size_t size
,
255 custom_allocation_timer_handler
* handler
)
257 ++(*handler
->count_
);
258 return ::operator new(size
);
261 void asio_handler_deallocate(void* pointer
, std::size_t,
262 custom_allocation_timer_handler
* handler
)
264 --(*handler
->count_
);
265 ::operator delete(pointer
);
268 void deadline_timer_custom_allocation_test()
270 static boost::asio::io_service io_service
;
273 boost::asio::deadline_timer t
;
274 timer() : t(io_service
) {}
277 int allocation_count
= 0;
279 for (int i
= 0; i
< 50; ++i
)
281 timers
[i
].t
.expires_at(boost::posix_time::pos_infin
);
282 timers
[i
].t
.async_wait(custom_allocation_timer_handler(&allocation_count
));
285 for (int i
= 50; i
< 100; ++i
)
287 timers
[i
].t
.expires_at(boost::posix_time::neg_infin
);
288 timers
[i
].t
.async_wait(custom_allocation_timer_handler(&allocation_count
));
291 for (int i
= 0; i
< 50; ++i
)
292 timers
[i
].t
.cancel();
296 BOOST_ASIO_CHECK(allocation_count
== 0);
299 void io_service_run(boost::asio::io_service
* ios
)
304 void deadline_timer_thread_test()
306 boost::asio::io_service ios
;
307 boost::asio::io_service::work
w(ios
);
308 boost::asio::deadline_timer
t1(ios
);
309 boost::asio::deadline_timer
t2(ios
);
312 boost::asio::detail::thread
th(boost::bind(io_service_run
, &ios
));
314 t2
.expires_from_now(boost::posix_time::seconds(2));
317 t1
.expires_from_now(boost::posix_time::seconds(2));
318 t1
.async_wait(boost::bind(increment
, &count
));
320 t2
.expires_from_now(boost::posix_time::seconds(4));
326 BOOST_ASIO_CHECK(count
== 1);
329 void deadline_timer_async_result_test()
331 boost::asio::io_service ios
;
332 boost::asio::deadline_timer
t1(ios
);
334 t1
.expires_from_now(boost::posix_time::seconds(1));
335 int i
= t1
.async_wait(archetypes::lazy_handler());
336 BOOST_ASIO_CHECK(i
== 42);
341 BOOST_ASIO_TEST_SUITE
344 BOOST_ASIO_TEST_CASE(deadline_timer_test
)
345 BOOST_ASIO_TEST_CASE(deadline_timer_cancel_test
)
346 BOOST_ASIO_TEST_CASE(deadline_timer_custom_allocation_test
)
347 BOOST_ASIO_TEST_CASE(deadline_timer_thread_test
)
348 BOOST_ASIO_TEST_CASE(deadline_timer_async_result_test
)
350 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
351 BOOST_ASIO_TEST_SUITE
354 BOOST_ASIO_TEST_CASE(null_test
)
356 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)