include/boost/corosio/timer.hpp

100.0% Lines (35/35) 100.0% List of functions (13/13)
timer.hpp
f(x) Functions (13)
Function Calls Lines Blocks
boost::corosio::timer::timer<long, std::ratio<1l, 1000l> >(boost::capy::execution_context&, std::chrono::duration<long, std::ratio<1l, 1000l> >) :92 8x 100.0% 80.0% boost::corosio::timer::timer<boost::capy::thread_pool::executor_type>(boost::capy::thread_pool::executor_type const&) :111 2x 50.0% 100.0% boost::corosio::timer::timer<boost::corosio::io_context::executor_type>(boost::corosio::io_context::executor_type const&) :111 2x 100.0% 100.0% boost::corosio::timer::timer<boost::corosio::io_context::executor_type>(boost::corosio::io_context::executor_type const&, std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > >) :125 2x 100.0% 100.0% boost::corosio::timer::timer<boost::corosio::io_context::executor_type, long, std::ratio<1l, 1000l> >(boost::corosio::io_context::executor_type const&, std::chrono::duration<long, std::ratio<1l, 1000l> >) :139 2x 100.0% 100.0% boost::corosio::timer::cancel_one() :182 4x 100.0% 100.0% boost::corosio::timer::expires_at(std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > >) :197 54x 100.0% 100.0% boost::corosio::timer::expires_after(std::chrono::duration<long, std::ratio<1l, 1000000000l> >) :215 9077x 100.0% 94.0% unsigned long boost::corosio::timer::expires_after<long, std::ratio<1l, 1000000l> >(std::chrono::duration<long, std::ratio<1l, 1000000l> >) :239 8348x 100.0% 100.0% unsigned long boost::corosio::timer::expires_after<long, std::ratio<1l, 1000l> >(std::chrono::duration<long, std::ratio<1l, 1000l> >) :239 645x 100.0% 100.0% unsigned long boost::corosio::timer::expires_after<long, std::ratio<1l, 1l> >(std::chrono::duration<long, std::ratio<1l, 1l> >) :239 68x 100.0% 100.0% unsigned long boost::corosio::timer::expires_after<long, std::ratio<3600l, 1l> >(std::chrono::duration<long, std::ratio<3600l, 1l> >) :239 16x 100.0% 100.0% boost::corosio::timer::get() const :253 9153x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2026 Steve Gerbino
4 //
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)
7 //
8 // Official repository: https://github.com/cppalliance/corosio
9 //
10
11 #ifndef BOOST_COROSIO_TIMER_HPP
12 #define BOOST_COROSIO_TIMER_HPP
13
14 #include <boost/corosio/detail/config.hpp>
15 #include <boost/corosio/io/io_timer.hpp>
16 #include <boost/capy/ex/execution_context.hpp>
17 #include <boost/capy/concept/executor.hpp>
18
19 #include <chrono>
20 #include <concepts>
21 #include <cstddef>
22 #include <type_traits>
23
24 namespace boost::corosio {
25
26 /** An asynchronous timer for coroutine I/O.
27
28 This class provides asynchronous timer operations that return
29 awaitable types. The timer can be used to schedule operations
30 to occur after a specified duration or at a specific time point.
31
32 Multiple coroutines may wait concurrently on the same timer.
33 When the timer expires, all waiters complete with success. When
34 the timer is cancelled, all waiters complete with an error that
35 compares equal to `capy::cond::canceled`.
36
37 Each timer operation participates in the affine awaitable protocol,
38 ensuring coroutines resume on the correct executor.
39
40 @par Thread Safety
41 Distinct objects: Safe.@n
42 Shared objects: Unsafe.
43
44 @par Semantics
45 Wraps platform timer facilities via the io_context reactor.
46 Operations dispatch to OS timer APIs (timerfd, IOCP timers,
47 kqueue EVFILT_TIMER).
48 */
49 class BOOST_COROSIO_DECL timer : public io_timer
50 {
51 public:
52 /// Alias for backward compatibility.
53 using implementation = io_timer::implementation;
54
55 /** Destructor.
56
57 Cancels any pending operations and releases timer resources.
58 */
59 ~timer() override;
60
61 /** Construct a timer from an execution context.
62
63 @param ctx The execution context that will own this timer. It
64 must be a corosio io_context; otherwise the constructor
65 throws (a timer service is required).
66
67 @throws std::logic_error if @p ctx is not an io_context.
68 */
69 explicit timer(capy::execution_context& ctx);
70
71 /** Construct a timer with an initial absolute expiry time.
72
73 @param ctx The execution context that will own this timer. It
74 must be a corosio io_context; otherwise the constructor
75 throws (a timer service is required).
76 @param t The initial expiry time point.
77
78 @throws std::logic_error if @p ctx is not an io_context.
79 */
80 timer(capy::execution_context& ctx, time_point t);
81
82 /** Construct a timer with an initial relative expiry time.
83
84 @param ctx The execution context that will own this timer. It
85 must be a corosio io_context; otherwise the constructor
86 throws (a timer service is required).
87 @param d The initial expiry duration relative to now.
88
89 @throws std::logic_error if @p ctx is not an io_context.
90 */
91 template<class Rep, class Period>
92 8x timer(capy::execution_context& ctx, std::chrono::duration<Rep, Period> d)
93 8x : timer(ctx)
94 {
95 8x expires_after(d);
96 8x }
97
98 /** Construct a timer from an executor.
99
100 The timer is associated with the executor's context, which must
101 be a corosio io_context.
102
103 @param ex The executor whose context will own this timer.
104
105 @throws std::logic_error if the executor's context is not an
106 io_context.
107 */
108 template<class Ex>
109 requires(!std::same_as<std::remove_cvref_t<Ex>, timer>) &&
110 capy::Executor<Ex>
111 4x explicit timer(Ex const& ex) : timer(ex.context())
112 {
113 2x }
114
115 /** Construct a timer from an executor with an absolute expiry time.
116
117 @param ex The executor whose context will own this timer.
118 @param t The initial expiry time point.
119
120 @throws std::logic_error if the executor's context is not an
121 io_context.
122 */
123 template<class Ex>
124 requires capy::Executor<Ex>
125 2x timer(Ex const& ex, time_point t) : timer(ex.context(), t)
126 {
127 2x }
128
129 /** Construct a timer from an executor with a relative expiry time.
130
131 @param ex The executor whose context will own this timer.
132 @param d The initial expiry duration relative to now.
133
134 @throws std::logic_error if the executor's context is not an
135 io_context.
136 */
137 template<class Ex, class Rep, class Period>
138 requires capy::Executor<Ex>
139 2x timer(Ex const& ex, std::chrono::duration<Rep, Period> d)
140 2x : timer(ex.context(), d)
141 {
142 2x }
143
144 /** Move constructor.
145
146 Transfers ownership of the timer resources.
147
148 @param other The timer to move from.
149
150 @pre No awaitables returned by @p other's methods exist.
151 @pre The execution context associated with @p other must
152 outlive this timer.
153 */
154 timer(timer&& other) noexcept;
155
156 /** Move assignment operator.
157
158 Closes any existing timer and transfers ownership.
159
160 @param other The timer to move from.
161
162 @pre No awaitables returned by either `*this` or @p other's
163 methods exist.
164 @pre The execution context associated with @p other must
165 outlive this timer.
166
167 @return Reference to this timer.
168 */
169 timer& operator=(timer&& other) noexcept;
170
171 timer(timer const&) = delete;
172 timer& operator=(timer const&) = delete;
173
174 /** Cancel one pending asynchronous wait operation.
175
176 The oldest pending wait is cancelled (FIFO order). It
177 completes with an error code that compares equal to
178 `capy::cond::canceled`.
179
180 @return The number of operations that were cancelled (0 or 1).
181 */
182 4x std::size_t cancel_one()
183 {
184 4x if (!get().might_have_pending_waits_)
185 2x return 0;
186 2x return do_cancel_one();
187 }
188
189 /** Set the timer's expiry time as an absolute time.
190
191 Any pending asynchronous wait operations will be cancelled.
192
193 @param t The expiry time to be used for the timer.
194
195 @return The number of pending operations that were cancelled.
196 */
197 54x std::size_t expires_at(time_point t)
198 {
199 54x auto& impl = get();
200 54x impl.expiry_ = t;
201 54x if (impl.heap_index_ == implementation::npos &&
202 50x !impl.might_have_pending_waits_)
203 50x return 0;
204 4x return do_update_expiry();
205 }
206
207 /** Set the timer's expiry time relative to now.
208
209 Any pending asynchronous wait operations will be cancelled.
210
211 @param d The expiry time relative to now.
212
213 @return The number of pending operations that were cancelled.
214 */
215 9077x std::size_t expires_after(duration d)
216 {
217 9077x auto& impl = get();
218 9077x if (d <= duration::zero())
219 6x impl.expiry_ = (time_point::min)();
220 else
221 9071x impl.expiry_ = clock_type::now() + d;
222 9077x if (impl.heap_index_ == implementation::npos &&
223 9073x !impl.might_have_pending_waits_)
224 9073x return 0;
225 4x return do_update_expiry();
226 }
227
228 /** Set the timer's expiry time relative to now.
229
230 This is a convenience overload that accepts any duration type
231 and converts it to the timer's native duration type. Any
232 pending asynchronous wait operations will be cancelled.
233
234 @param d The expiry time relative to now.
235
236 @return The number of pending operations that were cancelled.
237 */
238 template<class Rep, class Period>
239 9077x std::size_t expires_after(std::chrono::duration<Rep, Period> d)
240 {
241 9077x return expires_after(std::chrono::duration_cast<duration>(d));
242 }
243
244 protected:
245 explicit timer(handle h) noexcept : io_timer(std::move(h)) {}
246
247 private:
248 std::size_t do_cancel() override;
249 std::size_t do_cancel_one();
250 std::size_t do_update_expiry();
251
252 /// Return the underlying implementation.
253 9153x implementation& get() const noexcept
254 {
255 9153x return *static_cast<implementation*>(h_.get());
256 }
257 };
258
259 } // namespace boost::corosio
260
261 #endif
262