1 // 2 // basic_deadline_timer.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2015 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_DEADLINE_TIMER_HPP 12 #define BOOST_ASIO_BASIC_DEADLINE_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 20 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ 21 || defined(GENERATING_DOCUMENTATION) 22 23 #include <cstddef> 24 #include <boost/asio/basic_io_object.hpp> 25 #include <boost/asio/deadline_timer_service.hpp> 26 #include <boost/asio/detail/handler_type_requirements.hpp> 27 #include <boost/asio/detail/throw_error.hpp> 28 #include <boost/asio/error.hpp> 29 30 #include <boost/asio/detail/push_options.hpp> 31 32 namespace boost { 33 namespace asio { 34 35 /// Provides waitable timer functionality. 36 /** 37 * The basic_deadline_timer class template provides the ability to perform a 38 * blocking or asynchronous wait for a timer to expire. 39 * 40 * A deadline timer is always in one of two states: "expired" or "not expired". 41 * If the wait() or async_wait() function is called on an expired timer, the 42 * wait operation will complete immediately. 43 * 44 * Most applications will use the boost::asio::deadline_timer typedef. 45 * 46 * @par Thread Safety 47 * @e Distinct @e objects: Safe.@n 48 * @e Shared @e objects: Unsafe. 49 * 50 * @par Examples 51 * Performing a blocking wait: 52 * @code 53 * // Construct a timer without setting an expiry time. 54 * boost::asio::deadline_timer timer(io_service); 55 * 56 * // Set an expiry time relative to now. 57 * timer.expires_from_now(boost::posix_time::seconds(5)); 58 * 59 * // Wait for the timer to expire. 60 * timer.wait(); 61 * @endcode 62 * 63 * @par 64 * Performing an asynchronous wait: 65 * @code 66 * void handler(const boost::system::error_code& error) 67 * { 68 * if (!error) 69 * { 70 * // Timer expired. 71 * } 72 * } 73 * 74 * ... 75 * 76 * // Construct a timer with an absolute expiry time. 77 * boost::asio::deadline_timer timer(io_service, 78 * boost::posix_time::time_from_string("2005-12-07 23:59:59.000")); 79 * 80 * // Start an asynchronous wait. 81 * timer.async_wait(handler); 82 * @endcode 83 * 84 * @par Changing an active deadline_timer's expiry time 85 * 86 * Changing the expiry time of a timer while there are pending asynchronous 87 * waits causes those wait operations to be cancelled. To ensure that the action 88 * associated with the timer is performed only once, use something like this: 89 * used: 90 * 91 * @code 92 * void on_some_event() 93 * { 94 * if (my_timer.expires_from_now(seconds(5)) > 0) 95 * { 96 * // We managed to cancel the timer. Start new asynchronous wait. 97 * my_timer.async_wait(on_timeout); 98 * } 99 * else 100 * { 101 * // Too late, timer has already expired! 102 * } 103 * } 104 * 105 * void on_timeout(const boost::system::error_code& e) 106 * { 107 * if (e != boost::asio::error::operation_aborted) 108 * { 109 * // Timer was not cancelled, take necessary action. 110 * } 111 * } 112 * @endcode 113 * 114 * @li The boost::asio::basic_deadline_timer::expires_from_now() function 115 * cancels any pending asynchronous waits, and returns the number of 116 * asynchronous waits that were cancelled. If it returns 0 then you were too 117 * late and the wait handler has already been executed, or will soon be 118 * executed. If it returns 1 then the wait handler was successfully cancelled. 119 * 120 * @li If a wait handler is cancelled, the boost::system::error_code passed to 121 * it contains the value boost::asio::error::operation_aborted. 122 */ 123 template <typename Time, 124 typename TimeTraits = boost::asio::time_traits<Time>, 125 typename TimerService = deadline_timer_service<Time, TimeTraits> > 126 class basic_deadline_timer 127 : public basic_io_object<TimerService> 128 { 129 public: 130 /// The time traits type. 131 typedef TimeTraits traits_type; 132 133 /// The time type. 134 typedef typename traits_type::time_type time_type; 135 136 /// The duration type. 137 typedef typename traits_type::duration_type duration_type; 138 139 /// Constructor. 140 /** 141 * This constructor creates a timer without setting an expiry time. The 142 * expires_at() or expires_from_now() functions must be called to set an 143 * expiry time before the timer can be waited on. 144 * 145 * @param io_service The io_service object that the timer will use to dispatch 146 * handlers for any asynchronous operations performed on the timer. 147 */ basic_deadline_timer(boost::asio::io_service & io_service)148 explicit basic_deadline_timer(boost::asio::io_service& io_service) 149 : basic_io_object<TimerService>(io_service) 150 { 151 } 152 153 /// Constructor to set a particular expiry time as an absolute time. 154 /** 155 * This constructor creates a timer and sets the expiry time. 156 * 157 * @param io_service The io_service object that the timer will use to dispatch 158 * handlers for any asynchronous operations performed on the timer. 159 * 160 * @param expiry_time The expiry time to be used for the timer, expressed 161 * as an absolute time. 162 */ basic_deadline_timer(boost::asio::io_service & io_service,const time_type & expiry_time)163 basic_deadline_timer(boost::asio::io_service& io_service, 164 const time_type& expiry_time) 165 : basic_io_object<TimerService>(io_service) 166 { 167 boost::system::error_code ec; 168 this->service.expires_at(this->implementation, expiry_time, ec); 169 boost::asio::detail::throw_error(ec, "expires_at"); 170 } 171 172 /// Constructor to set a particular expiry time relative to now. 173 /** 174 * This constructor creates a timer and sets the expiry time. 175 * 176 * @param io_service The io_service object that the timer will use to dispatch 177 * handlers for any asynchronous operations performed on the timer. 178 * 179 * @param expiry_time The expiry time to be used for the timer, relative to 180 * now. 181 */ basic_deadline_timer(boost::asio::io_service & io_service,const duration_type & expiry_time)182 basic_deadline_timer(boost::asio::io_service& io_service, 183 const duration_type& expiry_time) 184 : basic_io_object<TimerService>(io_service) 185 { 186 boost::system::error_code ec; 187 this->service.expires_from_now(this->implementation, expiry_time, ec); 188 boost::asio::detail::throw_error(ec, "expires_from_now"); 189 } 190 191 /// Cancel any asynchronous operations that are waiting on the timer. 192 /** 193 * This function forces the completion of any pending asynchronous wait 194 * operations against the timer. The handler for each cancelled operation will 195 * be invoked with the boost::asio::error::operation_aborted error code. 196 * 197 * Cancelling the timer does not change the expiry time. 198 * 199 * @return The number of asynchronous operations that were cancelled. 200 * 201 * @throws boost::system::system_error Thrown on failure. 202 * 203 * @note If the timer has already expired when cancel() is called, then the 204 * handlers for asynchronous wait operations will: 205 * 206 * @li have already been invoked; or 207 * 208 * @li have been queued for invocation in the near future. 209 * 210 * These handlers can no longer be cancelled, and therefore are passed an 211 * error code that indicates the successful completion of the wait operation. 212 */ cancel()213 std::size_t cancel() 214 { 215 boost::system::error_code ec; 216 std::size_t s = this->service.cancel(this->implementation, ec); 217 boost::asio::detail::throw_error(ec, "cancel"); 218 return s; 219 } 220 221 /// Cancel any asynchronous operations that are waiting on the timer. 222 /** 223 * This function forces the completion of any pending asynchronous wait 224 * operations against the timer. The handler for each cancelled operation will 225 * be invoked with the boost::asio::error::operation_aborted error code. 226 * 227 * Cancelling the timer does not change the expiry time. 228 * 229 * @param ec Set to indicate what error occurred, if any. 230 * 231 * @return The number of asynchronous operations that were cancelled. 232 * 233 * @note If the timer has already expired when cancel() is called, then the 234 * handlers for asynchronous wait operations will: 235 * 236 * @li have already been invoked; or 237 * 238 * @li have been queued for invocation in the near future. 239 * 240 * These handlers can no longer be cancelled, and therefore are passed an 241 * error code that indicates the successful completion of the wait operation. 242 */ cancel(boost::system::error_code & ec)243 std::size_t cancel(boost::system::error_code& ec) 244 { 245 return this->service.cancel(this->implementation, ec); 246 } 247 248 /// Cancels one asynchronous operation that is waiting on the timer. 249 /** 250 * This function forces the completion of one pending asynchronous wait 251 * operation against the timer. Handlers are cancelled in FIFO order. The 252 * handler for the cancelled operation will be invoked with the 253 * boost::asio::error::operation_aborted error code. 254 * 255 * Cancelling the timer does not change the expiry time. 256 * 257 * @return The number of asynchronous operations that were cancelled. That is, 258 * either 0 or 1. 259 * 260 * @throws boost::system::system_error Thrown on failure. 261 * 262 * @note If the timer has already expired when cancel_one() is called, then 263 * the handlers for asynchronous wait operations will: 264 * 265 * @li have already been invoked; or 266 * 267 * @li have been queued for invocation in the near future. 268 * 269 * These handlers can no longer be cancelled, and therefore are passed an 270 * error code that indicates the successful completion of the wait operation. 271 */ cancel_one()272 std::size_t cancel_one() 273 { 274 boost::system::error_code ec; 275 std::size_t s = this->service.cancel_one(this->implementation, ec); 276 boost::asio::detail::throw_error(ec, "cancel_one"); 277 return s; 278 } 279 280 /// Cancels one asynchronous operation that is waiting on the timer. 281 /** 282 * This function forces the completion of one pending asynchronous wait 283 * operation against the timer. Handlers are cancelled in FIFO order. The 284 * handler for the cancelled operation will be invoked with the 285 * boost::asio::error::operation_aborted error code. 286 * 287 * Cancelling the timer does not change the expiry time. 288 * 289 * @param ec Set to indicate what error occurred, if any. 290 * 291 * @return The number of asynchronous operations that were cancelled. That is, 292 * either 0 or 1. 293 * 294 * @note If the timer has already expired when cancel_one() is called, then 295 * the handlers for asynchronous wait operations will: 296 * 297 * @li have already been invoked; or 298 * 299 * @li have been queued for invocation in the near future. 300 * 301 * These handlers can no longer be cancelled, and therefore are passed an 302 * error code that indicates the successful completion of the wait operation. 303 */ cancel_one(boost::system::error_code & ec)304 std::size_t cancel_one(boost::system::error_code& ec) 305 { 306 return this->service.cancel_one(this->implementation, ec); 307 } 308 309 /// Get the timer's expiry time as an absolute time. 310 /** 311 * This function may be used to obtain the timer's current expiry time. 312 * Whether the timer has expired or not does not affect this value. 313 */ expires_at() const314 time_type expires_at() const 315 { 316 return this->service.expires_at(this->implementation); 317 } 318 319 /// Set the timer's expiry time as an absolute time. 320 /** 321 * This function sets the expiry time. Any pending asynchronous wait 322 * operations will be cancelled. The handler for each cancelled operation will 323 * be invoked with the boost::asio::error::operation_aborted error code. 324 * 325 * @param expiry_time The expiry time to be used for the timer. 326 * 327 * @return The number of asynchronous operations that were cancelled. 328 * 329 * @throws boost::system::system_error Thrown on failure. 330 * 331 * @note If the timer has already expired when expires_at() is called, then 332 * the handlers for asynchronous wait operations will: 333 * 334 * @li have already been invoked; or 335 * 336 * @li have been queued for invocation in the near future. 337 * 338 * These handlers can no longer be cancelled, and therefore are passed an 339 * error code that indicates the successful completion of the wait operation. 340 */ expires_at(const time_type & expiry_time)341 std::size_t expires_at(const time_type& expiry_time) 342 { 343 boost::system::error_code ec; 344 std::size_t s = this->service.expires_at( 345 this->implementation, expiry_time, ec); 346 boost::asio::detail::throw_error(ec, "expires_at"); 347 return s; 348 } 349 350 /// Set the timer's expiry time as an absolute time. 351 /** 352 * This function sets the expiry time. Any pending asynchronous wait 353 * operations will be cancelled. The handler for each cancelled operation will 354 * be invoked with the boost::asio::error::operation_aborted error code. 355 * 356 * @param expiry_time The expiry time to be used for the timer. 357 * 358 * @param ec Set to indicate what error occurred, if any. 359 * 360 * @return The number of asynchronous operations that were cancelled. 361 * 362 * @note If the timer has already expired when expires_at() is called, then 363 * the handlers for asynchronous wait operations will: 364 * 365 * @li have already been invoked; or 366 * 367 * @li have been queued for invocation in the near future. 368 * 369 * These handlers can no longer be cancelled, and therefore are passed an 370 * error code that indicates the successful completion of the wait operation. 371 */ expires_at(const time_type & expiry_time,boost::system::error_code & ec)372 std::size_t expires_at(const time_type& expiry_time, 373 boost::system::error_code& ec) 374 { 375 return this->service.expires_at(this->implementation, expiry_time, ec); 376 } 377 378 /// Get the timer's expiry time relative to now. 379 /** 380 * This function may be used to obtain the timer's current expiry time. 381 * Whether the timer has expired or not does not affect this value. 382 */ expires_from_now() const383 duration_type expires_from_now() const 384 { 385 return this->service.expires_from_now(this->implementation); 386 } 387 388 /// Set the timer's expiry time relative to now. 389 /** 390 * This function sets the expiry time. Any pending asynchronous wait 391 * operations will be cancelled. The handler for each cancelled operation will 392 * be invoked with the boost::asio::error::operation_aborted error code. 393 * 394 * @param expiry_time The expiry time to be used for the timer. 395 * 396 * @return The number of asynchronous operations that were cancelled. 397 * 398 * @throws boost::system::system_error Thrown on failure. 399 * 400 * @note If the timer has already expired when expires_from_now() is called, 401 * then the handlers for asynchronous wait operations will: 402 * 403 * @li have already been invoked; or 404 * 405 * @li have been queued for invocation in the near future. 406 * 407 * These handlers can no longer be cancelled, and therefore are passed an 408 * error code that indicates the successful completion of the wait operation. 409 */ expires_from_now(const duration_type & expiry_time)410 std::size_t expires_from_now(const duration_type& expiry_time) 411 { 412 boost::system::error_code ec; 413 std::size_t s = this->service.expires_from_now( 414 this->implementation, expiry_time, ec); 415 boost::asio::detail::throw_error(ec, "expires_from_now"); 416 return s; 417 } 418 419 /// Set the timer's expiry time relative to now. 420 /** 421 * This function sets the expiry time. Any pending asynchronous wait 422 * operations will be cancelled. The handler for each cancelled operation will 423 * be invoked with the boost::asio::error::operation_aborted error code. 424 * 425 * @param expiry_time The expiry time to be used for the timer. 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 expires_from_now() is called, 432 * then the 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 */ expires_from_now(const duration_type & expiry_time,boost::system::error_code & ec)441 std::size_t expires_from_now(const duration_type& expiry_time, 442 boost::system::error_code& ec) 443 { 444 return this->service.expires_from_now( 445 this->implementation, expiry_time, ec); 446 } 447 448 /// Perform a blocking wait on the timer. 449 /** 450 * This function is used to wait for the timer to expire. This function 451 * blocks and does not return until the timer has expired. 452 * 453 * @throws boost::system::system_error Thrown on failure. 454 */ wait()455 void wait() 456 { 457 boost::system::error_code ec; 458 this->service.wait(this->implementation, ec); 459 boost::asio::detail::throw_error(ec, "wait"); 460 } 461 462 /// Perform a blocking wait on the timer. 463 /** 464 * This function is used to wait for the timer to expire. This function 465 * blocks and does not return until the timer has expired. 466 * 467 * @param ec Set to indicate what error occurred, if any. 468 */ wait(boost::system::error_code & ec)469 void wait(boost::system::error_code& ec) 470 { 471 this->service.wait(this->implementation, ec); 472 } 473 474 /// Start an asynchronous wait on the timer. 475 /** 476 * This function may be used to initiate an asynchronous wait against the 477 * timer. It always returns immediately. 478 * 479 * For each call to async_wait(), the supplied handler will be called exactly 480 * once. The handler will be called when: 481 * 482 * @li The timer has expired. 483 * 484 * @li The timer was cancelled, in which case the handler is passed the error 485 * code boost::asio::error::operation_aborted. 486 * 487 * @param handler The handler to be called when the timer expires. Copies 488 * will be made of the handler as required. The function signature of the 489 * handler must be: 490 * @code void handler( 491 * const boost::system::error_code& error // Result of operation. 492 * ); @endcode 493 * Regardless of whether the asynchronous operation completes immediately or 494 * not, the handler will not be invoked from within this function. Invocation 495 * of the handler will be performed in a manner equivalent to using 496 * boost::asio::io_service::post(). 497 */ 498 template <typename WaitHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,void (boost::system::error_code))499 BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, 500 void (boost::system::error_code)) 501 async_wait(BOOST_ASIO_MOVE_ARG(WaitHandler) handler) 502 { 503 // If you get an error on the following line it means that your handler does 504 // not meet the documented type requirements for a WaitHandler. 505 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; 506 507 return this->service.async_wait(this->implementation, 508 BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); 509 } 510 }; 511 512 } // namespace asio 513 } // namespace boost 514 515 #include <boost/asio/detail/pop_options.hpp> 516 517 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) 518 // || defined(GENERATING_DOCUMENTATION) 519 520 #endif // BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP 521