1    	//
2    	// basic_waitable_timer.hpp
3    	// ~~~~~~~~~~~~~~~~~~~~~~~~
4    	//
5    	// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6    	//
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)
9    	//
10   	
11   	#ifndef BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP
12   	#define BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP
13   	
14   	#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15   	# pragma once
16   	#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17   	
18   	#include <boost/asio/detail/config.hpp>
19   	#include <cstddef>
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>
25   	
26   	#if defined(BOOST_ASIO_HAS_MOVE)
27   	# include <utility>
28   	#endif // defined(BOOST_ASIO_HAS_MOVE)
29   	
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)
39   	
40   	#include <boost/asio/detail/push_options.hpp>
41   	
42   	namespace boost {
43   	namespace asio {
44   	
45   	#if !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
46   	#define BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL
47   	
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;
53   	
54   	#endif // !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
55   	
56   	/// Provides waitable timer functionality.
57   	/**
58   	 * The basic_waitable_timer class template provides the ability to perform a
59   	 * blocking or asynchronous wait for a timer to expire.
60   	 *
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.
64   	 *
65   	 * Most applications will use one of the boost::asio::steady_timer,
66   	 * boost::asio::system_timer or boost::asio::high_resolution_timer typedefs.
67   	 *
68   	 * @note This waitable timer functionality is for use with the C++11 standard
69   	 * library's @c &lt;chrono&gt; facility, or with the Boost.Chrono library.
70   	 *
71   	 * @par Thread Safety
72   	 * @e Distinct @e objects: Safe.@n
73   	 * @e Shared @e objects: Unsafe.
74   	 *
75   	 * @par Examples
76   	 * Performing a blocking wait (C++11):
77   	 * @code
78   	 * // Construct a timer without setting an expiry time.
79   	 * boost::asio::steady_timer timer(io_context);
80   	 *
81   	 * // Set an expiry time relative to now.
82   	 * timer.expires_after(std::chrono::seconds(5));
83   	 *
84   	 * // Wait for the timer to expire.
85   	 * timer.wait();
86   	 * @endcode
87   	 *
88   	 * @par 
89   	 * Performing an asynchronous wait (C++11):
90   	 * @code
91   	 * void handler(const boost::system::error_code& error)
92   	 * {
93   	 *   if (!error)
94   	 *   {
95   	 *     // Timer expired.
96   	 *   }
97   	 * }
98   	 *
99   	 * ...
100  	 *
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));
104  	 *
105  	 * // Start an asynchronous wait.
106  	 * timer.async_wait(handler);
107  	 * @endcode
108  	 *
109  	 * @par Changing an active waitable timer's expiry time
110  	 *
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:
114  	 * used:
115  	 *
116  	 * @code
117  	 * void on_some_event()
118  	 * {
119  	 *   if (my_timer.expires_after(seconds(5)) > 0)
120  	 *   {
121  	 *     // We managed to cancel the timer. Start new asynchronous wait.
122  	 *     my_timer.async_wait(on_timeout);
123  	 *   }
124  	 *   else
125  	 *   {
126  	 *     // Too late, timer has already expired!
127  	 *   }
128  	 * }
129  	 *
130  	 * void on_timeout(const boost::system::error_code& e)
131  	 * {
132  	 *   if (e != boost::asio::error::operation_aborted)
133  	 *   {
134  	 *     // Timer was not cancelled, take necessary action.
135  	 *   }
136  	 * }
137  	 * @endcode
138  	 *
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.
144  	 *
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.
147  	 */
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>
151  	{
152  	public:
153  	  /// The type of the executor associated with the object.
154  	  typedef io_context::executor_type executor_type;
155  	
156  	  /// The clock type.
157  	  typedef Clock clock_type;
158  	
159  	  /// The duration type of the clock.
160  	  typedef typename clock_type::duration duration;
161  	
162  	  /// The time point type of the clock.
163  	  typedef typename clock_type::time_point time_point;
164  	
165  	  /// The wait traits type.
166  	  typedef WaitTraits traits_type;
167  	
168  	  /// Constructor.
169  	  /**
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.
173  	   *
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.
176  	   */
177  	  explicit basic_waitable_timer(boost::asio::io_context& io_context)
178  	    : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
179  	  {
180  	  }
181  	
182  	  /// Constructor to set a particular expiry time as an absolute time.
183  	  /**
184  	   * This constructor creates a timer and sets the expiry time.
185  	   *
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.
188  	   *
189  	   * @param expiry_time The expiry time to be used for the timer, expressed
190  	   * as an absolute time.
191  	   */
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)
195  	  {
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");
199  	  }
200  	
201  	  /// Constructor to set a particular expiry time relative to now.
202  	  /**
203  	   * This constructor creates a timer and sets the expiry time.
204  	   *
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.
207  	   *
208  	   * @param expiry_time The expiry time to be used for the timer, relative to
209  	   * now.
210  	   */
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)
214  	  {
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");
219  	  }
220  	
221  	#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
222  	  /// Move-construct a basic_waitable_timer from another.
223  	  /**
224  	   * This constructor moves a timer from one object to another.
225  	   *
226  	   * @param other The other basic_waitable_timer object from which the move will
227  	   * occur.
228  	   *
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.
231  	   */
232  	  basic_waitable_timer(basic_waitable_timer&& other)
233  	    : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
234  	  {
235  	  }
236  	
237  	  /// Move-assign a basic_waitable_timer from another.
238  	  /**
239  	   * This assignment operator moves a timer from one object to another. Cancels
240  	   * any outstanding asynchronous operations associated with the target object.
241  	   *
242  	   * @param other The other basic_waitable_timer object from which the move will
243  	   * occur.
244  	   *
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.
247  	   */
248  	  basic_waitable_timer& operator=(basic_waitable_timer&& other)
249  	  {
250  	    basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
251  	    return *this;
252  	  }
253  	#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
254  	
255  	  /// Destroys the timer.
256  	  /**
257  	   * This function destroys the timer, cancelling any outstanding asynchronous
258  	   * wait operations associated with the timer as if by calling @c cancel.
259  	   */
260  	  ~basic_waitable_timer()
261  	  {
262  	  }
263  	
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
269  	  /// object.
270  	  /**
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.
273  	   *
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.
276  	   */
277  	  boost::asio::io_context& get_io_context()
278  	  {
279  	    return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
280  	  }
281  	
282  	  /// (Deprecated: Use get_executor().) Get the io_context associated with the
283  	  /// object.
284  	  /**
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.
287  	   *
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.
290  	   */
291  	  boost::asio::io_context& get_io_service()
292  	  {
293  	    return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
294  	  }
295  	#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
296  	
297  	  /// Get the executor associated with the object.
298  	  executor_type get_executor() BOOST_ASIO_NOEXCEPT
299  	  {
300  	    return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
301  	  }
302  	#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
303  	
304  	  /// Cancel any asynchronous operations that are waiting on the timer.
305  	  /**
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.
309  	   *
310  	   * Cancelling the timer does not change the expiry time.
311  	   *
312  	   * @return The number of asynchronous operations that were cancelled.
313  	   *
314  	   * @throws boost::system::system_error Thrown on failure.
315  	   *
316  	   * @note If the timer has already expired when cancel() is called, then the
317  	   * handlers for asynchronous wait operations will:
318  	   *
319  	   * @li have already been invoked; or
320  	   *
321  	   * @li have been queued for invocation in the near future.
322  	   *
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.
325  	   */
326  	  std::size_t cancel()
327  	  {
328  	    boost::system::error_code ec;
329  	    std::size_t s = this->get_service().cancel(this->get_implementation(), ec);
(1) Event fun_call_w_exception: Called function throws an exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >". [details]
330  	    boost::asio::detail::throw_error(ec, "cancel");
331  	    return s;
332  	  }
333  	
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.
337  	  /**
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.
341  	   *
342  	   * Cancelling the timer does not change the expiry time.
343  	   *
344  	   * @param ec Set to indicate what error occurred, if any.
345  	   *
346  	   * @return The number of asynchronous operations that were cancelled.
347  	   *
348  	   * @note If the timer has already expired when cancel() is called, then the
349  	   * handlers for asynchronous wait operations will:
350  	   *
351  	   * @li have already been invoked; or
352  	   *
353  	   * @li have been queued for invocation in the near future.
354  	   *
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.
357  	   */
358  	  std::size_t cancel(boost::system::error_code& ec)
359  	  {
360  	    return this->get_service().cancel(this->get_implementation(), ec);
361  	  }
362  	#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
363  	
364  	  /// Cancels one asynchronous operation that is waiting on the timer.
365  	  /**
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.
370  	   *
371  	   * Cancelling the timer does not change the expiry time.
372  	   *
373  	   * @return The number of asynchronous operations that were cancelled. That is,
374  	   * either 0 or 1.
375  	   *
376  	   * @throws boost::system::system_error Thrown on failure.
377  	   *
378  	   * @note If the timer has already expired when cancel_one() is called, then
379  	   * the handlers for asynchronous wait operations will:
380  	   *
381  	   * @li have already been invoked; or
382  	   *
383  	   * @li have been queued for invocation in the near future.
384  	   *
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.
387  	   */
388  	  std::size_t cancel_one()
389  	  {
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");
394  	    return s;
395  	  }
396  	
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.
400  	  /**
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.
405  	   *
406  	   * Cancelling the timer does not change the expiry time.
407  	   *
408  	   * @param ec Set to indicate what error occurred, if any.
409  	   *
410  	   * @return The number of asynchronous operations that were cancelled. That is,
411  	   * either 0 or 1.
412  	   *
413  	   * @note If the timer has already expired when cancel_one() is called, then
414  	   * the handlers for asynchronous wait operations will:
415  	   *
416  	   * @li have already been invoked; or
417  	   *
418  	   * @li have been queued for invocation in the near future.
419  	   *
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.
422  	   */
423  	  std::size_t cancel_one(boost::system::error_code& ec)
424  	  {
425  	    return this->get_service().cancel_one(this->get_implementation(), ec);
426  	  }
427  	
428  	  /// (Deprecated: Use expiry().) Get the timer's expiry time as an absolute
429  	  /// time.
430  	  /**
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.
433  	   */
434  	  time_point expires_at() const
435  	  {
436  	    return this->get_service().expires_at(this->get_implementation());
437  	  }
438  	#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
439  	
440  	  /// Get the timer's expiry time as an absolute time.
441  	  /**
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.
444  	   */
445  	  time_point expiry() const
446  	  {
447  	    return this->get_service().expiry(this->get_implementation());
448  	  }
449  	
450  	  /// Set the timer's expiry time as an absolute time.
451  	  /**
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.
455  	   *
456  	   * @param expiry_time The expiry time to be used for the timer.
457  	   *
458  	   * @return The number of asynchronous operations that were cancelled.
459  	   *
460  	   * @throws boost::system::system_error Thrown on failure.
461  	   *
462  	   * @note If the timer has already expired when expires_at() is called, then
463  	   * the handlers for asynchronous wait operations will:
464  	   *
465  	   * @li have already been invoked; or
466  	   *
467  	   * @li have been queued for invocation in the near future.
468  	   *
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.
471  	   */
472  	  std::size_t expires_at(const time_point& expiry_time)
473  	  {
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");
478  	    return s;
479  	  }
480  	
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.
484  	  /**
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.
488  	   *
489  	   * @param expiry_time The expiry time to be used for the timer.
490  	   *
491  	   * @param ec Set to indicate what error occurred, if any.
492  	   *
493  	   * @return The number of asynchronous operations that were cancelled.
494  	   *
495  	   * @note If the timer has already expired when expires_at() is called, then
496  	   * the handlers for asynchronous wait operations will:
497  	   *
498  	   * @li have already been invoked; or
499  	   *
500  	   * @li have been queued for invocation in the near future.
501  	   *
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.
504  	   */
505  	  std::size_t expires_at(const time_point& expiry_time,
506  	      boost::system::error_code& ec)
507  	  {
508  	    return this->get_service().expires_at(
509  	        this->get_implementation(), expiry_time, ec);
510  	  }
511  	#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
512  	
513  	  /// Set the timer's expiry time relative to now.
514  	  /**
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.
518  	   *
519  	   * @param expiry_time The expiry time to be used for the timer.
520  	   *
521  	   * @return The number of asynchronous operations that were cancelled.
522  	   *
523  	   * @throws boost::system::system_error Thrown on failure.
524  	   *
525  	   * @note If the timer has already expired when expires_after() is called,
526  	   * then the handlers for asynchronous wait operations will:
527  	   *
528  	   * @li have already been invoked; or
529  	   *
530  	   * @li have been queued for invocation in the near future.
531  	   *
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.
534  	   */
535  	  std::size_t expires_after(const duration& expiry_time)
536  	  {
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");
541  	    return s;
542  	  }
543  	
544  	#if !defined(BOOST_ASIO_NO_DEPRECATED)
545  	  /// (Deprecated: Use expiry().) Get the timer's expiry time relative to now.
546  	  /**
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.
549  	   */
550  	  duration expires_from_now() const
551  	  {
552  	    return this->get_service().expires_from_now(this->get_implementation());
553  	  }
554  	
555  	  /// (Deprecated: Use expires_after().) Set the timer's expiry time relative
556  	  /// to now.
557  	  /**
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.
561  	   *
562  	   * @param expiry_time The expiry time to be used for the timer.
563  	   *
564  	   * @return The number of asynchronous operations that were cancelled.
565  	   *
566  	   * @throws boost::system::system_error Thrown on failure.
567  	   *
568  	   * @note If the timer has already expired when expires_from_now() is called,
569  	   * then the handlers for asynchronous wait operations will:
570  	   *
571  	   * @li have already been invoked; or
572  	   *
573  	   * @li have been queued for invocation in the near future.
574  	   *
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.
577  	   */
578  	  std::size_t expires_from_now(const duration& expiry_time)
579  	  {
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");
584  	    return s;
585  	  }
586  	
587  	  /// (Deprecated: Use expires_after().) Set the timer's expiry time relative
588  	  /// to now.
589  	  /**
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.
593  	   *
594  	   * @param expiry_time The expiry time to be used for the timer.
595  	   *
596  	   * @param ec Set to indicate what error occurred, if any.
597  	   *
598  	   * @return The number of asynchronous operations that were cancelled.
599  	   *
600  	   * @note If the timer has already expired when expires_from_now() is called,
601  	   * then the handlers for asynchronous wait operations will:
602  	   *
603  	   * @li have already been invoked; or
604  	   *
605  	   * @li have been queued for invocation in the near future.
606  	   *
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.
609  	   */
610  	  std::size_t expires_from_now(const duration& expiry_time,
611  	      boost::system::error_code& ec)
612  	  {
613  	    return this->get_service().expires_from_now(
614  	        this->get_implementation(), expiry_time, ec);
615  	  }
616  	#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
617  	
618  	  /// Perform a blocking wait on the timer.
619  	  /**
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.
622  	   *
623  	   * @throws boost::system::system_error Thrown on failure.
624  	   */
625  	  void wait()
626  	  {
627  	    boost::system::error_code ec;
628  	    this->get_service().wait(this->get_implementation(), ec);
629  	    boost::asio::detail::throw_error(ec, "wait");
630  	  }
631  	
632  	  /// Perform a blocking wait on the timer.
633  	  /**
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.
636  	   *
637  	   * @param ec Set to indicate what error occurred, if any.
638  	   */
639  	  void wait(boost::system::error_code& ec)
640  	  {
641  	    this->get_service().wait(this->get_implementation(), ec);
642  	  }
643  	
644  	  /// Start an asynchronous wait on the timer.
645  	  /**
646  	   * This function may be used to initiate an asynchronous wait against the
647  	   * timer. It always returns immediately.
648  	   *
649  	   * For each call to async_wait(), the supplied handler will be called exactly
650  	   * once. The handler will be called when:
651  	   *
652  	   * @li The timer has expired.
653  	   *
654  	   * @li The timer was cancelled, in which case the handler is passed the error
655  	   * code boost::asio::error::operation_aborted.
656  	   *
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
659  	   * handler must be:
660  	   * @code void handler(
661  	   *   const boost::system::error_code& error // Result of operation.
662  	   * ); @endcode
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().
667  	   */
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)
672  	  {
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;
676  	
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);
683  	
684  	    this->get_service().async_wait(this->get_implementation(),
685  	        init.completion_handler);
686  	
687  	    return init.result.get();
688  	#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
689  	  }
690  	
691  	private:
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;
696  	};
697  	
698  	} // namespace asio
699  	} // namespace boost
700  	
701  	#include <boost/asio/detail/pop_options.hpp>
702  	
703  	#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
704  	# undef BOOST_ASIO_SVC_T
705  	#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
706  	
707  	#endif // BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP
708