include/boost/corosio/timer.hpp

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