Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:07

0001 //
0002 // basic_waitable_timer.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP
0012 #define BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <cstddef>
0020 #include <utility>
0021 #include <boost/asio/any_io_executor.hpp>
0022 #include <boost/asio/detail/chrono_time_traits.hpp>
0023 #include <boost/asio/detail/deadline_timer_service.hpp>
0024 #include <boost/asio/detail/handler_type_requirements.hpp>
0025 #include <boost/asio/detail/io_object_impl.hpp>
0026 #include <boost/asio/detail/non_const_lvalue.hpp>
0027 #include <boost/asio/detail/throw_error.hpp>
0028 #include <boost/asio/error.hpp>
0029 #include <boost/asio/wait_traits.hpp>
0030 
0031 #include <boost/asio/detail/push_options.hpp>
0032 
0033 namespace boost {
0034 namespace asio {
0035 
0036 #if !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
0037 #define BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL
0038 
0039 // Forward declaration with defaulted arguments.
0040 template <typename Clock,
0041     typename WaitTraits = boost::asio::wait_traits<Clock>,
0042     typename Executor = any_io_executor>
0043 class basic_waitable_timer;
0044 
0045 #endif // !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
0046 
0047 /// Provides waitable timer functionality.
0048 /**
0049  * The basic_waitable_timer class template provides the ability to perform a
0050  * blocking or asynchronous wait for a timer to expire.
0051  *
0052  * A waitable timer is always in one of two states: "expired" or "not expired".
0053  * If the wait() or async_wait() function is called on an expired timer, the
0054  * wait operation will complete immediately.
0055  *
0056  * Most applications will use one of the boost::asio::steady_timer,
0057  * boost::asio::system_timer or boost::asio::high_resolution_timer typedefs.
0058  *
0059  * @note This waitable timer functionality is for use with the C++11 standard
0060  * library's @c &lt;chrono&gt; facility, or with the Boost.Chrono library.
0061  *
0062  * @par Thread Safety
0063  * @e Distinct @e objects: Safe.@n
0064  * @e Shared @e objects: Unsafe.
0065  *
0066  * @par Examples
0067  * Performing a blocking wait (C++11):
0068  * @code
0069  * // Construct a timer without setting an expiry time.
0070  * boost::asio::steady_timer timer(my_context);
0071  *
0072  * // Set an expiry time relative to now.
0073  * timer.expires_after(std::chrono::seconds(5));
0074  *
0075  * // Wait for the timer to expire.
0076  * timer.wait();
0077  * @endcode
0078  *
0079  * @par 
0080  * Performing an asynchronous wait (C++11):
0081  * @code
0082  * void handler(const boost::system::error_code& error)
0083  * {
0084  *   if (!error)
0085  *   {
0086  *     // Timer expired.
0087  *   }
0088  * }
0089  *
0090  * ...
0091  *
0092  * // Construct a timer with an absolute expiry time.
0093  * boost::asio::steady_timer timer(my_context,
0094  *     std::chrono::steady_clock::now() + std::chrono::seconds(60));
0095  *
0096  * // Start an asynchronous wait.
0097  * timer.async_wait(handler);
0098  * @endcode
0099  *
0100  * @par Changing an active waitable timer's expiry time
0101  *
0102  * Changing the expiry time of a timer while there are pending asynchronous
0103  * waits causes those wait operations to be cancelled. To ensure that the action
0104  * associated with the timer is performed only once, use something like this:
0105  * used:
0106  *
0107  * @code
0108  * void on_some_event()
0109  * {
0110  *   if (my_timer.expires_after(seconds(5)) > 0)
0111  *   {
0112  *     // We managed to cancel the timer. Start new asynchronous wait.
0113  *     my_timer.async_wait(on_timeout);
0114  *   }
0115  *   else
0116  *   {
0117  *     // Too late, timer has already expired!
0118  *   }
0119  * }
0120  *
0121  * void on_timeout(const boost::system::error_code& e)
0122  * {
0123  *   if (e != boost::asio::error::operation_aborted)
0124  *   {
0125  *     // Timer was not cancelled, take necessary action.
0126  *   }
0127  * }
0128  * @endcode
0129  *
0130  * @li The boost::asio::basic_waitable_timer::expires_after() function
0131  * cancels any pending asynchronous waits, and returns the number of
0132  * asynchronous waits that were cancelled. If it returns 0 then you were too
0133  * late and the wait handler has already been executed, or will soon be
0134  * executed. If it returns 1 then the wait handler was successfully cancelled.
0135  *
0136  * @li If a wait handler is cancelled, the boost::system::error_code passed to
0137  * it contains the value boost::asio::error::operation_aborted.
0138  */
0139 template <typename Clock, typename WaitTraits, typename Executor>
0140 class basic_waitable_timer
0141 {
0142 private:
0143   class initiate_async_wait;
0144 
0145 public:
0146   /// The type of the executor associated with the object.
0147   typedef Executor executor_type;
0148 
0149   /// Rebinds the timer type to another executor.
0150   template <typename Executor1>
0151   struct rebind_executor
0152   {
0153     /// The timer type when rebound to the specified executor.
0154     typedef basic_waitable_timer<Clock, WaitTraits, Executor1> other;
0155   };
0156 
0157   /// The clock type.
0158   typedef Clock clock_type;
0159 
0160   /// The duration type of the clock.
0161   typedef typename clock_type::duration duration;
0162 
0163   /// The time point type of the clock.
0164   typedef typename clock_type::time_point time_point;
0165 
0166   /// The wait traits type.
0167   typedef WaitTraits traits_type;
0168 
0169   /// Constructor.
0170   /**
0171    * This constructor creates a timer without setting an expiry time. The
0172    * expires_at() or expires_after() functions must be called to set an expiry
0173    * time before the timer can be waited on.
0174    *
0175    * @param ex The I/O executor that the timer will use, by default, to
0176    * dispatch handlers for any asynchronous operations performed on the timer.
0177    */
0178   explicit basic_waitable_timer(const executor_type& ex)
0179     : impl_(0, ex)
0180   {
0181   }
0182 
0183   /// Constructor.
0184   /**
0185    * This constructor creates a timer without setting an expiry time. The
0186    * expires_at() or expires_after() functions must be called to set an expiry
0187    * time before the timer can be waited on.
0188    *
0189    * @param context An execution context which provides the I/O executor that
0190    * the timer will use, by default, to dispatch handlers for any asynchronous
0191    * operations performed on the timer.
0192    */
0193   template <typename ExecutionContext>
0194   explicit basic_waitable_timer(ExecutionContext& context,
0195       constraint_t<
0196         is_convertible<ExecutionContext&, execution_context&>::value
0197       > = 0)
0198     : impl_(0, 0, context)
0199   {
0200   }
0201 
0202   /// Constructor to set a particular expiry time as an absolute time.
0203   /**
0204    * This constructor creates a timer and sets the expiry time.
0205    *
0206    * @param ex The I/O executor object that the timer will use, by default, to
0207    * dispatch handlers for any asynchronous operations performed on the timer.
0208    *
0209    * @param expiry_time The expiry time to be used for the timer, expressed
0210    * as an absolute time.
0211    */
0212   basic_waitable_timer(const executor_type& ex, const time_point& expiry_time)
0213     : impl_(0, ex)
0214   {
0215     boost::system::error_code ec;
0216     impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
0217     boost::asio::detail::throw_error(ec, "expires_at");
0218   }
0219 
0220   /// Constructor to set a particular expiry time as an absolute time.
0221   /**
0222    * This constructor creates a timer and sets the expiry time.
0223    *
0224    * @param context An execution context which provides the I/O executor that
0225    * the timer will use, by default, to dispatch handlers for any asynchronous
0226    * operations performed on the timer.
0227    *
0228    * @param expiry_time The expiry time to be used for the timer, expressed
0229    * as an absolute time.
0230    */
0231   template <typename ExecutionContext>
0232   explicit basic_waitable_timer(ExecutionContext& context,
0233       const time_point& expiry_time,
0234       constraint_t<
0235         is_convertible<ExecutionContext&, execution_context&>::value
0236       > = 0)
0237     : impl_(0, 0, context)
0238   {
0239     boost::system::error_code ec;
0240     impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
0241     boost::asio::detail::throw_error(ec, "expires_at");
0242   }
0243 
0244   /// Constructor to set a particular expiry time relative to now.
0245   /**
0246    * This constructor creates a timer and sets the expiry time.
0247    *
0248    * @param ex The I/O executor that the timer will use, by default, to
0249    * dispatch handlers for any asynchronous operations performed on the timer.
0250    *
0251    * @param expiry_time The expiry time to be used for the timer, relative to
0252    * now.
0253    */
0254   basic_waitable_timer(const executor_type& ex, const duration& expiry_time)
0255     : impl_(0, ex)
0256   {
0257     boost::system::error_code ec;
0258     impl_.get_service().expires_after(
0259         impl_.get_implementation(), expiry_time, ec);
0260     boost::asio::detail::throw_error(ec, "expires_after");
0261   }
0262 
0263   /// Constructor to set a particular expiry time relative to now.
0264   /**
0265    * This constructor creates a timer and sets the expiry time.
0266    *
0267    * @param context An execution context which provides the I/O executor that
0268    * the timer will use, by default, to dispatch handlers for any asynchronous
0269    * operations performed on the timer.
0270    *
0271    * @param expiry_time The expiry time to be used for the timer, relative to
0272    * now.
0273    */
0274   template <typename ExecutionContext>
0275   explicit basic_waitable_timer(ExecutionContext& context,
0276       const duration& expiry_time,
0277       constraint_t<
0278         is_convertible<ExecutionContext&, execution_context&>::value
0279       > = 0)
0280     : impl_(0, 0, context)
0281   {
0282     boost::system::error_code ec;
0283     impl_.get_service().expires_after(
0284         impl_.get_implementation(), expiry_time, ec);
0285     boost::asio::detail::throw_error(ec, "expires_after");
0286   }
0287 
0288   /// Move-construct a basic_waitable_timer from another.
0289   /**
0290    * This constructor moves a timer from one object to another.
0291    *
0292    * @param other The other basic_waitable_timer object from which the move will
0293    * occur.
0294    *
0295    * @note Following the move, the moved-from object is in the same state as if
0296    * constructed using the @c basic_waitable_timer(const executor_type&)
0297    * constructor.
0298    */
0299   basic_waitable_timer(basic_waitable_timer&& other)
0300     : impl_(std::move(other.impl_))
0301   {
0302   }
0303 
0304   /// Move-assign a basic_waitable_timer from another.
0305   /**
0306    * This assignment operator moves a timer from one object to another. Cancels
0307    * any outstanding asynchronous operations associated with the target object.
0308    *
0309    * @param other The other basic_waitable_timer object from which the move will
0310    * occur.
0311    *
0312    * @note Following the move, the moved-from object is in the same state as if
0313    * constructed using the @c basic_waitable_timer(const executor_type&)
0314    * constructor.
0315    */
0316   basic_waitable_timer& operator=(basic_waitable_timer&& other)
0317   {
0318     impl_ = std::move(other.impl_);
0319     return *this;
0320   }
0321 
0322   // All timers have access to each other's implementations.
0323   template <typename Clock1, typename WaitTraits1, typename Executor1>
0324   friend class basic_waitable_timer;
0325 
0326   /// Move-construct a basic_waitable_timer from another.
0327   /**
0328    * This constructor moves a timer from one object to another.
0329    *
0330    * @param other The other basic_waitable_timer object from which the move will
0331    * occur.
0332    *
0333    * @note Following the move, the moved-from object is in the same state as if
0334    * constructed using the @c basic_waitable_timer(const executor_type&)
0335    * constructor.
0336    */
0337   template <typename Executor1>
0338   basic_waitable_timer(
0339       basic_waitable_timer<Clock, WaitTraits, Executor1>&& other,
0340       constraint_t<
0341         is_convertible<Executor1, Executor>::value
0342       > = 0)
0343     : impl_(std::move(other.impl_))
0344   {
0345   }
0346 
0347   /// Move-assign a basic_waitable_timer from another.
0348   /**
0349    * This assignment operator moves a timer from one object to another. Cancels
0350    * any outstanding asynchronous operations associated with the target object.
0351    *
0352    * @param other The other basic_waitable_timer object from which the move will
0353    * occur.
0354    *
0355    * @note Following the move, the moved-from object is in the same state as if
0356    * constructed using the @c basic_waitable_timer(const executor_type&)
0357    * constructor.
0358    */
0359   template <typename Executor1>
0360   constraint_t<
0361     is_convertible<Executor1, Executor>::value,
0362     basic_waitable_timer&
0363   > operator=(basic_waitable_timer<Clock, WaitTraits, Executor1>&& other)
0364   {
0365     basic_waitable_timer tmp(std::move(other));
0366     impl_ = std::move(tmp.impl_);
0367     return *this;
0368   }
0369 
0370   /// Destroys the timer.
0371   /**
0372    * This function destroys the timer, cancelling any outstanding asynchronous
0373    * wait operations associated with the timer as if by calling @c cancel.
0374    */
0375   ~basic_waitable_timer()
0376   {
0377   }
0378 
0379   /// Get the executor associated with the object.
0380   const executor_type& get_executor() noexcept
0381   {
0382     return impl_.get_executor();
0383   }
0384 
0385   /// Cancel any asynchronous operations that are waiting on the timer.
0386   /**
0387    * This function forces the completion of any pending asynchronous wait
0388    * operations against the timer. The handler for each cancelled operation will
0389    * be invoked with the boost::asio::error::operation_aborted error code.
0390    *
0391    * Cancelling the timer does not change the expiry time.
0392    *
0393    * @return The number of asynchronous operations that were cancelled.
0394    *
0395    * @throws boost::system::system_error Thrown on failure.
0396    *
0397    * @note If the timer has already expired when cancel() is called, then the
0398    * handlers for asynchronous wait operations will:
0399    *
0400    * @li have already been invoked; or
0401    *
0402    * @li have been queued for invocation in the near future.
0403    *
0404    * These handlers can no longer be cancelled, and therefore are passed an
0405    * error code that indicates the successful completion of the wait operation.
0406    */
0407   std::size_t cancel()
0408   {
0409     boost::system::error_code ec;
0410     std::size_t s = impl_.get_service().cancel(impl_.get_implementation(), ec);
0411     boost::asio::detail::throw_error(ec, "cancel");
0412     return s;
0413   }
0414 
0415 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0416   /// (Deprecated: Use non-error_code overload.) Cancel any asynchronous
0417   /// operations that are waiting on the timer.
0418   /**
0419    * This function forces the completion of any pending asynchronous wait
0420    * operations against the timer. The handler for each cancelled operation will
0421    * be invoked with the boost::asio::error::operation_aborted error code.
0422    *
0423    * Cancelling the timer does not change the expiry time.
0424    *
0425    * @param ec Set to indicate what error occurred, if any.
0426    *
0427    * @return The number of asynchronous operations that were cancelled.
0428    *
0429    * @note If the timer has already expired when cancel() is called, then the
0430    * handlers for asynchronous wait operations will:
0431    *
0432    * @li have already been invoked; or
0433    *
0434    * @li have been queued for invocation in the near future.
0435    *
0436    * These handlers can no longer be cancelled, and therefore are passed an
0437    * error code that indicates the successful completion of the wait operation.
0438    */
0439   std::size_t cancel(boost::system::error_code& ec)
0440   {
0441     return impl_.get_service().cancel(impl_.get_implementation(), ec);
0442   }
0443 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0444 
0445   /// Cancels one asynchronous operation that is waiting on the timer.
0446   /**
0447    * This function forces the completion of one pending asynchronous wait
0448    * operation against the timer. Handlers are cancelled in FIFO order. The
0449    * handler for the cancelled operation will be invoked with the
0450    * boost::asio::error::operation_aborted error code.
0451    *
0452    * Cancelling the timer does not change the expiry time.
0453    *
0454    * @return The number of asynchronous operations that were cancelled. That is,
0455    * either 0 or 1.
0456    *
0457    * @throws boost::system::system_error Thrown on failure.
0458    *
0459    * @note If the timer has already expired when cancel_one() is called, then
0460    * the handlers for asynchronous wait operations will:
0461    *
0462    * @li have already been invoked; or
0463    *
0464    * @li have been queued for invocation in the near future.
0465    *
0466    * These handlers can no longer be cancelled, and therefore are passed an
0467    * error code that indicates the successful completion of the wait operation.
0468    */
0469   std::size_t cancel_one()
0470   {
0471     boost::system::error_code ec;
0472     std::size_t s = impl_.get_service().cancel_one(
0473         impl_.get_implementation(), ec);
0474     boost::asio::detail::throw_error(ec, "cancel_one");
0475     return s;
0476   }
0477 
0478 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0479   /// (Deprecated: Use non-error_code overload.) Cancels one asynchronous
0480   /// operation that is waiting on the timer.
0481   /**
0482    * This function forces the completion of one pending asynchronous wait
0483    * operation against the timer. Handlers are cancelled in FIFO order. The
0484    * handler for the cancelled operation will be invoked with the
0485    * boost::asio::error::operation_aborted error code.
0486    *
0487    * Cancelling the timer does not change the expiry time.
0488    *
0489    * @param ec Set to indicate what error occurred, if any.
0490    *
0491    * @return The number of asynchronous operations that were cancelled. That is,
0492    * either 0 or 1.
0493    *
0494    * @note If the timer has already expired when cancel_one() is called, then
0495    * the handlers for asynchronous wait operations will:
0496    *
0497    * @li have already been invoked; or
0498    *
0499    * @li have been queued for invocation in the near future.
0500    *
0501    * These handlers can no longer be cancelled, and therefore are passed an
0502    * error code that indicates the successful completion of the wait operation.
0503    */
0504   std::size_t cancel_one(boost::system::error_code& ec)
0505   {
0506     return impl_.get_service().cancel_one(impl_.get_implementation(), ec);
0507   }
0508 
0509   /// (Deprecated: Use expiry().) Get the timer's expiry time as an absolute
0510   /// time.
0511   /**
0512    * This function may be used to obtain the timer's current expiry time.
0513    * Whether the timer has expired or not does not affect this value.
0514    */
0515   time_point expires_at() const
0516   {
0517     return impl_.get_service().expires_at(impl_.get_implementation());
0518   }
0519 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0520 
0521   /// Get the timer's expiry time as an absolute time.
0522   /**
0523    * This function may be used to obtain the timer's current expiry time.
0524    * Whether the timer has expired or not does not affect this value.
0525    */
0526   time_point expiry() const
0527   {
0528     return impl_.get_service().expiry(impl_.get_implementation());
0529   }
0530 
0531   /// Set the timer's expiry time as an absolute time.
0532   /**
0533    * This function sets the expiry time. Any pending asynchronous wait
0534    * operations will be cancelled. The handler for each cancelled operation will
0535    * be invoked with the boost::asio::error::operation_aborted error code.
0536    *
0537    * @param expiry_time The expiry time to be used for the timer.
0538    *
0539    * @return The number of asynchronous operations that were cancelled.
0540    *
0541    * @throws boost::system::system_error Thrown on failure.
0542    *
0543    * @note If the timer has already expired when expires_at() is called, then
0544    * the handlers for asynchronous wait operations will:
0545    *
0546    * @li have already been invoked; or
0547    *
0548    * @li have been queued for invocation in the near future.
0549    *
0550    * These handlers can no longer be cancelled, and therefore are passed an
0551    * error code that indicates the successful completion of the wait operation.
0552    */
0553   std::size_t expires_at(const time_point& expiry_time)
0554   {
0555     boost::system::error_code ec;
0556     std::size_t s = impl_.get_service().expires_at(
0557         impl_.get_implementation(), expiry_time, ec);
0558     boost::asio::detail::throw_error(ec, "expires_at");
0559     return s;
0560   }
0561 
0562 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0563   /// (Deprecated: Use non-error_code overload.) Set the timer's expiry time as
0564   /// an absolute time.
0565   /**
0566    * This function sets the expiry time. Any pending asynchronous wait
0567    * operations will be cancelled. The handler for each cancelled operation will
0568    * be invoked with the boost::asio::error::operation_aborted error code.
0569    *
0570    * @param expiry_time The expiry time to be used for the timer.
0571    *
0572    * @param ec Set to indicate what error occurred, if any.
0573    *
0574    * @return The number of asynchronous operations that were cancelled.
0575    *
0576    * @note If the timer has already expired when expires_at() is called, then
0577    * the handlers for asynchronous wait operations will:
0578    *
0579    * @li have already been invoked; or
0580    *
0581    * @li have been queued for invocation in the near future.
0582    *
0583    * These handlers can no longer be cancelled, and therefore are passed an
0584    * error code that indicates the successful completion of the wait operation.
0585    */
0586   std::size_t expires_at(const time_point& expiry_time,
0587       boost::system::error_code& ec)
0588   {
0589     return impl_.get_service().expires_at(
0590         impl_.get_implementation(), expiry_time, ec);
0591   }
0592 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0593 
0594   /// Set the timer's expiry time relative to now.
0595   /**
0596    * This function sets the expiry time. Any pending asynchronous wait
0597    * operations will be cancelled. The handler for each cancelled operation will
0598    * be invoked with the boost::asio::error::operation_aborted error code.
0599    *
0600    * @param expiry_time The expiry time to be used for the timer.
0601    *
0602    * @return The number of asynchronous operations that were cancelled.
0603    *
0604    * @throws boost::system::system_error Thrown on failure.
0605    *
0606    * @note If the timer has already expired when expires_after() is called,
0607    * then the handlers for asynchronous wait operations will:
0608    *
0609    * @li have already been invoked; or
0610    *
0611    * @li have been queued for invocation in the near future.
0612    *
0613    * These handlers can no longer be cancelled, and therefore are passed an
0614    * error code that indicates the successful completion of the wait operation.
0615    */
0616   std::size_t expires_after(const duration& expiry_time)
0617   {
0618     boost::system::error_code ec;
0619     std::size_t s = impl_.get_service().expires_after(
0620         impl_.get_implementation(), expiry_time, ec);
0621     boost::asio::detail::throw_error(ec, "expires_after");
0622     return s;
0623   }
0624 
0625 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0626   /// (Deprecated: Use expiry().) Get the timer's expiry time relative to now.
0627   /**
0628    * This function may be used to obtain the timer's current expiry time.
0629    * Whether the timer has expired or not does not affect this value.
0630    */
0631   duration expires_from_now() const
0632   {
0633     return impl_.get_service().expires_from_now(impl_.get_implementation());
0634   }
0635 
0636   /// (Deprecated: Use expires_after().) Set the timer's expiry time relative
0637   /// to now.
0638   /**
0639    * This function sets the expiry time. Any pending asynchronous wait
0640    * operations will be cancelled. The handler for each cancelled operation will
0641    * be invoked with the boost::asio::error::operation_aborted error code.
0642    *
0643    * @param expiry_time The expiry time to be used for the timer.
0644    *
0645    * @return The number of asynchronous operations that were cancelled.
0646    *
0647    * @throws boost::system::system_error Thrown on failure.
0648    *
0649    * @note If the timer has already expired when expires_from_now() is called,
0650    * then the handlers for asynchronous wait operations will:
0651    *
0652    * @li have already been invoked; or
0653    *
0654    * @li have been queued for invocation in the near future.
0655    *
0656    * These handlers can no longer be cancelled, and therefore are passed an
0657    * error code that indicates the successful completion of the wait operation.
0658    */
0659   std::size_t expires_from_now(const duration& expiry_time)
0660   {
0661     boost::system::error_code ec;
0662     std::size_t s = impl_.get_service().expires_from_now(
0663         impl_.get_implementation(), expiry_time, ec);
0664     boost::asio::detail::throw_error(ec, "expires_from_now");
0665     return s;
0666   }
0667 
0668   /// (Deprecated: Use expires_after().) Set the timer's expiry time relative
0669   /// to now.
0670   /**
0671    * This function sets the expiry time. Any pending asynchronous wait
0672    * operations will be cancelled. The handler for each cancelled operation will
0673    * be invoked with the boost::asio::error::operation_aborted error code.
0674    *
0675    * @param expiry_time The expiry time to be used for the timer.
0676    *
0677    * @param ec Set to indicate what error occurred, if any.
0678    *
0679    * @return The number of asynchronous operations that were cancelled.
0680    *
0681    * @note If the timer has already expired when expires_from_now() is called,
0682    * then the handlers for asynchronous wait operations will:
0683    *
0684    * @li have already been invoked; or
0685    *
0686    * @li have been queued for invocation in the near future.
0687    *
0688    * These handlers can no longer be cancelled, and therefore are passed an
0689    * error code that indicates the successful completion of the wait operation.
0690    */
0691   std::size_t expires_from_now(const duration& expiry_time,
0692       boost::system::error_code& ec)
0693   {
0694     return impl_.get_service().expires_from_now(
0695         impl_.get_implementation(), expiry_time, ec);
0696   }
0697 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0698 
0699   /// Perform a blocking wait on the timer.
0700   /**
0701    * This function is used to wait for the timer to expire. This function
0702    * blocks and does not return until the timer has expired.
0703    *
0704    * @throws boost::system::system_error Thrown on failure.
0705    */
0706   void wait()
0707   {
0708     boost::system::error_code ec;
0709     impl_.get_service().wait(impl_.get_implementation(), ec);
0710     boost::asio::detail::throw_error(ec, "wait");
0711   }
0712 
0713   /// Perform a blocking wait on the timer.
0714   /**
0715    * This function is used to wait for the timer to expire. This function
0716    * blocks and does not return until the timer has expired.
0717    *
0718    * @param ec Set to indicate what error occurred, if any.
0719    */
0720   void wait(boost::system::error_code& ec)
0721   {
0722     impl_.get_service().wait(impl_.get_implementation(), ec);
0723   }
0724 
0725   /// Start an asynchronous wait on the timer.
0726   /**
0727    * This function may be used to initiate an asynchronous wait against the
0728    * timer. It is an initiating function for an @ref asynchronous_operation,
0729    * and always returns immediately.
0730    *
0731    * For each call to async_wait(), the completion handler will be called
0732    * exactly once. The completion handler will be called when:
0733    *
0734    * @li The timer has expired.
0735    *
0736    * @li The timer was cancelled, in which case the handler is passed the error
0737    * code boost::asio::error::operation_aborted.
0738    *
0739    * @param token The @ref completion_token that will be used to produce a
0740    * completion handler, which will be called when the timer expires. Potential
0741    * completion tokens include @ref use_future, @ref use_awaitable, @ref
0742    * yield_context, or a function object with the correct completion signature.
0743    * The function signature of the completion handler must be:
0744    * @code void handler(
0745    *   const boost::system::error_code& error // Result of operation.
0746    * ); @endcode
0747    * Regardless of whether the asynchronous operation completes immediately or
0748    * not, the completion handler will not be invoked from within this function.
0749    * On immediate completion, invocation of the handler will be performed in a
0750    * manner equivalent to using boost::asio::post().
0751    *
0752    * @par Completion Signature
0753    * @code void(boost::system::error_code) @endcode
0754    *
0755    * @par Per-Operation Cancellation
0756    * This asynchronous operation supports cancellation for the following
0757    * boost::asio::cancellation_type values:
0758    *
0759    * @li @c cancellation_type::terminal
0760    *
0761    * @li @c cancellation_type::partial
0762    *
0763    * @li @c cancellation_type::total
0764    */
0765   template <
0766       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
0767         WaitToken = default_completion_token_t<executor_type>>
0768   auto async_wait(
0769       WaitToken&& token = default_completion_token_t<executor_type>())
0770     -> decltype(
0771       async_initiate<WaitToken, void (boost::system::error_code)>(
0772         declval<initiate_async_wait>(), token))
0773   {
0774     return async_initiate<WaitToken, void (boost::system::error_code)>(
0775         initiate_async_wait(this), token);
0776   }
0777 
0778 private:
0779   // Disallow copying and assignment.
0780   basic_waitable_timer(const basic_waitable_timer&) = delete;
0781   basic_waitable_timer& operator=(const basic_waitable_timer&) = delete;
0782 
0783   class initiate_async_wait
0784   {
0785   public:
0786     typedef Executor executor_type;
0787 
0788     explicit initiate_async_wait(basic_waitable_timer* self)
0789       : self_(self)
0790     {
0791     }
0792 
0793     const executor_type& get_executor() const noexcept
0794     {
0795       return self_->get_executor();
0796     }
0797 
0798     template <typename WaitHandler>
0799     void operator()(WaitHandler&& handler) const
0800     {
0801       // If you get an error on the following line it means that your handler
0802       // does not meet the documented type requirements for a WaitHandler.
0803       BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
0804 
0805       detail::non_const_lvalue<WaitHandler> handler2(handler);
0806       self_->impl_.get_service().async_wait(
0807           self_->impl_.get_implementation(),
0808           handler2.value, self_->impl_.get_executor());
0809     }
0810 
0811   private:
0812     basic_waitable_timer* self_;
0813   };
0814 
0815   detail::io_object_impl<
0816     detail::deadline_timer_service<
0817       detail::chrono_time_traits<Clock, WaitTraits>>,
0818     executor_type > impl_;
0819 };
0820 
0821 } // namespace asio
0822 } // namespace boost
0823 
0824 #include <boost/asio/detail/pop_options.hpp>
0825 
0826 #endif // BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP