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_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 HIT 18 : 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 18 : 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 14 : cancel_after(capy::IoAwaitable auto&& op, timer& t, timer::duration timeout)
112 : {
113 : return cancel_at(
114 14 : 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 : @par Example
137 : @code
138 : auto [ec, n] = co_await cancel_at(
139 : sock.read_some( buf ),
140 : clock::now() + 5s );
141 : if (ec == capy::cond::canceled)
142 : // timed out or parent cancelled
143 : @endcode
144 :
145 : @param op The inner I/O awaitable to wrap.
146 : @param deadline The absolute time point at which to cancel.
147 :
148 : @return An awaitable whose result matches @p op's result type.
149 :
150 : @see cancel_after
151 : */
152 : auto
153 6 : cancel_at(capy::IoAwaitable auto&& op, timer::time_point deadline)
154 : {
155 : return detail::cancel_at_awaitable<std::decay_t<decltype(op)>, timer, true>(
156 6 : std::forward<decltype(op)>(op), deadline);
157 : }
158 :
159 : /** Cancel an operation if it does not complete within a duration.
160 :
161 : Convenience overload that creates a @ref timer internally.
162 : Equivalent to `cancel_at( op, clock::now() + timeout )`.
163 :
164 : @par Completion Conditions
165 : The returned awaitable resumes when either:
166 : @li The inner operation completes (successfully or with error).
167 : @li The timeout elapses and the inner operation is cancelled.
168 : @li The caller's stop token is triggered, cancelling both.
169 :
170 : @par Error Conditions
171 : @li On timeout or parent cancellation, the inner operation
172 : completes with an error equal to `capy::cond::canceled`.
173 : @li All other errors are propagated from the inner operation.
174 :
175 : @note Creates a timer per call. Use the explicit-timer overload
176 : to amortize allocation across multiple timeouts.
177 :
178 : @par Example
179 : @code
180 : auto [ec, n] = co_await cancel_after(
181 : sock.read_some( buf ), 5s );
182 : if (ec == capy::cond::canceled)
183 : // timed out
184 : @endcode
185 :
186 : @param op The inner I/O awaitable to wrap.
187 : @param timeout The relative duration after which to cancel.
188 :
189 : @return An awaitable whose result matches @p op's result type.
190 :
191 : @see cancel_at
192 : */
193 : auto
194 4 : cancel_after(capy::IoAwaitable auto&& op, timer::duration timeout)
195 : {
196 : return cancel_at(
197 4 : std::forward<decltype(op)>(op), timer::clock_type::now() + timeout);
198 : }
199 :
200 : } // namespace boost::corosio
201 :
202 : #endif
|