TLA Line data 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 HIT 6 : 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 6 : 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 4 : cancel_after(capy::IoAwaitable auto&& op, timer::duration timeout)
230 : {
231 : return cancel_at<Backend>(
232 4 : std::forward<decltype(op)>(op), timer::clock_type::now() + timeout);
233 : }
234 :
235 : } // namespace boost::corosio
236 :
237 : #endif
|