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 : @par Example
153 : @code
154 : auto [ec, n] = co_await cancel_at<epoll>(
155 : sock.read_some( buf ),
156 : clock::now() + 5s );
157 : if (ec == capy::cond::canceled)
158 : // timed out or parent cancelled
159 : @endcode
160 :
161 : @tparam Backend A backend tag value (e.g., `epoll`).
162 :
163 : @param op The inner I/O awaitable to wrap.
164 : @param deadline The absolute time point at which to cancel.
165 :
166 : @return An awaitable whose result matches @p op's result type.
167 :
168 : @see cancel_after, native_timer
169 : */
170 : template<auto Backend>
171 : auto
172 HIT 6 : cancel_at(capy::IoAwaitable auto&& op, timer::time_point deadline)
173 : {
174 : return detail::cancel_at_awaitable<
175 : std::decay_t<decltype(op)>, native_timer<Backend>, true>(
176 6 : std::forward<decltype(op)>(op), deadline);
177 : }
178 :
179 : /** Cancel an operation if it does not complete within a duration.
180 :
181 : Convenience overload that creates a @ref native_timer internally.
182 : Equivalent to `cancel_at<Backend>( op, clock::now() + timeout )`.
183 :
184 : @par Completion Conditions
185 : The returned awaitable resumes when either:
186 : @li The inner operation completes (successfully or with error).
187 : @li The timeout elapses and the inner operation is cancelled.
188 : @li The caller's stop token is triggered, cancelling both.
189 :
190 : @par Error Conditions
191 : @li On timeout or parent cancellation, the inner operation
192 : completes with an error equal to `capy::cond::canceled`.
193 : @li All other errors are propagated from the inner operation.
194 :
195 : @note Creates a timer per call. Use the explicit-timer overload
196 : to amortize allocation across multiple timeouts.
197 :
198 : @par Example
199 : @code
200 : auto [ec, n] = co_await cancel_after<epoll>(
201 : sock.read_some( buf ), 5s );
202 : if (ec == capy::cond::canceled)
203 : // timed out
204 : @endcode
205 :
206 : @tparam Backend A backend tag value (e.g., `epoll`).
207 :
208 : @param op The inner I/O awaitable to wrap.
209 : @param timeout The relative duration after which to cancel.
210 :
211 : @return An awaitable whose result matches @p op's result type.
212 :
213 : @see cancel_at, native_timer
214 : */
215 : template<auto Backend>
216 : auto
217 4 : cancel_after(capy::IoAwaitable auto&& op, timer::duration timeout)
218 : {
219 : return cancel_at<Backend>(
220 4 : std::forward<decltype(op)>(op), timer::clock_type::now() + timeout);
221 : }
222 :
223 : } // namespace boost::corosio
224 :
225 : #endif
|