include/boost/corosio/cancel.hpp

100.0% Lines (8/8) 100.0% List of functions (4/4)
cancel.hpp
f(x) Functions (4)
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_CANCEL_HPP
11 #define BOOST_COROSIO_CANCEL_HPP
12
13 #include <boost/corosio/detail/cancel_at_awaitable.hpp>
14 #include <boost/corosio/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 Races @p op against the given timer. If the deadline is reached
25 first, the inner operation is cancelled via its stop token and
26 completes with an error comparing equal to `capy::cond::canceled`.
27 If the inner operation completes first, the timer is cancelled.
28
29 Parent cancellation (from the caller's stop token) is forwarded
30 to both the inner operation and the timeout timer.
31
32 The timer's expiry is overwritten by this call. The timer must
33 outlive the returned awaitable. Do not issue overlapping waits
34 on the same timer.
35
36 @par Completion Conditions
37 The returned awaitable resumes when either:
38 @li The inner operation completes (successfully or with error).
39 @li The deadline expires and the inner operation is cancelled.
40 @li The caller's stop token is triggered, cancelling both.
41
42 @par Error Conditions
43 @li On timeout or parent cancellation, the inner operation
44 completes with an error equal to `capy::cond::canceled`.
45 @li All other errors are propagated from the inner operation.
46
47 @par Example
48 @code
49 timer timeout_timer( ioc );
50 auto [ec, n] = co_await cancel_at(
51 sock.read_some( buf ), timeout_timer,
52 clock::now() + 5s );
53 if (ec == capy::cond::canceled)
54 // timed out or parent cancelled
55 @endcode
56
57 @param op The inner I/O awaitable to wrap.
58 @param t The timer to use for the deadline. Must outlive
59 the returned awaitable.
60 @param deadline The absolute time point at which to cancel.
61
62 @return An awaitable whose result matches @p op's result type.
63
64 @see cancel_after
65 */
66 auto
67 18x cancel_at(capy::IoAwaitable auto&& op, timer& t, timer::time_point deadline)
68 {
69 return detail::cancel_at_awaitable<std::decay_t<decltype(op)>, timer>(
70 18x std::forward<decltype(op)>(op), t, deadline);
71 }
72
73 /** Cancel an operation if it does not complete within a duration.
74
75 Equivalent to `cancel_at( op, t, clock::now() + timeout )`.
76
77 The timer's expiry is overwritten by this call. The timer must
78 outlive the returned awaitable. Do not issue overlapping waits
79 on the same timer.
80
81 @par Completion Conditions
82 The returned awaitable resumes when either:
83 @li The inner operation completes (successfully or with error).
84 @li The timeout elapses and the inner operation is cancelled.
85 @li The caller's stop token is triggered, cancelling both.
86
87 @par Error Conditions
88 @li On timeout or parent cancellation, the inner operation
89 completes with an error equal to `capy::cond::canceled`.
90 @li All other errors are propagated from the inner operation.
91
92 @par Example
93 @code
94 timer timeout_timer( ioc );
95 auto [ec, n] = co_await cancel_after(
96 sock.read_some( buf ), timeout_timer, 5s );
97 if (ec == capy::cond::canceled)
98 // timed out
99 @endcode
100
101 @param op The inner I/O awaitable to wrap.
102 @param t The timer to use for the timeout. Must outlive
103 the returned awaitable.
104 @param timeout The relative duration after which to cancel.
105
106 @return An awaitable whose result matches @p op's result type.
107
108 @see cancel_at
109 */
110 auto
111 14x cancel_after(capy::IoAwaitable auto&& op, timer& t, timer::duration timeout)
112 {
113 return cancel_at(
114 14x std::forward<decltype(op)>(op), t, timer::clock_type::now() + timeout);
115 }
116
117 /** Cancel an operation if it does not complete by a deadline.
118
119 Convenience overload that creates a @ref timer internally.
120 Otherwise identical to the explicit-timer overload.
121
122 @par Completion Conditions
123 The returned awaitable resumes when either:
124 @li The inner operation completes (successfully or with error).
125 @li The deadline expires and the inner operation is cancelled.
126 @li The caller's stop token is triggered, cancelling both.
127
128 @par Error Conditions
129 @li On timeout or parent cancellation, the inner operation
130 completes with an error equal to `capy::cond::canceled`.
131 @li All other errors are propagated from the inner operation.
132
133 @note Creates a timer per call. Use the explicit-timer overload
134 to amortize allocation across multiple timeouts.
135
136 @note The awaiting coroutine's executor must be backed by an
137 io_context (the deadline timer is built from it). Awaiting this
138 on a non-io_context executor is a precondition violation and
139 aborts; use the explicit-timer overload to construct the timer
140 yourself if you need a catchable error.
141
142 @par Example
143 @code
144 auto [ec, n] = co_await cancel_at(
145 sock.read_some( buf ),
146 clock::now() + 5s );
147 if (ec == capy::cond::canceled)
148 // timed out or parent cancelled
149 @endcode
150
151 @param op The inner I/O awaitable to wrap.
152 @param deadline The absolute time point at which to cancel.
153
154 @return An awaitable whose result matches @p op's result type.
155
156 @see cancel_after
157 */
158 auto
159 6x cancel_at(capy::IoAwaitable auto&& op, timer::time_point deadline)
160 {
161 return detail::cancel_at_awaitable<std::decay_t<decltype(op)>, timer, true>(
162 6x std::forward<decltype(op)>(op), deadline);
163 }
164
165 /** Cancel an operation if it does not complete within a duration.
166
167 Convenience overload that creates a @ref timer internally.
168 Equivalent to `cancel_at( op, clock::now() + timeout )`.
169
170 @par Completion Conditions
171 The returned awaitable resumes when either:
172 @li The inner operation completes (successfully or with error).
173 @li The timeout elapses and the inner operation is cancelled.
174 @li The caller's stop token is triggered, cancelling both.
175
176 @par Error Conditions
177 @li On timeout or parent cancellation, the inner operation
178 completes with an error equal to `capy::cond::canceled`.
179 @li All other errors are propagated from the inner operation.
180
181 @note Creates a timer per call. Use the explicit-timer overload
182 to amortize allocation across multiple timeouts.
183
184 @note The awaiting coroutine's executor must be backed by an
185 io_context (the deadline timer is built from it). Awaiting this
186 on a non-io_context executor is a precondition violation and
187 aborts; use the explicit-timer overload to construct the timer
188 yourself if you need a catchable error.
189
190 @par Example
191 @code
192 auto [ec, n] = co_await cancel_after(
193 sock.read_some( buf ), 5s );
194 if (ec == capy::cond::canceled)
195 // timed out
196 @endcode
197
198 @param op The inner I/O awaitable to wrap.
199 @param timeout The relative duration after which to cancel.
200
201 @return An awaitable whose result matches @p op's result type.
202
203 @see cancel_at
204 */
205 auto
206 4x cancel_after(capy::IoAwaitable auto&& op, timer::duration timeout)
207 {
208 return cancel_at(
209 4x std::forward<decltype(op)>(op), timer::clock_type::now() + timeout);
210 }
211
212 } // namespace boost::corosio
213
214 #endif
215