Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

667 lines
22KB

  1. //
  2. // basic_deadline_timer.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 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. #ifndef ASIO_BASIC_DEADLINE_TIMER_HPP
  11. #define ASIO_BASIC_DEADLINE_TIMER_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #if defined(ASIO_HAS_BOOST_DATE_TIME) \
  17. || defined(GENERATING_DOCUMENTATION)
  18. #include <cstddef>
  19. #include "asio/detail/deadline_timer_service.hpp"
  20. #include "asio/detail/handler_type_requirements.hpp"
  21. #include "asio/detail/io_object_impl.hpp"
  22. #include "asio/detail/non_const_lvalue.hpp"
  23. #include "asio/detail/throw_error.hpp"
  24. #include "asio/error.hpp"
  25. #include "asio/execution_context.hpp"
  26. #include "asio/executor.hpp"
  27. #include "asio/time_traits.hpp"
  28. #include "asio/detail/push_options.hpp"
  29. namespace asio {
  30. /// Provides waitable timer functionality.
  31. /**
  32. * The basic_deadline_timer class template provides the ability to perform a
  33. * blocking or asynchronous wait for a timer to expire.
  34. *
  35. * A deadline timer is always in one of two states: "expired" or "not expired".
  36. * If the wait() or async_wait() function is called on an expired timer, the
  37. * wait operation will complete immediately.
  38. *
  39. * Most applications will use the asio::deadline_timer typedef.
  40. *
  41. * @par Thread Safety
  42. * @e Distinct @e objects: Safe.@n
  43. * @e Shared @e objects: Unsafe.
  44. *
  45. * @par Examples
  46. * Performing a blocking wait:
  47. * @code
  48. * // Construct a timer without setting an expiry time.
  49. * asio::deadline_timer timer(my_context);
  50. *
  51. * // Set an expiry time relative to now.
  52. * timer.expires_from_now(boost::posix_time::seconds(5));
  53. *
  54. * // Wait for the timer to expire.
  55. * timer.wait();
  56. * @endcode
  57. *
  58. * @par
  59. * Performing an asynchronous wait:
  60. * @code
  61. * void handler(const asio::error_code& error)
  62. * {
  63. * if (!error)
  64. * {
  65. * // Timer expired.
  66. * }
  67. * }
  68. *
  69. * ...
  70. *
  71. * // Construct a timer with an absolute expiry time.
  72. * asio::deadline_timer timer(my_context,
  73. * boost::posix_time::time_from_string("2005-12-07 23:59:59.000"));
  74. *
  75. * // Start an asynchronous wait.
  76. * timer.async_wait(handler);
  77. * @endcode
  78. *
  79. * @par Changing an active deadline_timer's expiry time
  80. *
  81. * Changing the expiry time of a timer while there are pending asynchronous
  82. * waits causes those wait operations to be cancelled. To ensure that the action
  83. * associated with the timer is performed only once, use something like this:
  84. * used:
  85. *
  86. * @code
  87. * void on_some_event()
  88. * {
  89. * if (my_timer.expires_from_now(seconds(5)) > 0)
  90. * {
  91. * // We managed to cancel the timer. Start new asynchronous wait.
  92. * my_timer.async_wait(on_timeout);
  93. * }
  94. * else
  95. * {
  96. * // Too late, timer has already expired!
  97. * }
  98. * }
  99. *
  100. * void on_timeout(const asio::error_code& e)
  101. * {
  102. * if (e != asio::error::operation_aborted)
  103. * {
  104. * // Timer was not cancelled, take necessary action.
  105. * }
  106. * }
  107. * @endcode
  108. *
  109. * @li The asio::basic_deadline_timer::expires_from_now() function
  110. * cancels any pending asynchronous waits, and returns the number of
  111. * asynchronous waits that were cancelled. If it returns 0 then you were too
  112. * late and the wait handler has already been executed, or will soon be
  113. * executed. If it returns 1 then the wait handler was successfully cancelled.
  114. *
  115. * @li If a wait handler is cancelled, the asio::error_code passed to
  116. * it contains the value asio::error::operation_aborted.
  117. */
  118. template <typename Time,
  119. typename TimeTraits = asio::time_traits<Time>,
  120. typename Executor = executor>
  121. class basic_deadline_timer
  122. {
  123. public:
  124. /// The type of the executor associated with the object.
  125. typedef Executor executor_type;
  126. /// The time traits type.
  127. typedef TimeTraits traits_type;
  128. /// The time type.
  129. typedef typename traits_type::time_type time_type;
  130. /// The duration type.
  131. typedef typename traits_type::duration_type duration_type;
  132. /// Constructor.
  133. /**
  134. * This constructor creates a timer without setting an expiry time. The
  135. * expires_at() or expires_from_now() functions must be called to set an
  136. * expiry time before the timer can be waited on.
  137. *
  138. * @param ex The I/O executor that the timer will use, by default, to
  139. * dispatch handlers for any asynchronous operations performed on the timer.
  140. */
  141. explicit basic_deadline_timer(const executor_type& ex)
  142. : impl_(ex)
  143. {
  144. }
  145. /// Constructor.
  146. /**
  147. * This constructor creates a timer without setting an expiry time. The
  148. * expires_at() or expires_from_now() functions must be called to set an
  149. * expiry time before the timer can be waited on.
  150. *
  151. * @param context An execution context which provides the I/O executor that
  152. * the timer will use, by default, to dispatch handlers for any asynchronous
  153. * operations performed on the timer.
  154. */
  155. template <typename ExecutionContext>
  156. explicit basic_deadline_timer(ExecutionContext& context,
  157. typename enable_if<
  158. is_convertible<ExecutionContext&, execution_context&>::value
  159. >::type* = 0)
  160. : impl_(context)
  161. {
  162. }
  163. /// Constructor to set a particular expiry time as an absolute time.
  164. /**
  165. * This constructor creates a timer and sets the expiry time.
  166. *
  167. * @param ex The I/O executor that the timer will use, by default, to
  168. * dispatch handlers for any asynchronous operations performed on the timer.
  169. *
  170. * @param expiry_time The expiry time to be used for the timer, expressed
  171. * as an absolute time.
  172. */
  173. basic_deadline_timer(const executor_type& ex, const time_type& expiry_time)
  174. : impl_(ex)
  175. {
  176. asio::error_code ec;
  177. impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
  178. asio::detail::throw_error(ec, "expires_at");
  179. }
  180. /// Constructor to set a particular expiry time as an absolute time.
  181. /**
  182. * This constructor creates a timer and sets the expiry time.
  183. *
  184. * @param context An execution context which provides the I/O executor that
  185. * the timer will use, by default, to dispatch handlers for any asynchronous
  186. * operations performed on the timer.
  187. *
  188. * @param expiry_time The expiry time to be used for the timer, expressed
  189. * as an absolute time.
  190. */
  191. template <typename ExecutionContext>
  192. basic_deadline_timer(ExecutionContext& context, const time_type& expiry_time,
  193. typename enable_if<
  194. is_convertible<ExecutionContext&, execution_context&>::value
  195. >::type* = 0)
  196. : impl_(context)
  197. {
  198. asio::error_code ec;
  199. impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
  200. asio::detail::throw_error(ec, "expires_at");
  201. }
  202. /// Constructor to set a particular expiry time relative to now.
  203. /**
  204. * This constructor creates a timer and sets the expiry time.
  205. *
  206. * @param ex The I/O executor 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, relative to
  210. * now.
  211. */
  212. basic_deadline_timer(const executor_type& ex,
  213. const duration_type& expiry_time)
  214. : impl_(ex)
  215. {
  216. asio::error_code ec;
  217. impl_.get_service().expires_from_now(
  218. impl_.get_implementation(), expiry_time, ec);
  219. asio::detail::throw_error(ec, "expires_from_now");
  220. }
  221. /// Constructor to set a particular expiry time relative to now.
  222. /**
  223. * This constructor creates a timer and sets the expiry time.
  224. *
  225. * @param context An execution context which provides the I/O executor that
  226. * the timer will use, by default, to dispatch handlers for any asynchronous
  227. * operations performed on the timer.
  228. *
  229. * @param expiry_time The expiry time to be used for the timer, relative to
  230. * now.
  231. */
  232. template <typename ExecutionContext>
  233. basic_deadline_timer(ExecutionContext& context,
  234. const duration_type& expiry_time,
  235. typename enable_if<
  236. is_convertible<ExecutionContext&, execution_context&>::value
  237. >::type* = 0)
  238. : impl_(context)
  239. {
  240. asio::error_code ec;
  241. impl_.get_service().expires_from_now(
  242. impl_.get_implementation(), expiry_time, ec);
  243. asio::detail::throw_error(ec, "expires_from_now");
  244. }
  245. #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  246. /// Move-construct a basic_deadline_timer from another.
  247. /**
  248. * This constructor moves a timer from one object to another.
  249. *
  250. * @param other The other basic_deadline_timer object from which the move will
  251. * occur.
  252. *
  253. * @note Following the move, the moved-from object is in the same state as if
  254. * constructed using the @c basic_deadline_timer(const executor_type&)
  255. * constructor.
  256. */
  257. basic_deadline_timer(basic_deadline_timer&& other)
  258. : impl_(std::move(other.impl_))
  259. {
  260. }
  261. /// Move-assign a basic_deadline_timer from another.
  262. /**
  263. * This assignment operator moves a timer from one object to another. Cancels
  264. * any outstanding asynchronous operations associated with the target object.
  265. *
  266. * @param other The other basic_deadline_timer object from which the move will
  267. * occur.
  268. *
  269. * @note Following the move, the moved-from object is in the same state as if
  270. * constructed using the @c basic_deadline_timer(const executor_type&)
  271. * constructor.
  272. */
  273. basic_deadline_timer& operator=(basic_deadline_timer&& other)
  274. {
  275. impl_ = std::move(other.impl_);
  276. return *this;
  277. }
  278. #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  279. /// Destroys the timer.
  280. /**
  281. * This function destroys the timer, cancelling any outstanding asynchronous
  282. * wait operations associated with the timer as if by calling @c cancel.
  283. */
  284. ~basic_deadline_timer()
  285. {
  286. }
  287. /// Get the executor associated with the object.
  288. executor_type get_executor() ASIO_NOEXCEPT
  289. {
  290. return impl_.get_executor();
  291. }
  292. /// Cancel any asynchronous operations that are waiting on the timer.
  293. /**
  294. * This function forces the completion of any pending asynchronous wait
  295. * operations against the timer. The handler for each cancelled operation will
  296. * be invoked with the asio::error::operation_aborted error code.
  297. *
  298. * Cancelling the timer does not change the expiry time.
  299. *
  300. * @return The number of asynchronous operations that were cancelled.
  301. *
  302. * @throws asio::system_error Thrown on failure.
  303. *
  304. * @note If the timer has already expired when cancel() is called, then the
  305. * handlers for asynchronous wait operations will:
  306. *
  307. * @li have already been invoked; or
  308. *
  309. * @li have been queued for invocation in the near future.
  310. *
  311. * These handlers can no longer be cancelled, and therefore are passed an
  312. * error code that indicates the successful completion of the wait operation.
  313. */
  314. std::size_t cancel()
  315. {
  316. asio::error_code ec;
  317. std::size_t s = impl_.get_service().cancel(impl_.get_implementation(), ec);
  318. asio::detail::throw_error(ec, "cancel");
  319. return s;
  320. }
  321. /// Cancel any asynchronous operations that are waiting on the timer.
  322. /**
  323. * This function forces the completion of any pending asynchronous wait
  324. * operations against the timer. The handler for each cancelled operation will
  325. * be invoked with the asio::error::operation_aborted error code.
  326. *
  327. * Cancelling the timer does not change the expiry time.
  328. *
  329. * @param ec Set to indicate what error occurred, if any.
  330. *
  331. * @return The number of asynchronous operations that were cancelled.
  332. *
  333. * @note If the timer has already expired when cancel() is called, then the
  334. * handlers for asynchronous wait operations will:
  335. *
  336. * @li have already been invoked; or
  337. *
  338. * @li have been queued for invocation in the near future.
  339. *
  340. * These handlers can no longer be cancelled, and therefore are passed an
  341. * error code that indicates the successful completion of the wait operation.
  342. */
  343. std::size_t cancel(asio::error_code& ec)
  344. {
  345. return impl_.get_service().cancel(impl_.get_implementation(), ec);
  346. }
  347. /// Cancels one asynchronous operation that is waiting on the timer.
  348. /**
  349. * This function forces the completion of one pending asynchronous wait
  350. * operation against the timer. Handlers are cancelled in FIFO order. The
  351. * handler for the cancelled operation will be invoked with the
  352. * asio::error::operation_aborted error code.
  353. *
  354. * Cancelling the timer does not change the expiry time.
  355. *
  356. * @return The number of asynchronous operations that were cancelled. That is,
  357. * either 0 or 1.
  358. *
  359. * @throws asio::system_error Thrown on failure.
  360. *
  361. * @note If the timer has already expired when cancel_one() is called, then
  362. * the handlers for asynchronous wait operations will:
  363. *
  364. * @li have already been invoked; or
  365. *
  366. * @li have been queued for invocation in the near future.
  367. *
  368. * These handlers can no longer be cancelled, and therefore are passed an
  369. * error code that indicates the successful completion of the wait operation.
  370. */
  371. std::size_t cancel_one()
  372. {
  373. asio::error_code ec;
  374. std::size_t s = impl_.get_service().cancel_one(
  375. impl_.get_implementation(), ec);
  376. asio::detail::throw_error(ec, "cancel_one");
  377. return s;
  378. }
  379. /// Cancels one asynchronous operation that is waiting on the timer.
  380. /**
  381. * This function forces the completion of one pending asynchronous wait
  382. * operation against the timer. Handlers are cancelled in FIFO order. The
  383. * handler for the cancelled operation will be invoked with the
  384. * asio::error::operation_aborted error code.
  385. *
  386. * Cancelling the timer does not change the expiry time.
  387. *
  388. * @param ec Set to indicate what error occurred, if any.
  389. *
  390. * @return The number of asynchronous operations that were cancelled. That is,
  391. * either 0 or 1.
  392. *
  393. * @note If the timer has already expired when cancel_one() is called, then
  394. * the handlers for asynchronous wait operations will:
  395. *
  396. * @li have already been invoked; or
  397. *
  398. * @li have been queued for invocation in the near future.
  399. *
  400. * These handlers can no longer be cancelled, and therefore are passed an
  401. * error code that indicates the successful completion of the wait operation.
  402. */
  403. std::size_t cancel_one(asio::error_code& ec)
  404. {
  405. return impl_.get_service().cancel_one(impl_.get_implementation(), ec);
  406. }
  407. /// Get the timer's expiry time as an absolute time.
  408. /**
  409. * This function may be used to obtain the timer's current expiry time.
  410. * Whether the timer has expired or not does not affect this value.
  411. */
  412. time_type expires_at() const
  413. {
  414. return impl_.get_service().expires_at(impl_.get_implementation());
  415. }
  416. /// Set the timer's expiry time as an absolute time.
  417. /**
  418. * This function sets the expiry time. Any pending asynchronous wait
  419. * operations will be cancelled. The handler for each cancelled operation will
  420. * be invoked with the asio::error::operation_aborted error code.
  421. *
  422. * @param expiry_time The expiry time to be used for the timer.
  423. *
  424. * @return The number of asynchronous operations that were cancelled.
  425. *
  426. * @throws asio::system_error Thrown on failure.
  427. *
  428. * @note If the timer has already expired when expires_at() is called, then
  429. * the handlers for asynchronous wait operations will:
  430. *
  431. * @li have already been invoked; or
  432. *
  433. * @li have been queued for invocation in the near future.
  434. *
  435. * These handlers can no longer be cancelled, and therefore are passed an
  436. * error code that indicates the successful completion of the wait operation.
  437. */
  438. std::size_t expires_at(const time_type& expiry_time)
  439. {
  440. asio::error_code ec;
  441. std::size_t s = impl_.get_service().expires_at(
  442. impl_.get_implementation(), expiry_time, ec);
  443. asio::detail::throw_error(ec, "expires_at");
  444. return s;
  445. }
  446. /// Set the timer's expiry time as an absolute time.
  447. /**
  448. * This function sets the expiry time. Any pending asynchronous wait
  449. * operations will be cancelled. The handler for each cancelled operation will
  450. * be invoked with the asio::error::operation_aborted error code.
  451. *
  452. * @param expiry_time The expiry time to be used for the timer.
  453. *
  454. * @param ec Set to indicate what error occurred, if any.
  455. *
  456. * @return The number of asynchronous operations that were cancelled.
  457. *
  458. * @note If the timer has already expired when expires_at() is called, then
  459. * the handlers for asynchronous wait operations will:
  460. *
  461. * @li have already been invoked; or
  462. *
  463. * @li have been queued for invocation in the near future.
  464. *
  465. * These handlers can no longer be cancelled, and therefore are passed an
  466. * error code that indicates the successful completion of the wait operation.
  467. */
  468. std::size_t expires_at(const time_type& expiry_time,
  469. asio::error_code& ec)
  470. {
  471. return impl_.get_service().expires_at(
  472. impl_.get_implementation(), expiry_time, ec);
  473. }
  474. /// Get the timer's expiry time relative to now.
  475. /**
  476. * This function may be used to obtain the timer's current expiry time.
  477. * Whether the timer has expired or not does not affect this value.
  478. */
  479. duration_type expires_from_now() const
  480. {
  481. return impl_.get_service().expires_from_now(impl_.get_implementation());
  482. }
  483. /// Set the timer's expiry time relative to now.
  484. /**
  485. * This function sets the expiry time. Any pending asynchronous wait
  486. * operations will be cancelled. The handler for each cancelled operation will
  487. * be invoked with the asio::error::operation_aborted error code.
  488. *
  489. * @param expiry_time The expiry time to be used for the timer.
  490. *
  491. * @return The number of asynchronous operations that were cancelled.
  492. *
  493. * @throws asio::system_error Thrown on failure.
  494. *
  495. * @note If the timer has already expired when expires_from_now() is called,
  496. * then the handlers for asynchronous wait operations will:
  497. *
  498. * @li have already been invoked; or
  499. *
  500. * @li have been queued for invocation in the near future.
  501. *
  502. * These handlers can no longer be cancelled, and therefore are passed an
  503. * error code that indicates the successful completion of the wait operation.
  504. */
  505. std::size_t expires_from_now(const duration_type& expiry_time)
  506. {
  507. asio::error_code ec;
  508. std::size_t s = impl_.get_service().expires_from_now(
  509. impl_.get_implementation(), expiry_time, ec);
  510. asio::detail::throw_error(ec, "expires_from_now");
  511. return s;
  512. }
  513. /// Set the timer's expiry time relative to now.
  514. /**
  515. * This function sets the expiry time. Any pending asynchronous wait
  516. * operations will be cancelled. The handler for each cancelled operation will
  517. * be invoked with the asio::error::operation_aborted error code.
  518. *
  519. * @param expiry_time The expiry time to be used for the timer.
  520. *
  521. * @param ec Set to indicate what error occurred, if any.
  522. *
  523. * @return The number of asynchronous operations that were cancelled.
  524. *
  525. * @note If the timer has already expired when expires_from_now() is called,
  526. * then the handlers for asynchronous wait operations will:
  527. *
  528. * @li have already been invoked; or
  529. *
  530. * @li have been queued for invocation in the near future.
  531. *
  532. * These handlers can no longer be cancelled, and therefore are passed an
  533. * error code that indicates the successful completion of the wait operation.
  534. */
  535. std::size_t expires_from_now(const duration_type& expiry_time,
  536. asio::error_code& ec)
  537. {
  538. return impl_.get_service().expires_from_now(
  539. impl_.get_implementation(), expiry_time, ec);
  540. }
  541. /// Perform a blocking wait on the timer.
  542. /**
  543. * This function is used to wait for the timer to expire. This function
  544. * blocks and does not return until the timer has expired.
  545. *
  546. * @throws asio::system_error Thrown on failure.
  547. */
  548. void wait()
  549. {
  550. asio::error_code ec;
  551. impl_.get_service().wait(impl_.get_implementation(), ec);
  552. asio::detail::throw_error(ec, "wait");
  553. }
  554. /// Perform a blocking wait on the timer.
  555. /**
  556. * This function is used to wait for the timer to expire. This function
  557. * blocks and does not return until the timer has expired.
  558. *
  559. * @param ec Set to indicate what error occurred, if any.
  560. */
  561. void wait(asio::error_code& ec)
  562. {
  563. impl_.get_service().wait(impl_.get_implementation(), ec);
  564. }
  565. /// Start an asynchronous wait on the timer.
  566. /**
  567. * This function may be used to initiate an asynchronous wait against the
  568. * timer. It always returns immediately.
  569. *
  570. * For each call to async_wait(), the supplied handler will be called exactly
  571. * once. The handler will be called when:
  572. *
  573. * @li The timer has expired.
  574. *
  575. * @li The timer was cancelled, in which case the handler is passed the error
  576. * code asio::error::operation_aborted.
  577. *
  578. * @param handler The handler to be called when the timer expires. Copies
  579. * will be made of the handler as required. The function signature of the
  580. * handler must be:
  581. * @code void handler(
  582. * const asio::error_code& error // Result of operation.
  583. * ); @endcode
  584. * Regardless of whether the asynchronous operation completes immediately or
  585. * not, the handler will not be invoked from within this function. On
  586. * immediate completion, invocation of the handler will be performed in a
  587. * manner equivalent to using asio::post().
  588. */
  589. template <typename WaitHandler>
  590. ASIO_INITFN_RESULT_TYPE(WaitHandler,
  591. void (asio::error_code))
  592. async_wait(ASIO_MOVE_ARG(WaitHandler) handler)
  593. {
  594. return async_initiate<WaitHandler, void (asio::error_code)>(
  595. initiate_async_wait(), handler, this);
  596. }
  597. private:
  598. // Disallow copying and assignment.
  599. basic_deadline_timer(const basic_deadline_timer&) ASIO_DELETED;
  600. basic_deadline_timer& operator=(
  601. const basic_deadline_timer&) ASIO_DELETED;
  602. struct initiate_async_wait
  603. {
  604. template <typename WaitHandler>
  605. void operator()(ASIO_MOVE_ARG(WaitHandler) handler,
  606. basic_deadline_timer* self) const
  607. {
  608. // If you get an error on the following line it means that your handler
  609. // does not meet the documented type requirements for a WaitHandler.
  610. ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
  611. detail::non_const_lvalue<WaitHandler> handler2(handler);
  612. self->impl_.get_service().async_wait(
  613. self->impl_.get_implementation(), handler2.value,
  614. self->impl_.get_implementation_executor());
  615. }
  616. };
  617. detail::io_object_impl<
  618. detail::deadline_timer_service<TimeTraits>, Executor> impl_;
  619. };
  620. } // namespace asio
  621. #include "asio/detail/pop_options.hpp"
  622. #endif // defined(ASIO_HAS_BOOST_DATE_TIME)
  623. // || defined(GENERATING_DOCUMENTATION)
  624. #endif // ASIO_BASIC_DEADLINE_TIMER_HPP