100.00% Lines (28/28) 100.00% Functions (6/6)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3   // Copyright (c) 2026 Steve Gerbino 3   // Copyright (c) 2026 Steve Gerbino
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 5   // Distributed under the Boost Software License, Version 1.0. (See accompanying
6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/cppalliance/corosio 8   // Official repository: https://github.com/cppalliance/corosio
9   // 9   //
10   10  
11   #ifndef BOOST_COROSIO_TIMER_HPP 11   #ifndef BOOST_COROSIO_TIMER_HPP
12   #define BOOST_COROSIO_TIMER_HPP 12   #define BOOST_COROSIO_TIMER_HPP
13   13  
14   #include <boost/corosio/detail/config.hpp> 14   #include <boost/corosio/detail/config.hpp>
15   #include <boost/corosio/io/io_timer.hpp> 15   #include <boost/corosio/io/io_timer.hpp>
16   #include <boost/capy/ex/execution_context.hpp> 16   #include <boost/capy/ex/execution_context.hpp>
17   #include <boost/capy/concept/executor.hpp> 17   #include <boost/capy/concept/executor.hpp>
18   18  
19   #include <chrono> 19   #include <chrono>
20   #include <cstddef> 20   #include <cstddef>
21   21  
22   namespace boost::corosio { 22   namespace boost::corosio {
23   23  
24   /** An asynchronous timer for coroutine I/O. 24   /** An asynchronous timer for coroutine I/O.
25   25  
26   This class provides asynchronous timer operations that return 26   This class provides asynchronous timer operations that return
27   awaitable types. The timer can be used to schedule operations 27   awaitable types. The timer can be used to schedule operations
28   to occur after a specified duration or at a specific time point. 28   to occur after a specified duration or at a specific time point.
29   29  
30   Multiple coroutines may wait concurrently on the same timer. 30   Multiple coroutines may wait concurrently on the same timer.
31   When the timer expires, all waiters complete with success. When 31   When the timer expires, all waiters complete with success. When
32   the timer is cancelled, all waiters complete with an error that 32   the timer is cancelled, all waiters complete with an error that
33   compares equal to `capy::cond::canceled`. 33   compares equal to `capy::cond::canceled`.
34   34  
35   Each timer operation participates in the affine awaitable protocol, 35   Each timer operation participates in the affine awaitable protocol,
36   ensuring coroutines resume on the correct executor. 36   ensuring coroutines resume on the correct executor.
37   37  
38   @par Thread Safety 38   @par Thread Safety
39   Distinct objects: Safe.@n 39   Distinct objects: Safe.@n
40   Shared objects: Unsafe. 40   Shared objects: Unsafe.
41   41  
42   @par Semantics 42   @par Semantics
43   Wraps platform timer facilities via the io_context reactor. 43   Wraps platform timer facilities via the io_context reactor.
44   Operations dispatch to OS timer APIs (timerfd, IOCP timers, 44   Operations dispatch to OS timer APIs (timerfd, IOCP timers,
45   kqueue EVFILT_TIMER). 45   kqueue EVFILT_TIMER).
46   */ 46   */
47   class BOOST_COROSIO_DECL timer : public io_timer 47   class BOOST_COROSIO_DECL timer : public io_timer
48   { 48   {
49   public: 49   public:
50   /// Alias for backward compatibility. 50   /// Alias for backward compatibility.
51   using implementation = io_timer::implementation; 51   using implementation = io_timer::implementation;
52   52  
53   /** Destructor. 53   /** Destructor.
54   54  
55   Cancels any pending operations and releases timer resources. 55   Cancels any pending operations and releases timer resources.
56   */ 56   */
57   ~timer() override; 57   ~timer() override;
58   58  
59   /** Construct a timer from an execution context. 59   /** Construct a timer from an execution context.
60   60  
61   @param ctx The execution context that will own this timer. 61   @param ctx The execution context that will own this timer.
62   */ 62   */
63   explicit timer(capy::execution_context& ctx); 63   explicit timer(capy::execution_context& ctx);
64   64  
65   /** Construct a timer with an initial absolute expiry time. 65   /** Construct a timer with an initial absolute expiry time.
66   66  
67   @param ctx The execution context that will own this timer. 67   @param ctx The execution context that will own this timer.
68   @param t The initial expiry time point. 68   @param t The initial expiry time point.
69   */ 69   */
70   timer(capy::execution_context& ctx, time_point t); 70   timer(capy::execution_context& ctx, time_point t);
71   71  
72   /** Construct a timer with an initial relative expiry time. 72   /** Construct a timer with an initial relative expiry time.
73   73  
74   @param ctx The execution context that will own this timer. 74   @param ctx The execution context that will own this timer.
75   @param d The initial expiry duration relative to now. 75   @param d The initial expiry duration relative to now.
76   */ 76   */
77   template<class Rep, class Period> 77   template<class Rep, class Period>
HITCBC 78   2 timer(capy::execution_context& ctx, std::chrono::duration<Rep, Period> d) 78   2 timer(capy::execution_context& ctx, std::chrono::duration<Rep, Period> d)
HITCBC 79   2 : timer(ctx) 79   2 : timer(ctx)
80   { 80   {
HITCBC 81   2 expires_after(d); 81   2 expires_after(d);
HITCBC 82   2 } 82   2 }
83   83  
84   /** Move constructor. 84   /** Move constructor.
85   85  
86   Transfers ownership of the timer resources. 86   Transfers ownership of the timer resources.
87   87  
88   @param other The timer to move from. 88   @param other The timer to move from.
89   89  
90   @pre No awaitables returned by @p other's methods exist. 90   @pre No awaitables returned by @p other's methods exist.
91   @pre The execution context associated with @p other must 91   @pre The execution context associated with @p other must
92   outlive this timer. 92   outlive this timer.
93   */ 93   */
94   timer(timer&& other) noexcept; 94   timer(timer&& other) noexcept;
95   95  
96   /** Move assignment operator. 96   /** Move assignment operator.
97   97  
98   Closes any existing timer and transfers ownership. 98   Closes any existing timer and transfers ownership.
99   99  
100   @param other The timer to move from. 100   @param other The timer to move from.
101   101  
102   @pre No awaitables returned by either `*this` or @p other's 102   @pre No awaitables returned by either `*this` or @p other's
103   methods exist. 103   methods exist.
104   @pre The execution context associated with @p other must 104   @pre The execution context associated with @p other must
105   outlive this timer. 105   outlive this timer.
106   106  
107   @return Reference to this timer. 107   @return Reference to this timer.
108   */ 108   */
109   timer& operator=(timer&& other) noexcept; 109   timer& operator=(timer&& other) noexcept;
110   110  
111   timer(timer const&) = delete; 111   timer(timer const&) = delete;
112   timer& operator=(timer const&) = delete; 112   timer& operator=(timer const&) = delete;
113   113  
114   /** Cancel one pending asynchronous wait operation. 114   /** Cancel one pending asynchronous wait operation.
115   115  
116   The oldest pending wait is cancelled (FIFO order). It 116   The oldest pending wait is cancelled (FIFO order). It
117   completes with an error code that compares equal to 117   completes with an error code that compares equal to
118   `capy::cond::canceled`. 118   `capy::cond::canceled`.
119   119  
120   @return The number of operations that were cancelled (0 or 1). 120   @return The number of operations that were cancelled (0 or 1).
121   */ 121   */
HITCBC 122   4 std::size_t cancel_one() 122   4 std::size_t cancel_one()
123   { 123   {
HITCBC 124   4 if (!get().might_have_pending_waits_) 124   4 if (!get().might_have_pending_waits_)
HITCBC 125   2 return 0; 125   2 return 0;
HITCBC 126   2 return do_cancel_one(); 126   2 return do_cancel_one();
127   } 127   }
128   128  
129   /** Set the timer's expiry time as an absolute time. 129   /** Set the timer's expiry time as an absolute time.
130   130  
131   Any pending asynchronous wait operations will be cancelled. 131   Any pending asynchronous wait operations will be cancelled.
132   132  
133   @param t The expiry time to be used for the timer. 133   @param t The expiry time to be used for the timer.
134   134  
135   @return The number of pending operations that were cancelled. 135   @return The number of pending operations that were cancelled.
136   */ 136   */
HITCBC 137   42 std::size_t expires_at(time_point t) 137   42 std::size_t expires_at(time_point t)
138   { 138   {
HITCBC 139   42 auto& impl = get(); 139   42 auto& impl = get();
HITCBC 140   42 impl.expiry_ = t; 140   42 impl.expiry_ = t;
HITCBC 141   42 if (impl.heap_index_ == implementation::npos && 141   42 if (impl.heap_index_ == implementation::npos &&
HITCBC 142   40 !impl.might_have_pending_waits_) 142   40 !impl.might_have_pending_waits_)
HITCBC 143   40 return 0; 143   40 return 0;
HITCBC 144   2 return do_update_expiry(); 144   2 return do_update_expiry();
145   } 145   }
146   146  
147   /** Set the timer's expiry time relative to now. 147   /** Set the timer's expiry time relative to now.
148   148  
149   Any pending asynchronous wait operations will be cancelled. 149   Any pending asynchronous wait operations will be cancelled.
150   150  
151   @param d The expiry time relative to now. 151   @param d The expiry time relative to now.
152   152  
153   @return The number of pending operations that were cancelled. 153   @return The number of pending operations that were cancelled.
154   */ 154   */
HITCBC 155   7896 std::size_t expires_after(duration d) 155   6655 std::size_t expires_after(duration d)
156   { 156   {
HITCBC 157   7896 auto& impl = get(); 157   6655 auto& impl = get();
HITCBC 158   7896 if (d <= duration::zero()) 158   6655 if (d <= duration::zero())
HITCBC 159   6 impl.expiry_ = (time_point::min)(); 159   6 impl.expiry_ = (time_point::min)();
160   else 160   else
HITCBC 161   7890 impl.expiry_ = clock_type::now() + d; 161   6649 impl.expiry_ = clock_type::now() + d;
HITCBC 162   7896 if (impl.heap_index_ == implementation::npos && 162   6655 if (impl.heap_index_ == implementation::npos &&
HITCBC 163   7892 !impl.might_have_pending_waits_) 163   6651 !impl.might_have_pending_waits_)
HITCBC 164   7892 return 0; 164   6651 return 0;
HITCBC 165   4 return do_update_expiry(); 165   4 return do_update_expiry();
166   } 166   }
167   167  
168   /** Set the timer's expiry time relative to now. 168   /** Set the timer's expiry time relative to now.
169   169  
170   This is a convenience overload that accepts any duration type 170   This is a convenience overload that accepts any duration type
171   and converts it to the timer's native duration type. Any 171   and converts it to the timer's native duration type. Any
172   pending asynchronous wait operations will be cancelled. 172   pending asynchronous wait operations will be cancelled.
173   173  
174   @param d The expiry time relative to now. 174   @param d The expiry time relative to now.
175   175  
176   @return The number of pending operations that were cancelled. 176   @return The number of pending operations that were cancelled.
177   */ 177   */
178   template<class Rep, class Period> 178   template<class Rep, class Period>
HITCBC 179   7896 std::size_t expires_after(std::chrono::duration<Rep, Period> d) 179   6655 std::size_t expires_after(std::chrono::duration<Rep, Period> d)
180   { 180   {
HITCBC 181   7896 return expires_after(std::chrono::duration_cast<duration>(d)); 181   6655 return expires_after(std::chrono::duration_cast<duration>(d));
182   } 182   }
183   183  
184   protected: 184   protected:
185   explicit timer(handle h) noexcept : io_timer(std::move(h)) {} 185   explicit timer(handle h) noexcept : io_timer(std::move(h)) {}
186   186  
187   private: 187   private:
188   std::size_t do_cancel() override; 188   std::size_t do_cancel() override;
189   std::size_t do_cancel_one(); 189   std::size_t do_cancel_one();
190   std::size_t do_update_expiry(); 190   std::size_t do_update_expiry();
191   191  
192   /// Return the underlying implementation. 192   /// Return the underlying implementation.
HITCBC 193   7958 implementation& get() const noexcept 193   6717 implementation& get() const noexcept
194   { 194   {
HITCBC 195   7958 return *static_cast<implementation*>(h_.get()); 195   6717 return *static_cast<implementation*>(h_.get());
196   } 196   }
197   }; 197   };
198   198  
199   } // namespace boost::corosio 199   } // namespace boost::corosio
200   200  
201   #endif 201   #endif