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   6966 std::size_t expires_after(duration d) 155   8178 std::size_t expires_after(duration d)
156   { 156   {
HITCBC 157   6966 auto& impl = get(); 157   8178 auto& impl = get();
HITCBC 158   6966 if (d <= duration::zero()) 158   8178 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   6960 impl.expiry_ = clock_type::now() + d; 161   8172 impl.expiry_ = clock_type::now() + d;
HITCBC 162   6966 if (impl.heap_index_ == implementation::npos && 162   8178 if (impl.heap_index_ == implementation::npos &&
HITCBC 163   6962 !impl.might_have_pending_waits_) 163   8174 !impl.might_have_pending_waits_)
HITCBC 164   6962 return 0; 164   8174 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   6966 std::size_t expires_after(std::chrono::duration<Rep, Period> d) 179   8178 std::size_t expires_after(std::chrono::duration<Rep, Period> d)
180   { 180   {
HITCBC 181   6966 return expires_after(std::chrono::duration_cast<duration>(d)); 181   8178 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   7028 implementation& get() const noexcept 193   8240 implementation& get() const noexcept
194   { 194   {
HITCBC 195   7028 return *static_cast<implementation*>(h_.get()); 195   8240 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