2 // basic_waitable_timer.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~
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 #ifndef BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP
12 #define BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
20 #include <boost/asio/basic_io_object.hpp>
21 #include <boost/asio/detail/handler_type_requirements.hpp>
22 #include <boost/asio/detail/throw_error.hpp>
23 #include <boost/asio/error.hpp>
24 #include <boost/asio/wait_traits.hpp>
26 #if defined(BOOST_ASIO_HAS_MOVE)
28 #endif // defined(BOOST_ASIO_HAS_MOVE)
30 #if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
31 # include <boost/asio/waitable_timer_service.hpp>
32 #else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
33 # include <boost/asio/detail/chrono_time_traits.hpp>
34 # include <boost/asio/detail/deadline_timer_service.hpp>
35 # define BOOST_ASIO_SVC_T \
36 detail::deadline_timer_service< \
37 detail::chrono_time_traits<Clock, WaitTraits> >
38 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
40 #include <boost/asio/detail/push_options.hpp>
45 #if !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
46 #define BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL
48 // Forward declaration with defaulted arguments.
49 template <typename Clock,
50 typename WaitTraits = boost::asio::wait_traits<Clock>
51 BOOST_ASIO_SVC_TPARAM_DEF2(= waitable_timer_service<Clock, WaitTraits>)>
52 class basic_waitable_timer;
54 #endif // !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
56 /// Provides waitable timer functionality.
58 * The basic_waitable_timer class template provides the ability to perform a
59 * blocking or asynchronous wait for a timer to expire.
61 * A waitable timer is always in one of two states: "expired" or "not expired".
62 * If the wait() or async_wait() function is called on an expired timer, the
63 * wait operation will complete immediately.
65 * Most applications will use one of the boost::asio::steady_timer,
66 * boost::asio::system_timer or boost::asio::high_resolution_timer typedefs.
68 * @note This waitable timer functionality is for use with the C++11 standard
69 * library's @c <chrono> facility, or with the Boost.Chrono library.
72 * @e Distinct @e objects: Safe.@n
73 * @e Shared @e objects: Unsafe.
76 * Performing a blocking wait (C++11):
78 * // Construct a timer without setting an expiry time.
79 * boost::asio::steady_timer timer(io_context);
81 * // Set an expiry time relative to now.
82 * timer.expires_after(std::chrono::seconds(5));
84 * // Wait for the timer to expire.
89 * Performing an asynchronous wait (C++11):
91 * void handler(const boost::system::error_code& error)
101 * // Construct a timer with an absolute expiry time.
102 * boost::asio::steady_timer timer(io_context,
103 * std::chrono::steady_clock::now() + std::chrono::seconds(60));
105 * // Start an asynchronous wait.
106 * timer.async_wait(handler);
109 * @par Changing an active waitable timer's expiry time
111 * Changing the expiry time of a timer while there are pending asynchronous
112 * waits causes those wait operations to be cancelled. To ensure that the action
113 * associated with the timer is performed only once, use something like this:
117 * void on_some_event()
119 * if (my_timer.expires_after(seconds(5)) > 0)
121 * // We managed to cancel the timer. Start new asynchronous wait.
122 * my_timer.async_wait(on_timeout);
126 * // Too late, timer has already expired!
130 * void on_timeout(const boost::system::error_code& e)
132 * if (e != boost::asio::error::operation_aborted)
134 * // Timer was not cancelled, take necessary action.
139 * @li The boost::asio::basic_waitable_timer::expires_after() function
140 * cancels any pending asynchronous waits, and returns the number of
141 * asynchronous waits that were cancelled. If it returns 0 then you were too
142 * late and the wait handler has already been executed, or will soon be
143 * executed. If it returns 1 then the wait handler was successfully cancelled.
145 * @li If a wait handler is cancelled, the boost::system::error_code passed to
146 * it contains the value boost::asio::error::operation_aborted.
148 template <typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM>
149 class basic_waitable_timer
150 : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>
153 /// The type of the executor associated with the object.
154 typedef io_context::executor_type executor_type;
157 typedef Clock clock_type;
159 /// The duration type of the clock.
160 typedef typename clock_type::duration duration;
162 /// The time point type of the clock.
163 typedef typename clock_type::time_point time_point;
165 /// The wait traits type.
166 typedef WaitTraits traits_type;
170 * This constructor creates a timer without setting an expiry time. The
171 * expires_at() or expires_after() functions must be called to set an expiry
172 * time before the timer can be waited on.
174 * @param io_context The io_context object that the timer will use to dispatch
175 * handlers for any asynchronous operations performed on the timer.
177 explicit basic_waitable_timer(boost::asio::io_context& io_context)
178 : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
182 /// Constructor to set a particular expiry time as an absolute time.
184 * This constructor creates a timer and sets the expiry time.
186 * @param io_context The io_context object that the timer will use to dispatch
187 * handlers for any asynchronous operations performed on the timer.
189 * @param expiry_time The expiry time to be used for the timer, expressed
190 * as an absolute time.
192 basic_waitable_timer(boost::asio::io_context& io_context,
193 const time_point& expiry_time)
194 : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
196 boost::system::error_code ec;
197 this->get_service().expires_at(this->get_implementation(), expiry_time, ec);
198 boost::asio::detail::throw_error(ec, "expires_at");
201 /// Constructor to set a particular expiry time relative to now.
203 * This constructor creates a timer and sets the expiry time.
205 * @param io_context The io_context object that the timer will use to dispatch
206 * handlers for any asynchronous operations performed on the timer.
208 * @param expiry_time The expiry time to be used for the timer, relative to
211 basic_waitable_timer(boost::asio::io_context& io_context,
212 const duration& expiry_time)
213 : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
215 boost::system::error_code ec;
216 this->get_service().expires_after(
217 this->get_implementation(), expiry_time, ec);
218 boost::asio::detail::throw_error(ec, "expires_after");
221 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
222 /// Move-construct a basic_waitable_timer from another.
224 * This constructor moves a timer from one object to another.
226 * @param other The other basic_waitable_timer object from which the move will
229 * @note Following the move, the moved-from object is in the same state as if
230 * constructed using the @c basic_waitable_timer(io_context&) constructor.
232 basic_waitable_timer(basic_waitable_timer&& other)
233 : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
237 /// Move-assign a basic_waitable_timer from another.
239 * This assignment operator moves a timer from one object to another. Cancels
240 * any outstanding asynchronous operations associated with the target object.
242 * @param other The other basic_waitable_timer object from which the move will
245 * @note Following the move, the moved-from object is in the same state as if
246 * constructed using the @c basic_waitable_timer(io_context&) constructor.
248 basic_waitable_timer& operator=(basic_waitable_timer&& other)
250 basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
253 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
255 /// Destroys the timer.
257 * This function destroys the timer, cancelling any outstanding asynchronous
258 * wait operations associated with the timer as if by calling @c cancel.
260 ~basic_waitable_timer()
264 #if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
265 // These functions are provided by basic_io_object<>.
266 #else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
267 #if !defined(BOOST_ASIO_NO_DEPRECATED)
268 /// (Deprecated: Use get_executor().) Get the io_context associated with the
271 * This function may be used to obtain the io_context object that the I/O
272 * object uses to dispatch handlers for asynchronous operations.
274 * @return A reference to the io_context object that the I/O object will use
275 * to dispatch handlers. Ownership is not transferred to the caller.
277 boost::asio::io_context& get_io_context()
279 return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
282 /// (Deprecated: Use get_executor().) Get the io_context associated with the
285 * This function may be used to obtain the io_context object that the I/O
286 * object uses to dispatch handlers for asynchronous operations.
288 * @return A reference to the io_context object that the I/O object will use
289 * to dispatch handlers. Ownership is not transferred to the caller.
291 boost::asio::io_context& get_io_service()
293 return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
295 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
297 /// Get the executor associated with the object.
298 executor_type get_executor() BOOST_ASIO_NOEXCEPT
300 return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
302 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
304 /// Cancel any asynchronous operations that are waiting on the timer.
306 * This function forces the completion of any pending asynchronous wait
307 * operations against the timer. The handler for each cancelled operation will
308 * be invoked with the boost::asio::error::operation_aborted error code.
310 * Cancelling the timer does not change the expiry time.
312 * @return The number of asynchronous operations that were cancelled.
314 * @throws boost::system::system_error Thrown on failure.
316 * @note If the timer has already expired when cancel() is called, then the
317 * handlers for asynchronous wait operations will:
319 * @li have already been invoked; or
321 * @li have been queued for invocation in the near future.
323 * These handlers can no longer be cancelled, and therefore are passed an
324 * error code that indicates the successful completion of the wait operation.
328 boost::system::error_code ec;
329 std::size_t s = this->get_service().cancel(this->get_implementation(), ec);
330 boost::asio::detail::throw_error(ec, "cancel");
334 #if !defined(BOOST_ASIO_NO_DEPRECATED)
335 /// (Deprecated: Use non-error_code overload.) Cancel any asynchronous
336 /// operations that are waiting on the timer.
338 * This function forces the completion of any pending asynchronous wait
339 * operations against the timer. The handler for each cancelled operation will
340 * be invoked with the boost::asio::error::operation_aborted error code.
342 * Cancelling the timer does not change the expiry time.
344 * @param ec Set to indicate what error occurred, if any.
346 * @return The number of asynchronous operations that were cancelled.
348 * @note If the timer has already expired when cancel() is called, then the
349 * handlers for asynchronous wait operations will:
351 * @li have already been invoked; or
353 * @li have been queued for invocation in the near future.
355 * These handlers can no longer be cancelled, and therefore are passed an
356 * error code that indicates the successful completion of the wait operation.
358 std::size_t cancel(boost::system::error_code& ec)
360 return this->get_service().cancel(this->get_implementation(), ec);
362 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
364 /// Cancels one asynchronous operation that is waiting on the timer.
366 * This function forces the completion of one pending asynchronous wait
367 * operation against the timer. Handlers are cancelled in FIFO order. The
368 * handler for the cancelled operation will be invoked with the
369 * boost::asio::error::operation_aborted error code.
371 * Cancelling the timer does not change the expiry time.
373 * @return The number of asynchronous operations that were cancelled. That is,
376 * @throws boost::system::system_error Thrown on failure.
378 * @note If the timer has already expired when cancel_one() is called, then
379 * the handlers for asynchronous wait operations will:
381 * @li have already been invoked; or
383 * @li have been queued for invocation in the near future.
385 * These handlers can no longer be cancelled, and therefore are passed an
386 * error code that indicates the successful completion of the wait operation.
388 std::size_t cancel_one()
390 boost::system::error_code ec;
391 std::size_t s = this->get_service().cancel_one(
392 this->get_implementation(), ec);
393 boost::asio::detail::throw_error(ec, "cancel_one");
397 #if !defined(BOOST_ASIO_NO_DEPRECATED)
398 /// (Deprecated: Use non-error_code overload.) Cancels one asynchronous
399 /// operation that is waiting on the timer.
401 * This function forces the completion of one pending asynchronous wait
402 * operation against the timer. Handlers are cancelled in FIFO order. The
403 * handler for the cancelled operation will be invoked with the
404 * boost::asio::error::operation_aborted error code.
406 * Cancelling the timer does not change the expiry time.
408 * @param ec Set to indicate what error occurred, if any.
410 * @return The number of asynchronous operations that were cancelled. That is,
413 * @note If the timer has already expired when cancel_one() is called, then
414 * the handlers for asynchronous wait operations will:
416 * @li have already been invoked; or
418 * @li have been queued for invocation in the near future.
420 * These handlers can no longer be cancelled, and therefore are passed an
421 * error code that indicates the successful completion of the wait operation.
423 std::size_t cancel_one(boost::system::error_code& ec)
425 return this->get_service().cancel_one(this->get_implementation(), ec);
428 /// (Deprecated: Use expiry().) Get the timer's expiry time as an absolute
431 * This function may be used to obtain the timer's current expiry time.
432 * Whether the timer has expired or not does not affect this value.
434 time_point expires_at() const
436 return this->get_service().expires_at(this->get_implementation());
438 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
440 /// Get the timer's expiry time as an absolute time.
442 * This function may be used to obtain the timer's current expiry time.
443 * Whether the timer has expired or not does not affect this value.
445 time_point expiry() const
447 return this->get_service().expiry(this->get_implementation());
450 /// Set the timer's expiry time as an absolute time.
452 * This function sets the expiry time. Any pending asynchronous wait
453 * operations will be cancelled. The handler for each cancelled operation will
454 * be invoked with the boost::asio::error::operation_aborted error code.
456 * @param expiry_time The expiry time to be used for the timer.
458 * @return The number of asynchronous operations that were cancelled.
460 * @throws boost::system::system_error Thrown on failure.
462 * @note If the timer has already expired when expires_at() is called, then
463 * the handlers for asynchronous wait operations will:
465 * @li have already been invoked; or
467 * @li have been queued for invocation in the near future.
469 * These handlers can no longer be cancelled, and therefore are passed an
470 * error code that indicates the successful completion of the wait operation.
472 std::size_t expires_at(const time_point& expiry_time)
474 boost::system::error_code ec;
475 std::size_t s = this->get_service().expires_at(
476 this->get_implementation(), expiry_time, ec);
477 boost::asio::detail::throw_error(ec, "expires_at");
481 #if !defined(BOOST_ASIO_NO_DEPRECATED)
482 /// (Deprecated: Use non-error_code overload.) Set the timer's expiry time as
483 /// an absolute time.
485 * This function sets the expiry time. Any pending asynchronous wait
486 * operations will be cancelled. The handler for each cancelled operation will
487 * be invoked with the boost::asio::error::operation_aborted error code.
489 * @param expiry_time The expiry time to be used for the timer.
491 * @param ec Set to indicate what error occurred, if any.
493 * @return The number of asynchronous operations that were cancelled.
495 * @note If the timer has already expired when expires_at() is called, then
496 * the handlers for asynchronous wait operations will:
498 * @li have already been invoked; or
500 * @li have been queued for invocation in the near future.
502 * These handlers can no longer be cancelled, and therefore are passed an
503 * error code that indicates the successful completion of the wait operation.
505 std::size_t expires_at(const time_point& expiry_time,
506 boost::system::error_code& ec)
508 return this->get_service().expires_at(
509 this->get_implementation(), expiry_time, ec);
511 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
513 /// Set the timer's expiry time relative to now.
515 * This function sets the expiry time. Any pending asynchronous wait
516 * operations will be cancelled. The handler for each cancelled operation will
517 * be invoked with the boost::asio::error::operation_aborted error code.
519 * @param expiry_time The expiry time to be used for the timer.
521 * @return The number of asynchronous operations that were cancelled.
523 * @throws boost::system::system_error Thrown on failure.
525 * @note If the timer has already expired when expires_after() is called,
526 * then the handlers for asynchronous wait operations will:
528 * @li have already been invoked; or
530 * @li have been queued for invocation in the near future.
532 * These handlers can no longer be cancelled, and therefore are passed an
533 * error code that indicates the successful completion of the wait operation.
535 std::size_t expires_after(const duration& expiry_time)
537 boost::system::error_code ec;
538 std::size_t s = this->get_service().expires_after(
539 this->get_implementation(), expiry_time, ec);
540 boost::asio::detail::throw_error(ec, "expires_after");
544 #if !defined(BOOST_ASIO_NO_DEPRECATED)
545 /// (Deprecated: Use expiry().) Get the timer's expiry time relative to now.
547 * This function may be used to obtain the timer's current expiry time.
548 * Whether the timer has expired or not does not affect this value.
550 duration expires_from_now() const
552 return this->get_service().expires_from_now(this->get_implementation());
555 /// (Deprecated: Use expires_after().) Set the timer's expiry time relative
558 * This function sets the expiry time. Any pending asynchronous wait
559 * operations will be cancelled. The handler for each cancelled operation will
560 * be invoked with the boost::asio::error::operation_aborted error code.
562 * @param expiry_time The expiry time to be used for the timer.
564 * @return The number of asynchronous operations that were cancelled.
566 * @throws boost::system::system_error Thrown on failure.
568 * @note If the timer has already expired when expires_from_now() is called,
569 * then the handlers for asynchronous wait operations will:
571 * @li have already been invoked; or
573 * @li have been queued for invocation in the near future.
575 * These handlers can no longer be cancelled, and therefore are passed an
576 * error code that indicates the successful completion of the wait operation.
578 std::size_t expires_from_now(const duration& expiry_time)
580 boost::system::error_code ec;
581 std::size_t s = this->get_service().expires_from_now(
582 this->get_implementation(), expiry_time, ec);
583 boost::asio::detail::throw_error(ec, "expires_from_now");
587 /// (Deprecated: Use expires_after().) Set the timer's expiry time relative
590 * This function sets the expiry time. Any pending asynchronous wait
591 * operations will be cancelled. The handler for each cancelled operation will
592 * be invoked with the boost::asio::error::operation_aborted error code.
594 * @param expiry_time The expiry time to be used for the timer.
596 * @param ec Set to indicate what error occurred, if any.
598 * @return The number of asynchronous operations that were cancelled.
600 * @note If the timer has already expired when expires_from_now() is called,
601 * then the handlers for asynchronous wait operations will:
603 * @li have already been invoked; or
605 * @li have been queued for invocation in the near future.
607 * These handlers can no longer be cancelled, and therefore are passed an
608 * error code that indicates the successful completion of the wait operation.
610 std::size_t expires_from_now(const duration& expiry_time,
611 boost::system::error_code& ec)
613 return this->get_service().expires_from_now(
614 this->get_implementation(), expiry_time, ec);
616 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
618 /// Perform a blocking wait on the timer.
620 * This function is used to wait for the timer to expire. This function
621 * blocks and does not return until the timer has expired.
623 * @throws boost::system::system_error Thrown on failure.
627 boost::system::error_code ec;
628 this->get_service().wait(this->get_implementation(), ec);
629 boost::asio::detail::throw_error(ec, "wait");
632 /// Perform a blocking wait on the timer.
634 * This function is used to wait for the timer to expire. This function
635 * blocks and does not return until the timer has expired.
637 * @param ec Set to indicate what error occurred, if any.
639 void wait(boost::system::error_code& ec)
641 this->get_service().wait(this->get_implementation(), ec);
644 /// Start an asynchronous wait on the timer.
646 * This function may be used to initiate an asynchronous wait against the
647 * timer. It always returns immediately.
649 * For each call to async_wait(), the supplied handler will be called exactly
650 * once. The handler will be called when:
652 * @li The timer has expired.
654 * @li The timer was cancelled, in which case the handler is passed the error
655 * code boost::asio::error::operation_aborted.
657 * @param handler The handler to be called when the timer expires. Copies
658 * will be made of the handler as required. The function signature of the
660 * @code void handler(
661 * const boost::system::error_code& error // Result of operation.
663 * Regardless of whether the asynchronous operation completes immediately or
664 * not, the handler will not be invoked from within this function. Invocation
665 * of the handler will be performed in a manner equivalent to using
666 * boost::asio::io_context::post().
668 template <typename WaitHandler>
669 BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
670 void (boost::system::error_code))
671 async_wait(BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
673 // If you get an error on the following line it means that your handler does
674 // not meet the documented type requirements for a WaitHandler.
675 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
677 #if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
678 return this->get_service().async_wait(this->get_implementation(),
679 BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
680 #else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
681 async_completion<WaitHandler,
682 void (boost::system::error_code)> init(handler);
684 this->get_service().async_wait(this->get_implementation(),
685 init.completion_handler);
687 return init.result.get();
688 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
692 // Disallow copying and assignment.
693 basic_waitable_timer(const basic_waitable_timer&) BOOST_ASIO_DELETED;
694 basic_waitable_timer& operator=(
695 const basic_waitable_timer&) BOOST_ASIO_DELETED;
701 #include <boost/asio/detail/pop_options.hpp>
703 #if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
704 # undef BOOST_ASIO_SVC_T
705 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
707 #endif // BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP