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