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