1 // 2 // basic_waitable_timer.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 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/any_io_executor.hpp> 21 #include <boost/asio/detail/chrono_time_traits.hpp> 22 #include <boost/asio/detail/deadline_timer_service.hpp> 23 #include <boost/asio/detail/handler_type_requirements.hpp> 24 #include <boost/asio/detail/io_object_impl.hpp> 25 #include <boost/asio/detail/non_const_lvalue.hpp> 26 #include <boost/asio/detail/throw_error.hpp> 27 #include <boost/asio/error.hpp> 28 #include <boost/asio/wait_traits.hpp> 29 30 #if defined(BOOST_ASIO_HAS_MOVE) 31 # include <utility> 32 #endif // defined(BOOST_ASIO_HAS_MOVE) 33 34 #include <boost/asio/detail/push_options.hpp> 35 36 namespace boost { 37 namespace asio { 38 39 #if !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL) 40 #define BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL 41 42 // Forward declaration with defaulted arguments. 43 template <typename Clock, 44 typename WaitTraits = boost::asio::wait_traits<Clock>, 45 typename Executor = any_io_executor> 46 class basic_waitable_timer; 47 48 #endif // !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL) 49 50 /// Provides waitable timer functionality. 51 /** 52 * The basic_waitable_timer class template provides the ability to perform a 53 * blocking or asynchronous wait for a timer to expire. 54 * 55 * A waitable timer is always in one of two states: "expired" or "not expired". 56 * If the wait() or async_wait() function is called on an expired timer, the 57 * wait operation will complete immediately. 58 * 59 * Most applications will use one of the boost::asio::steady_timer, 60 * boost::asio::system_timer or boost::asio::high_resolution_timer typedefs. 61 * 62 * @note This waitable timer functionality is for use with the C++11 standard 63 * library's @c <chrono> facility, or with the Boost.Chrono library. 64 * 65 * @par Thread Safety 66 * @e Distinct @e objects: Safe.@n 67 * @e Shared @e objects: Unsafe. 68 * 69 * @par Examples 70 * Performing a blocking wait (C++11): 71 * @code 72 * // Construct a timer without setting an expiry time. 73 * boost::asio::steady_timer timer(my_context); 74 * 75 * // Set an expiry time relative to now. 76 * timer.expires_after(std::chrono::seconds(5)); 77 * 78 * // Wait for the timer to expire. 79 * timer.wait(); 80 * @endcode 81 * 82 * @par 83 * Performing an asynchronous wait (C++11): 84 * @code 85 * void handler(const boost::system::error_code& error) 86 * { 87 * if (!error) 88 * { 89 * // Timer expired. 90 * } 91 * } 92 * 93 * ... 94 * 95 * // Construct a timer with an absolute expiry time. 96 * boost::asio::steady_timer timer(my_context, 97 * std::chrono::steady_clock::now() + std::chrono::seconds(60)); 98 * 99 * // Start an asynchronous wait. 100 * timer.async_wait(handler); 101 * @endcode 102 * 103 * @par Changing an active waitable timer's expiry time 104 * 105 * Changing the expiry time of a timer while there are pending asynchronous 106 * waits causes those wait operations to be cancelled. To ensure that the action 107 * associated with the timer is performed only once, use something like this: 108 * used: 109 * 110 * @code 111 * void on_some_event() 112 * { 113 * if (my_timer.expires_after(seconds(5)) > 0) 114 * { 115 * // We managed to cancel the timer. Start new asynchronous wait. 116 * my_timer.async_wait(on_timeout); 117 * } 118 * else 119 * { 120 * // Too late, timer has already expired! 121 * } 122 * } 123 * 124 * void on_timeout(const boost::system::error_code& e) 125 * { 126 * if (e != boost::asio::error::operation_aborted) 127 * { 128 * // Timer was not cancelled, take necessary action. 129 * } 130 * } 131 * @endcode 132 * 133 * @li The boost::asio::basic_waitable_timer::expires_after() function 134 * cancels any pending asynchronous waits, and returns the number of 135 * asynchronous waits that were cancelled. If it returns 0 then you were too 136 * late and the wait handler has already been executed, or will soon be 137 * executed. If it returns 1 then the wait handler was successfully cancelled. 138 * 139 * @li If a wait handler is cancelled, the boost::system::error_code passed to 140 * it contains the value boost::asio::error::operation_aborted. 141 */ 142 template <typename Clock, typename WaitTraits, typename Executor> 143 class basic_waitable_timer 144 { 145 public: 146 /// The type of the executor associated with the object. 147 typedef Executor executor_type; 148 149 /// Rebinds the timer type to another executor. 150 template <typename Executor1> 151 struct rebind_executor 152 { 153 /// The timer type when rebound to the specified executor. 154 typedef basic_waitable_timer<Clock, WaitTraits, Executor1> other; 155 }; 156 157 /// The clock type. 158 typedef Clock clock_type; 159 160 /// The duration type of the clock. 161 typedef typename clock_type::duration duration; 162 163 /// The time point type of the clock. 164 typedef typename clock_type::time_point time_point; 165 166 /// The wait traits type. 167 typedef WaitTraits traits_type; 168 169 /// Constructor. 170 /** 171 * This constructor creates a timer without setting an expiry time. The 172 * expires_at() or expires_after() functions must be called to set an expiry 173 * time before the timer can be waited on. 174 * 175 * @param ex The I/O executor that the timer will use, by default, to 176 * dispatch handlers for any asynchronous operations performed on the timer. 177 */ basic_waitable_timer(const executor_type & ex)178 explicit basic_waitable_timer(const executor_type& ex) 179 : impl_(0, ex) 180 { 181 } 182 183 /// Constructor. 184 /** 185 * This constructor creates a timer without setting an expiry time. The 186 * expires_at() or expires_after() functions must be called to set an expiry 187 * time before the timer can be waited on. 188 * 189 * @param context An execution context which provides the I/O executor that 190 * the timer will use, by default, to dispatch handlers for any asynchronous 191 * operations performed on the timer. 192 */ 193 template <typename ExecutionContext> basic_waitable_timer(ExecutionContext & context,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)194 explicit basic_waitable_timer(ExecutionContext& context, 195 typename constraint< 196 is_convertible<ExecutionContext&, execution_context&>::value 197 >::type = 0) 198 : impl_(0, 0, context) 199 { 200 } 201 202 /// Constructor to set a particular expiry time as an absolute time. 203 /** 204 * This constructor creates a timer and sets the expiry time. 205 * 206 * @param ex The I/O executor object that the timer will use, by default, to 207 * dispatch handlers for any asynchronous operations performed on the timer. 208 * 209 * @param expiry_time The expiry time to be used for the timer, expressed 210 * as an absolute time. 211 */ basic_waitable_timer(const executor_type & ex,const time_point & expiry_time)212 basic_waitable_timer(const executor_type& ex, const time_point& expiry_time) 213 : impl_(0, ex) 214 { 215 boost::system::error_code ec; 216 impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec); 217 boost::asio::detail::throw_error(ec, "expires_at"); 218 } 219 220 /// Constructor to set a particular expiry time as an absolute time. 221 /** 222 * This constructor creates a timer and sets the expiry time. 223 * 224 * @param context An execution context which provides the I/O executor that 225 * the timer will use, by default, to dispatch handlers for any asynchronous 226 * operations performed on the timer. 227 * 228 * @param expiry_time The expiry time to be used for the timer, expressed 229 * as an absolute time. 230 */ 231 template <typename ExecutionContext> basic_waitable_timer(ExecutionContext & context,const time_point & expiry_time,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)232 explicit basic_waitable_timer(ExecutionContext& context, 233 const time_point& expiry_time, 234 typename constraint< 235 is_convertible<ExecutionContext&, execution_context&>::value 236 >::type = 0) 237 : impl_(0, 0, context) 238 { 239 boost::system::error_code ec; 240 impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec); 241 boost::asio::detail::throw_error(ec, "expires_at"); 242 } 243 244 /// Constructor to set a particular expiry time relative to now. 245 /** 246 * This constructor creates a timer and sets the expiry time. 247 * 248 * @param ex The I/O executor that the timer will use, by default, to 249 * dispatch handlers for any asynchronous operations performed on the timer. 250 * 251 * @param expiry_time The expiry time to be used for the timer, relative to 252 * now. 253 */ basic_waitable_timer(const executor_type & ex,const duration & expiry_time)254 basic_waitable_timer(const executor_type& ex, const duration& expiry_time) 255 : impl_(0, ex) 256 { 257 boost::system::error_code ec; 258 impl_.get_service().expires_after( 259 impl_.get_implementation(), expiry_time, ec); 260 boost::asio::detail::throw_error(ec, "expires_after"); 261 } 262 263 /// Constructor to set a particular expiry time relative to now. 264 /** 265 * This constructor creates a timer and sets the expiry time. 266 * 267 * @param context An execution context which provides the I/O executor that 268 * the timer will use, by default, to dispatch handlers for any asynchronous 269 * operations performed on the timer. 270 * 271 * @param expiry_time The expiry time to be used for the timer, relative to 272 * now. 273 */ 274 template <typename ExecutionContext> basic_waitable_timer(ExecutionContext & context,const duration & expiry_time,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)275 explicit basic_waitable_timer(ExecutionContext& context, 276 const duration& expiry_time, 277 typename constraint< 278 is_convertible<ExecutionContext&, execution_context&>::value 279 >::type = 0) 280 : impl_(0, 0, context) 281 { 282 boost::system::error_code ec; 283 impl_.get_service().expires_after( 284 impl_.get_implementation(), expiry_time, ec); 285 boost::asio::detail::throw_error(ec, "expires_after"); 286 } 287 288 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 289 /// Move-construct a basic_waitable_timer from another. 290 /** 291 * This constructor moves a timer from one object to another. 292 * 293 * @param other The other basic_waitable_timer object from which the move will 294 * occur. 295 * 296 * @note Following the move, the moved-from object is in the same state as if 297 * constructed using the @c basic_waitable_timer(const executor_type&) 298 * constructor. 299 */ basic_waitable_timer(basic_waitable_timer && other)300 basic_waitable_timer(basic_waitable_timer&& other) 301 : impl_(std::move(other.impl_)) 302 { 303 } 304 305 /// Move-assign a basic_waitable_timer from another. 306 /** 307 * This assignment operator moves a timer from one object to another. Cancels 308 * any outstanding asynchronous operations associated with the target object. 309 * 310 * @param other The other basic_waitable_timer object from which the move will 311 * occur. 312 * 313 * @note Following the move, the moved-from object is in the same state as if 314 * constructed using the @c basic_waitable_timer(const executor_type&) 315 * constructor. 316 */ operator =(basic_waitable_timer && other)317 basic_waitable_timer& operator=(basic_waitable_timer&& other) 318 { 319 impl_ = std::move(other.impl_); 320 return *this; 321 } 322 323 // All timers have access to each other's implementations. 324 template <typename Clock1, typename WaitTraits1, typename Executor1> 325 friend class basic_waitable_timer; 326 327 /// Move-construct a basic_waitable_timer from another. 328 /** 329 * This constructor moves a timer from one object to another. 330 * 331 * @param other The other basic_waitable_timer object from which the move will 332 * occur. 333 * 334 * @note Following the move, the moved-from object is in the same state as if 335 * constructed using the @c basic_waitable_timer(const executor_type&) 336 * constructor. 337 */ 338 template <typename Executor1> basic_waitable_timer(basic_waitable_timer<Clock,WaitTraits,Executor1> && other,typename constraint<is_convertible<Executor1,Executor>::value>::type=0)339 basic_waitable_timer( 340 basic_waitable_timer<Clock, WaitTraits, Executor1>&& other, 341 typename constraint< 342 is_convertible<Executor1, Executor>::value 343 >::type = 0) 344 : impl_(std::move(other.impl_)) 345 { 346 } 347 348 /// Move-assign a basic_waitable_timer from another. 349 /** 350 * This assignment operator moves a timer from one object to another. Cancels 351 * any outstanding asynchronous operations associated with the target object. 352 * 353 * @param other The other basic_waitable_timer object from which the move will 354 * occur. 355 * 356 * @note Following the move, the moved-from object is in the same state as if 357 * constructed using the @c basic_waitable_timer(const executor_type&) 358 * constructor. 359 */ 360 template <typename Executor1> 361 typename constraint< 362 is_convertible<Executor1, Executor>::value, 363 basic_waitable_timer& operator =(basic_waitable_timer<Clock,WaitTraits,Executor1> && other)364 >::type operator=(basic_waitable_timer<Clock, WaitTraits, Executor1>&& other) 365 { 366 basic_waitable_timer tmp(std::move(other)); 367 impl_ = std::move(tmp.impl_); 368 return *this; 369 } 370 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 371 372 /// Destroys the timer. 373 /** 374 * This function destroys the timer, cancelling any outstanding asynchronous 375 * wait operations associated with the timer as if by calling @c cancel. 376 */ ~basic_waitable_timer()377 ~basic_waitable_timer() 378 { 379 } 380 381 /// Get the executor associated with the object. get_executor()382 executor_type get_executor() BOOST_ASIO_NOEXCEPT 383 { 384 return impl_.get_executor(); 385 } 386 387 /// Cancel any asynchronous operations that are waiting on the timer. 388 /** 389 * This function forces the completion of any pending asynchronous wait 390 * operations against the timer. The handler for each cancelled operation will 391 * be invoked with the boost::asio::error::operation_aborted error code. 392 * 393 * Cancelling the timer does not change the expiry time. 394 * 395 * @return The number of asynchronous operations that were cancelled. 396 * 397 * @throws boost::system::system_error Thrown on failure. 398 * 399 * @note If the timer has already expired when cancel() is called, then the 400 * handlers for asynchronous wait operations will: 401 * 402 * @li have already been invoked; or 403 * 404 * @li have been queued for invocation in the near future. 405 * 406 * These handlers can no longer be cancelled, and therefore are passed an 407 * error code that indicates the successful completion of the wait operation. 408 */ cancel()409 std::size_t cancel() 410 { 411 boost::system::error_code ec; 412 std::size_t s = impl_.get_service().cancel(impl_.get_implementation(), ec); 413 boost::asio::detail::throw_error(ec, "cancel"); 414 return s; 415 } 416 417 #if !defined(BOOST_ASIO_NO_DEPRECATED) 418 /// (Deprecated: Use non-error_code overload.) Cancel any asynchronous 419 /// operations that are waiting on the timer. 420 /** 421 * This function forces the completion of any pending asynchronous wait 422 * operations against the timer. The handler for each cancelled operation will 423 * be invoked with the boost::asio::error::operation_aborted error code. 424 * 425 * Cancelling the timer does not change the expiry time. 426 * 427 * @param ec Set to indicate what error occurred, if any. 428 * 429 * @return The number of asynchronous operations that were cancelled. 430 * 431 * @note If the timer has already expired when cancel() is called, then the 432 * handlers for asynchronous wait operations will: 433 * 434 * @li have already been invoked; or 435 * 436 * @li have been queued for invocation in the near future. 437 * 438 * These handlers can no longer be cancelled, and therefore are passed an 439 * error code that indicates the successful completion of the wait operation. 440 */ cancel(boost::system::error_code & ec)441 std::size_t cancel(boost::system::error_code& ec) 442 { 443 return impl_.get_service().cancel(impl_.get_implementation(), ec); 444 } 445 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 446 447 /// Cancels one asynchronous operation that is waiting on the timer. 448 /** 449 * This function forces the completion of one pending asynchronous wait 450 * operation against the timer. Handlers are cancelled in FIFO order. The 451 * handler for the cancelled operation will be invoked with the 452 * boost::asio::error::operation_aborted error code. 453 * 454 * Cancelling the timer does not change the expiry time. 455 * 456 * @return The number of asynchronous operations that were cancelled. That is, 457 * either 0 or 1. 458 * 459 * @throws boost::system::system_error Thrown on failure. 460 * 461 * @note If the timer has already expired when cancel_one() is called, then 462 * the handlers for asynchronous wait operations will: 463 * 464 * @li have already been invoked; or 465 * 466 * @li have been queued for invocation in the near future. 467 * 468 * These handlers can no longer be cancelled, and therefore are passed an 469 * error code that indicates the successful completion of the wait operation. 470 */ cancel_one()471 std::size_t cancel_one() 472 { 473 boost::system::error_code ec; 474 std::size_t s = impl_.get_service().cancel_one( 475 impl_.get_implementation(), ec); 476 boost::asio::detail::throw_error(ec, "cancel_one"); 477 return s; 478 } 479 480 #if !defined(BOOST_ASIO_NO_DEPRECATED) 481 /// (Deprecated: Use non-error_code overload.) Cancels one asynchronous 482 /// operation that is waiting on the timer. 483 /** 484 * This function forces the completion of one pending asynchronous wait 485 * operation against the timer. Handlers are cancelled in FIFO order. The 486 * handler for the cancelled operation will be invoked with the 487 * boost::asio::error::operation_aborted error code. 488 * 489 * Cancelling the timer does not change the expiry time. 490 * 491 * @param ec Set to indicate what error occurred, if any. 492 * 493 * @return The number of asynchronous operations that were cancelled. That is, 494 * either 0 or 1. 495 * 496 * @note If the timer has already expired when cancel_one() is called, then 497 * the handlers for asynchronous wait operations will: 498 * 499 * @li have already been invoked; or 500 * 501 * @li have been queued for invocation in the near future. 502 * 503 * These handlers can no longer be cancelled, and therefore are passed an 504 * error code that indicates the successful completion of the wait operation. 505 */ cancel_one(boost::system::error_code & ec)506 std::size_t cancel_one(boost::system::error_code& ec) 507 { 508 return impl_.get_service().cancel_one(impl_.get_implementation(), ec); 509 } 510 511 /// (Deprecated: Use expiry().) Get the timer's expiry time as an absolute 512 /// time. 513 /** 514 * This function may be used to obtain the timer's current expiry time. 515 * Whether the timer has expired or not does not affect this value. 516 */ expires_at() const517 time_point expires_at() const 518 { 519 return impl_.get_service().expires_at(impl_.get_implementation()); 520 } 521 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 522 523 /// Get the timer's expiry time as an absolute time. 524 /** 525 * This function may be used to obtain the timer's current expiry time. 526 * Whether the timer has expired or not does not affect this value. 527 */ expiry() const528 time_point expiry() const 529 { 530 return impl_.get_service().expiry(impl_.get_implementation()); 531 } 532 533 /// Set the timer's expiry time as an absolute time. 534 /** 535 * This function sets the expiry time. Any pending asynchronous wait 536 * operations will be cancelled. The handler for each cancelled operation will 537 * be invoked with the boost::asio::error::operation_aborted error code. 538 * 539 * @param expiry_time The expiry time to be used for the timer. 540 * 541 * @return The number of asynchronous operations that were cancelled. 542 * 543 * @throws boost::system::system_error Thrown on failure. 544 * 545 * @note If the timer has already expired when expires_at() is called, then 546 * the handlers for asynchronous wait operations will: 547 * 548 * @li have already been invoked; or 549 * 550 * @li have been queued for invocation in the near future. 551 * 552 * These handlers can no longer be cancelled, and therefore are passed an 553 * error code that indicates the successful completion of the wait operation. 554 */ expires_at(const time_point & expiry_time)555 std::size_t expires_at(const time_point& expiry_time) 556 { 557 boost::system::error_code ec; 558 std::size_t s = impl_.get_service().expires_at( 559 impl_.get_implementation(), expiry_time, ec); 560 boost::asio::detail::throw_error(ec, "expires_at"); 561 return s; 562 } 563 564 #if !defined(BOOST_ASIO_NO_DEPRECATED) 565 /// (Deprecated: Use non-error_code overload.) Set the timer's expiry time as 566 /// an absolute time. 567 /** 568 * This function sets the expiry time. Any pending asynchronous wait 569 * operations will be cancelled. The handler for each cancelled operation will 570 * be invoked with the boost::asio::error::operation_aborted error code. 571 * 572 * @param expiry_time The expiry time to be used for the timer. 573 * 574 * @param ec Set to indicate what error occurred, if any. 575 * 576 * @return The number of asynchronous operations that were cancelled. 577 * 578 * @note If the timer has already expired when expires_at() is called, then 579 * the handlers for asynchronous wait operations will: 580 * 581 * @li have already been invoked; or 582 * 583 * @li have been queued for invocation in the near future. 584 * 585 * These handlers can no longer be cancelled, and therefore are passed an 586 * error code that indicates the successful completion of the wait operation. 587 */ expires_at(const time_point & expiry_time,boost::system::error_code & ec)588 std::size_t expires_at(const time_point& expiry_time, 589 boost::system::error_code& ec) 590 { 591 return impl_.get_service().expires_at( 592 impl_.get_implementation(), expiry_time, ec); 593 } 594 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 595 596 /// Set the timer's expiry time relative to now. 597 /** 598 * This function sets the expiry time. Any pending asynchronous wait 599 * operations will be cancelled. The handler for each cancelled operation will 600 * be invoked with the boost::asio::error::operation_aborted error code. 601 * 602 * @param expiry_time The expiry time to be used for the timer. 603 * 604 * @return The number of asynchronous operations that were cancelled. 605 * 606 * @throws boost::system::system_error Thrown on failure. 607 * 608 * @note If the timer has already expired when expires_after() is called, 609 * then the handlers for asynchronous wait operations will: 610 * 611 * @li have already been invoked; or 612 * 613 * @li have been queued for invocation in the near future. 614 * 615 * These handlers can no longer be cancelled, and therefore are passed an 616 * error code that indicates the successful completion of the wait operation. 617 */ expires_after(const duration & expiry_time)618 std::size_t expires_after(const duration& expiry_time) 619 { 620 boost::system::error_code ec; 621 std::size_t s = impl_.get_service().expires_after( 622 impl_.get_implementation(), expiry_time, ec); 623 boost::asio::detail::throw_error(ec, "expires_after"); 624 return s; 625 } 626 627 #if !defined(BOOST_ASIO_NO_DEPRECATED) 628 /// (Deprecated: Use expiry().) Get the timer's expiry time relative to now. 629 /** 630 * This function may be used to obtain the timer's current expiry time. 631 * Whether the timer has expired or not does not affect this value. 632 */ expires_from_now() const633 duration expires_from_now() const 634 { 635 return impl_.get_service().expires_from_now(impl_.get_implementation()); 636 } 637 638 /// (Deprecated: Use expires_after().) Set the timer's expiry time relative 639 /// to now. 640 /** 641 * This function sets the expiry time. Any pending asynchronous wait 642 * operations will be cancelled. The handler for each cancelled operation will 643 * be invoked with the boost::asio::error::operation_aborted error code. 644 * 645 * @param expiry_time The expiry time to be used for the timer. 646 * 647 * @return The number of asynchronous operations that were cancelled. 648 * 649 * @throws boost::system::system_error Thrown on failure. 650 * 651 * @note If the timer has already expired when expires_from_now() is called, 652 * then the handlers for asynchronous wait operations will: 653 * 654 * @li have already been invoked; or 655 * 656 * @li have been queued for invocation in the near future. 657 * 658 * These handlers can no longer be cancelled, and therefore are passed an 659 * error code that indicates the successful completion of the wait operation. 660 */ expires_from_now(const duration & expiry_time)661 std::size_t expires_from_now(const duration& expiry_time) 662 { 663 boost::system::error_code ec; 664 std::size_t s = impl_.get_service().expires_from_now( 665 impl_.get_implementation(), expiry_time, ec); 666 boost::asio::detail::throw_error(ec, "expires_from_now"); 667 return s; 668 } 669 670 /// (Deprecated: Use expires_after().) Set the timer's expiry time relative 671 /// to now. 672 /** 673 * This function sets the expiry time. Any pending asynchronous wait 674 * operations will be cancelled. The handler for each cancelled operation will 675 * be invoked with the boost::asio::error::operation_aborted error code. 676 * 677 * @param expiry_time The expiry time to be used for the timer. 678 * 679 * @param ec Set to indicate what error occurred, if any. 680 * 681 * @return The number of asynchronous operations that were cancelled. 682 * 683 * @note If the timer has already expired when expires_from_now() is called, 684 * then the handlers for asynchronous wait operations will: 685 * 686 * @li have already been invoked; or 687 * 688 * @li have been queued for invocation in the near future. 689 * 690 * These handlers can no longer be cancelled, and therefore are passed an 691 * error code that indicates the successful completion of the wait operation. 692 */ expires_from_now(const duration & expiry_time,boost::system::error_code & ec)693 std::size_t expires_from_now(const duration& expiry_time, 694 boost::system::error_code& ec) 695 { 696 return impl_.get_service().expires_from_now( 697 impl_.get_implementation(), expiry_time, ec); 698 } 699 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 700 701 /// Perform a blocking wait on the timer. 702 /** 703 * This function is used to wait for the timer to expire. This function 704 * blocks and does not return until the timer has expired. 705 * 706 * @throws boost::system::system_error Thrown on failure. 707 */ wait()708 void wait() 709 { 710 boost::system::error_code ec; 711 impl_.get_service().wait(impl_.get_implementation(), ec); 712 boost::asio::detail::throw_error(ec, "wait"); 713 } 714 715 /// Perform a blocking wait on the timer. 716 /** 717 * This function is used to wait for the timer to expire. This function 718 * blocks and does not return until the timer has expired. 719 * 720 * @param ec Set to indicate what error occurred, if any. 721 */ wait(boost::system::error_code & ec)722 void wait(boost::system::error_code& ec) 723 { 724 impl_.get_service().wait(impl_.get_implementation(), ec); 725 } 726 727 /// Start an asynchronous wait on the timer. 728 /** 729 * This function may be used to initiate an asynchronous wait against the 730 * timer. It always returns immediately. 731 * 732 * For each call to async_wait(), the supplied handler will be called exactly 733 * once. The handler will be called when: 734 * 735 * @li The timer has expired. 736 * 737 * @li The timer was cancelled, in which case the handler is passed the error 738 * code boost::asio::error::operation_aborted. 739 * 740 * @param handler The handler to be called when the timer expires. Copies 741 * will be made of the handler as required. The function signature of the 742 * handler must be: 743 * @code void handler( 744 * const boost::system::error_code& error // Result of operation. 745 * ); @endcode 746 * Regardless of whether the asynchronous operation completes immediately or 747 * not, the handler will not be invoked from within this function. On 748 * immediate completion, invocation of the handler will be performed in a 749 * manner equivalent to using boost::asio::post(). 750 */ 751 template < 752 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) 753 WaitHandler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,void (boost::system::error_code))754 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler, 755 void (boost::system::error_code)) 756 async_wait( 757 BOOST_ASIO_MOVE_ARG(WaitHandler) handler 758 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) 759 { 760 return async_initiate<WaitHandler, void (boost::system::error_code)>( 761 initiate_async_wait(this), handler); 762 } 763 764 private: 765 // Disallow copying and assignment. 766 basic_waitable_timer(const basic_waitable_timer&) BOOST_ASIO_DELETED; 767 basic_waitable_timer& operator=( 768 const basic_waitable_timer&) BOOST_ASIO_DELETED; 769 770 class initiate_async_wait 771 { 772 public: 773 typedef Executor executor_type; 774 initiate_async_wait(basic_waitable_timer * self)775 explicit initiate_async_wait(basic_waitable_timer* self) 776 : self_(self) 777 { 778 } 779 get_executor() const780 executor_type get_executor() const BOOST_ASIO_NOEXCEPT 781 { 782 return self_->get_executor(); 783 } 784 785 template <typename WaitHandler> operator ()(BOOST_ASIO_MOVE_ARG (WaitHandler)handler) const786 void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler) const 787 { 788 // If you get an error on the following line it means that your handler 789 // does not meet the documented type requirements for a WaitHandler. 790 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; 791 792 detail::non_const_lvalue<WaitHandler> handler2(handler); 793 self_->impl_.get_service().async_wait( 794 self_->impl_.get_implementation(), 795 handler2.value, self_->impl_.get_executor()); 796 } 797 798 private: 799 basic_waitable_timer* self_; 800 }; 801 802 detail::io_object_impl< 803 detail::deadline_timer_service< 804 detail::chrono_time_traits<Clock, WaitTraits> >, 805 executor_type > impl_; 806 }; 807 808 } // namespace asio 809 } // namespace boost 810 811 #include <boost/asio/detail/pop_options.hpp> 812 813 #endif // BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP 814