include/boost/corosio/native/native_cancel.hpp

100.0% Lines (4/4) 100.0% List of functions (2/2)
native_cancel.hpp
f(x) Functions (2)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/corosio
8 //
9
10 #ifndef BOOST_COROSIO_NATIVE_NATIVE_CANCEL_HPP
11 #define BOOST_COROSIO_NATIVE_NATIVE_CANCEL_HPP
12
13 #include <boost/corosio/detail/cancel_at_awaitable.hpp>
14 #include <boost/corosio/native/native_timer.hpp>
15 #include <boost/capy/concept/io_awaitable.hpp>
16
17 #include <type_traits>
18 #include <utility>
19
20 namespace boost::corosio {
21
22 /** Cancel an operation if it does not complete by a deadline.
23
24 Overload for @ref native_timer that devirtualizes the internal
25 timer wait, allowing the compiler to inline the timer path.
26 Otherwise identical to the @ref timer overload.
27
28 If the deadline is reached first, the inner operation completes
29 with an error comparing equal to `capy::cond::canceled`. If the
30 inner operation completes first, the timer is cancelled. Parent
31 cancellation is forwarded to both.
32
33 The timer's expiry is overwritten by this call. The timer must
34 outlive the returned awaitable. Do not issue overlapping waits
35 on the same timer.
36
37 @par Completion Conditions
38 The returned awaitable resumes when either:
39 @li The inner operation completes (successfully or with error).
40 @li The deadline expires and the inner operation is cancelled.
41 @li The caller's stop token is triggered, cancelling both.
42
43 @par Error Conditions
44 @li On timeout or parent cancellation, the inner operation
45 completes with an error equal to `capy::cond::canceled`.
46 @li All other errors are propagated from the inner operation.
47
48 @par Example
49 @code
50 native_timer<epoll> t( ioc );
51 auto [ec, n] = co_await cancel_at(
52 sock.read_some( buf ), t,
53 clock::now() + 5s );
54 if (ec == capy::cond::canceled)
55 // timed out or parent cancelled
56 @endcode
57
58 @tparam Backend A backend tag value (e.g., `epoll`).
59
60 @param op The inner I/O awaitable to wrap.
61 @param t The native timer to use for the deadline. Must outlive
62 the returned awaitable.
63 @param deadline The absolute time point at which to cancel.
64
65 @return An awaitable whose result matches @p op's result type.
66
67 @see cancel_after, native_timer
68 */
69 template<auto Backend>
70 auto
71 cancel_at(
72 capy::IoAwaitable auto&& op,
73 native_timer<Backend>& t,
74 timer::time_point deadline)
75 {
76 return detail::cancel_at_awaitable<
77 std::decay_t<decltype(op)>, native_timer<Backend>>(
78 std::forward<decltype(op)>(op), t, deadline);
79 }
80
81 /** Cancel an operation if it does not complete within a duration.
82
83 Overload for @ref native_timer. Equivalent to
84 `cancel_at( op, t, clock::now() + timeout )`.
85
86 The timer's expiry is overwritten by this call. The timer must
87 outlive the returned awaitable. Do not issue overlapping waits
88 on the same timer.
89
90 @par Completion Conditions
91 The returned awaitable resumes when either:
92 @li The inner operation completes (successfully or with error).
93 @li The timeout elapses and the inner operation is cancelled.
94 @li The caller's stop token is triggered, cancelling both.
95
96 @par Error Conditions
97 @li On timeout or parent cancellation, the inner operation
98 completes with an error equal to `capy::cond::canceled`.
99 @li All other errors are propagated from the inner operation.
100
101 @par Example
102 @code
103 native_timer<epoll> t( ioc );
104 auto [ec, n] = co_await cancel_after(
105 sock.read_some( buf ), t, 5s );
106 if (ec == capy::cond::canceled)
107 // timed out
108 @endcode
109
110 @tparam Backend A backend tag value (e.g., `epoll`).
111
112 @param op The inner I/O awaitable to wrap.
113 @param t The native timer to use for the timeout. Must outlive
114 the returned awaitable.
115 @param timeout The relative duration after which to cancel.
116
117 @return An awaitable whose result matches @p op's result type.
118
119 @see cancel_at, native_timer
120 */
121 template<auto Backend>
122 auto
123 cancel_after(
124 capy::IoAwaitable auto&& op,
125 native_timer<Backend>& t,
126 timer::duration timeout)
127 {
128 return cancel_at(
129 std::forward<decltype(op)>(op), t, timer::clock_type::now() + timeout);
130 }
131
132 /** Cancel an operation if it does not complete by a deadline.
133
134 Convenience overload that creates a @ref native_timer internally,
135 devirtualizing the timer wait. Otherwise identical to the
136 explicit-timer overload.
137
138 @par Completion Conditions
139 The returned awaitable resumes when either:
140 @li The inner operation completes (successfully or with error).
141 @li The deadline expires and the inner operation is cancelled.
142 @li The caller's stop token is triggered, cancelling both.
143
144 @par Error Conditions
145 @li On timeout or parent cancellation, the inner operation
146 completes with an error equal to `capy::cond::canceled`.
147 @li All other errors are propagated from the inner operation.
148
149 @note Creates a timer per call. Use the explicit-timer overload
150 to amortize allocation across multiple timeouts.
151
152 @note The awaiting coroutine's executor must be backed by an
153 io_context (the deadline timer is built from it). Awaiting this
154 on a non-io_context executor is a precondition violation and
155 aborts; use the explicit-timer overload to construct the timer
156 yourself if you need a catchable error.
157
158 @par Example
159 @code
160 auto [ec, n] = co_await cancel_at<epoll>(
161 sock.read_some( buf ),
162 clock::now() + 5s );
163 if (ec == capy::cond::canceled)
164 // timed out or parent cancelled
165 @endcode
166
167 @tparam Backend A backend tag value (e.g., `epoll`).
168
169 @param op The inner I/O awaitable to wrap.
170 @param deadline The absolute time point at which to cancel.
171
172 @return An awaitable whose result matches @p op's result type.
173
174 @see cancel_after, native_timer
175 */
176 template<auto Backend>
177 auto
178 6x cancel_at(capy::IoAwaitable auto&& op, timer::time_point deadline)
179 {
180 return detail::cancel_at_awaitable<
181 std::decay_t<decltype(op)>, native_timer<Backend>, true>(
182 6x std::forward<decltype(op)>(op), deadline);
183 }
184
185 /** Cancel an operation if it does not complete within a duration.
186
187 Convenience overload that creates a @ref native_timer internally.
188 Equivalent to `cancel_at<Backend>( op, clock::now() + timeout )`.
189
190 @par Completion Conditions
191 The returned awaitable resumes when either:
192 @li The inner operation completes (successfully or with error).
193 @li The timeout elapses and the inner operation is cancelled.
194 @li The caller's stop token is triggered, cancelling both.
195
196 @par Error Conditions
197 @li On timeout or parent cancellation, the inner operation
198 completes with an error equal to `capy::cond::canceled`.
199 @li All other errors are propagated from the inner operation.
200
201 @note Creates a timer per call. Use the explicit-timer overload
202 to amortize allocation across multiple timeouts.
203
204 @note The awaiting coroutine's executor must be backed by an
205 io_context (the deadline timer is built from it). Awaiting this
206 on a non-io_context executor is a precondition violation and
207 aborts; use the explicit-timer overload to construct the timer
208 yourself if you need a catchable error.
209
210 @par Example
211 @code
212 auto [ec, n] = co_await cancel_after<epoll>(
213 sock.read_some( buf ), 5s );
214 if (ec == capy::cond::canceled)
215 // timed out
216 @endcode
217
218 @tparam Backend A backend tag value (e.g., `epoll`).
219
220 @param op The inner I/O awaitable to wrap.
221 @param timeout The relative duration after which to cancel.
222
223 @return An awaitable whose result matches @p op's result type.
224
225 @see cancel_at, native_timer
226 */
227 template<auto Backend>
228 auto
229 4x cancel_after(capy::IoAwaitable auto&& op, timer::duration timeout)
230 {
231 return cancel_at<Backend>(
232 4x std::forward<decltype(op)>(op), timer::clock_type::now() + timeout);
233 }
234
235 } // namespace boost::corosio
236
237 #endif
238