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