![]() |
|
|||
File indexing completed on 2025-09-15 08:29:55
0001 // 0002 // basic_waitable_timer.hpp 0003 // ~~~~~~~~~~~~~~~~~~~~~~~~ 0004 // 0005 // Copyright (c) 2003-2025 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 <chrono> 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 /// Cancels one asynchronous operation that is waiting on the timer. 0416 /** 0417 * This function forces the completion of one pending asynchronous wait 0418 * operation against the timer. Handlers are cancelled in FIFO order. The 0419 * handler for the cancelled operation will be invoked with the 0420 * boost::asio::error::operation_aborted error code. 0421 * 0422 * Cancelling the timer does not change the expiry time. 0423 * 0424 * @return The number of asynchronous operations that were cancelled. That is, 0425 * either 0 or 1. 0426 * 0427 * @throws boost::system::system_error Thrown on failure. 0428 * 0429 * @note If the timer has already expired when cancel_one() is called, then 0430 * the 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_one() 0440 { 0441 boost::system::error_code ec; 0442 std::size_t s = impl_.get_service().cancel_one( 0443 impl_.get_implementation(), ec); 0444 boost::asio::detail::throw_error(ec, "cancel_one"); 0445 return s; 0446 } 0447 0448 /// Get the timer's expiry time as an absolute time. 0449 /** 0450 * This function may be used to obtain the timer's current expiry time. 0451 * Whether the timer has expired or not does not affect this value. 0452 */ 0453 time_point expiry() const 0454 { 0455 return impl_.get_service().expiry(impl_.get_implementation()); 0456 } 0457 0458 /// Set the timer's expiry time as an absolute time. 0459 /** 0460 * This function sets the expiry time. Any pending asynchronous wait 0461 * operations will be cancelled. The handler for each cancelled operation will 0462 * be invoked with the boost::asio::error::operation_aborted error code. 0463 * 0464 * @param expiry_time The expiry time to be used for the timer. 0465 * 0466 * @return The number of asynchronous operations that were cancelled. 0467 * 0468 * @throws boost::system::system_error Thrown on failure. 0469 * 0470 * @note If the timer has already expired when expires_at() is called, then 0471 * the handlers for asynchronous wait operations will: 0472 * 0473 * @li have already been invoked; or 0474 * 0475 * @li have been queued for invocation in the near future. 0476 * 0477 * These handlers can no longer be cancelled, and therefore are passed an 0478 * error code that indicates the successful completion of the wait operation. 0479 */ 0480 std::size_t expires_at(const time_point& expiry_time) 0481 { 0482 boost::system::error_code ec; 0483 std::size_t s = impl_.get_service().expires_at( 0484 impl_.get_implementation(), expiry_time, ec); 0485 boost::asio::detail::throw_error(ec, "expires_at"); 0486 return s; 0487 } 0488 0489 /// Set the timer's expiry time relative to now. 0490 /** 0491 * This function sets the expiry time. Any pending asynchronous wait 0492 * operations will be cancelled. The handler for each cancelled operation will 0493 * be invoked with the boost::asio::error::operation_aborted error code. 0494 * 0495 * @param expiry_time The expiry time to be used for the timer. 0496 * 0497 * @return The number of asynchronous operations that were cancelled. 0498 * 0499 * @throws boost::system::system_error Thrown on failure. 0500 * 0501 * @note If the timer has already expired when expires_after() is called, 0502 * then the handlers for asynchronous wait operations will: 0503 * 0504 * @li have already been invoked; or 0505 * 0506 * @li have been queued for invocation in the near future. 0507 * 0508 * These handlers can no longer be cancelled, and therefore are passed an 0509 * error code that indicates the successful completion of the wait operation. 0510 */ 0511 std::size_t expires_after(const duration& expiry_time) 0512 { 0513 boost::system::error_code ec; 0514 std::size_t s = impl_.get_service().expires_after( 0515 impl_.get_implementation(), expiry_time, ec); 0516 boost::asio::detail::throw_error(ec, "expires_after"); 0517 return s; 0518 } 0519 0520 /// Perform a blocking wait on the timer. 0521 /** 0522 * This function is used to wait for the timer to expire. This function 0523 * blocks and does not return until the timer has expired. 0524 * 0525 * @throws boost::system::system_error Thrown on failure. 0526 */ 0527 void wait() 0528 { 0529 boost::system::error_code ec; 0530 impl_.get_service().wait(impl_.get_implementation(), ec); 0531 boost::asio::detail::throw_error(ec, "wait"); 0532 } 0533 0534 /// Perform a blocking wait on the timer. 0535 /** 0536 * This function is used to wait for the timer to expire. This function 0537 * blocks and does not return until the timer has expired. 0538 * 0539 * @param ec Set to indicate what error occurred, if any. 0540 */ 0541 void wait(boost::system::error_code& ec) 0542 { 0543 impl_.get_service().wait(impl_.get_implementation(), ec); 0544 } 0545 0546 /// Start an asynchronous wait on the timer. 0547 /** 0548 * This function may be used to initiate an asynchronous wait against the 0549 * timer. It is an initiating function for an @ref asynchronous_operation, 0550 * and always returns immediately. 0551 * 0552 * For each call to async_wait(), the completion handler will be called 0553 * exactly once. The completion handler will be called when: 0554 * 0555 * @li The timer has expired. 0556 * 0557 * @li The timer was cancelled, in which case the handler is passed the error 0558 * code boost::asio::error::operation_aborted. 0559 * 0560 * @param token The @ref completion_token that will be used to produce a 0561 * completion handler, which will be called when the timer expires. Potential 0562 * completion tokens include @ref use_future, @ref use_awaitable, @ref 0563 * yield_context, or a function object with the correct completion signature. 0564 * The function signature of the completion handler must be: 0565 * @code void handler( 0566 * const boost::system::error_code& error // Result of operation. 0567 * ); @endcode 0568 * Regardless of whether the asynchronous operation completes immediately or 0569 * not, the completion handler will not be invoked from within this function. 0570 * On immediate completion, invocation of the handler will be performed in a 0571 * manner equivalent to using boost::asio::async_immediate(). 0572 * 0573 * @par Completion Signature 0574 * @code void(boost::system::error_code) @endcode 0575 * 0576 * @par Per-Operation Cancellation 0577 * This asynchronous operation supports cancellation for the following 0578 * boost::asio::cancellation_type values: 0579 * 0580 * @li @c cancellation_type::terminal 0581 * 0582 * @li @c cancellation_type::partial 0583 * 0584 * @li @c cancellation_type::total 0585 */ 0586 template < 0587 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) 0588 WaitToken = default_completion_token_t<executor_type>> 0589 auto async_wait( 0590 WaitToken&& token = default_completion_token_t<executor_type>()) 0591 -> decltype( 0592 async_initiate<WaitToken, void (boost::system::error_code)>( 0593 declval<initiate_async_wait>(), token)) 0594 { 0595 return async_initiate<WaitToken, void (boost::system::error_code)>( 0596 initiate_async_wait(this), token); 0597 } 0598 0599 private: 0600 // Disallow copying and assignment. 0601 basic_waitable_timer(const basic_waitable_timer&) = delete; 0602 basic_waitable_timer& operator=(const basic_waitable_timer&) = delete; 0603 0604 class initiate_async_wait 0605 { 0606 public: 0607 typedef Executor executor_type; 0608 0609 explicit initiate_async_wait(basic_waitable_timer* self) 0610 : self_(self) 0611 { 0612 } 0613 0614 const executor_type& get_executor() const noexcept 0615 { 0616 return self_->get_executor(); 0617 } 0618 0619 template <typename WaitHandler> 0620 void operator()(WaitHandler&& handler) const 0621 { 0622 // If you get an error on the following line it means that your handler 0623 // does not meet the documented type requirements for a WaitHandler. 0624 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; 0625 0626 detail::non_const_lvalue<WaitHandler> handler2(handler); 0627 self_->impl_.get_service().async_wait( 0628 self_->impl_.get_implementation(), 0629 handler2.value, self_->impl_.get_executor()); 0630 } 0631 0632 private: 0633 basic_waitable_timer* self_; 0634 }; 0635 0636 detail::io_object_impl< 0637 detail::deadline_timer_service< 0638 detail::chrono_time_traits<Clock, WaitTraits>>, 0639 executor_type > impl_; 0640 }; 0641 0642 } // namespace asio 0643 } // namespace boost 0644 0645 #include <boost/asio/detail/pop_options.hpp> 0646 0647 #endif // BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |