libs/capy/include/boost/capy/ex/immediate.hpp

100.0% Lines (22/22) 84.0% Functions (21/25) -% Branches (0/0)
libs/capy/include/boost/capy/ex/immediate.hpp
Line Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
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/capy
8 //
9
10 #ifndef BOOST_CAPY_EX_IMMEDIATE_HPP
11 #define BOOST_CAPY_EX_IMMEDIATE_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/ex/executor_ref.hpp>
15 #include <boost/capy/io_result.hpp>
16
17 #include <coroutine>
18 #include <stop_token>
19 #include <utility>
20
21 namespace boost {
22 namespace capy {
23
24 /** An awaitable that completes immediately with a value.
25
26 This awaitable wraps a synchronous result so it can be used in
27 contexts that require an awaitable type. It never suspends -
28 `await_ready()` always returns `true`, so the coroutine machinery
29 is optimized away by the compiler.
30
31 Use this to adapt synchronous operations to satisfy async concepts
32 like @ref IoAwaitable without the overhead of a full coroutine frame.
33
34 @tparam T The result type to wrap.
35
36 @par Example
37 @code
38 // Wrap a sync operation as an awaitable
39 immediate<int> get_value()
40 {
41 return {42};
42 }
43
44 task<void> example()
45 {
46 int x = co_await get_value(); // No suspension, returns 42
47 }
48 @endcode
49
50 @par Satisfying WriteSink with sync operations
51 @code
52 struct my_sync_sink
53 {
54 template<ConstBufferSequence CB>
55 immediate<io_result<std::size_t>>
56 write(CB buffers)
57 {
58 auto n = process_sync(buffers);
59 return {{{}, n}};
60 }
61
62 immediate<io_result<>>
63 write_eof()
64 {
65 return {{}};
66 }
67 };
68 @endcode
69
70 @see ready, io_result
71 */
72 template<class T>
73 struct immediate
74 {
75 /** The wrapped value. */
76 T value_;
77
78 /** Always returns true - this awaitable never suspends. */
79 constexpr bool
80 21 await_ready() const noexcept
81 {
82 21 return true;
83 }
84
85 /** Never called since await_ready() returns true. */
86 constexpr void
87 await_suspend(std::coroutine_handle<>) const noexcept
88 {
89 }
90
91 /** IoAwaitable protocol overload.
92
93 This overload allows `immediate` to satisfy the @ref IoAwaitable
94 concept. Since the result is already available, the executor and
95 stop token are unused.
96
97 @param h The coroutine handle (unused).
98 @param ex The executor (unused).
99 @param token The stop token (unused).
100
101 @return `std::noop_coroutine()` to indicate no suspension.
102 */
103 std::coroutine_handle<>
104 1 await_suspend(
105 std::coroutine_handle<> h,
106 executor_ref ex,
107 std::stop_token token = {}) const noexcept
108 {
109 (void)h;
110 (void)ex;
111 (void)token;
112 1 return std::noop_coroutine();
113 }
114
115 /** Returns the wrapped value.
116
117 @return The stored value, moved if non-const.
118 */
119 constexpr T
120 24 await_resume() noexcept
121 {
122 24 return std::move(value_);
123 }
124
125 /** Returns the wrapped value (const overload). */
126 constexpr T const&
127 await_resume() const noexcept
128 {
129 return value_;
130 }
131 };
132
133 //----------------------------------------------------------
134
135 /** Create an immediate awaitable for a successful io_result.
136
137 This helper creates an @ref immediate wrapping an @ref io_result
138 with no error and the provided values.
139
140 @par Example
141 @code
142 immediate<io_result<std::size_t>>
143 write(const_buffer buf)
144 {
145 auto n = write_sync(buf);
146 return ready(n); // success with n bytes
147 }
148
149 immediate<io_result<>>
150 connect()
151 {
152 connect_sync();
153 return ready(); // void success
154 }
155 @endcode
156
157 @return An immediate awaitable containing a successful io_result.
158
159 @see immediate, io_result
160 */
161 inline
162 immediate<io_result<>>
163 3 ready() noexcept
164 {
165 3 return {{}};
166 }
167
168 /** Create an immediate awaitable for a successful io_result with one value.
169
170 @param t1 The result value.
171
172 @return An immediate awaitable containing `io_result<T1>{{}, t1}`.
173 */
174 template<class T1>
175 immediate<io_result<T1>>
176 4 ready(T1 t1)
177 {
178 4 return {{{}, std::move(t1)}};
179 }
180
181 /** Create an immediate awaitable for a successful io_result with two values.
182
183 @param t1 The first result value.
184 @param t2 The second result value.
185
186 @return An immediate awaitable containing `io_result<T1,T2>{{}, t1, t2}`.
187 */
188 template<class T1, class T2>
189 immediate<io_result<T1, T2>>
190 2 ready(T1 t1, T2 t2)
191 {
192 2 return {{{}, std::move(t1), std::move(t2)}};
193 }
194
195 /** Create an immediate awaitable for a successful io_result with three values.
196
197 @param t1 The first result value.
198 @param t2 The second result value.
199 @param t3 The third result value.
200
201 @return An immediate awaitable containing `io_result<T1,T2,T3>{{}, t1, t2, t3}`.
202 */
203 template<class T1, class T2, class T3>
204 immediate<io_result<T1, T2, T3>>
205 2 ready(T1 t1, T2 t2, T3 t3)
206 {
207 2 return {{{}, std::move(t1), std::move(t2), std::move(t3)}};
208 }
209
210 //----------------------------------------------------------
211
212 /** Create an immediate awaitable for a failed io_result.
213
214 This helper creates an @ref immediate wrapping an @ref io_result
215 with an error code.
216
217 @par Example
218 @code
219 immediate<io_result<std::size_t>>
220 write(const_buffer buf)
221 {
222 auto ec = write_sync(buf);
223 if(ec)
224 return ready(ec, std::size_t{0});
225 return ready(buffer_size(buf));
226 }
227 @endcode
228
229 @param ec The error code.
230
231 @return An immediate awaitable containing a failed io_result.
232
233 @see immediate, io_result
234 */
235 inline
236 immediate<io_result<>>
237 1 ready(std::error_code ec) noexcept
238 {
239 1 return {{ec}};
240 }
241
242 /** Create an immediate awaitable for an io_result with error and one value.
243
244 @param ec The error code.
245 @param t1 The result value.
246
247 @return An immediate awaitable containing `io_result<T1>{ec, t1}`.
248 */
249 template<class T1>
250 immediate<io_result<T1>>
251 2 ready(std::error_code ec, T1 t1)
252 {
253 2 return {{ec, std::move(t1)}};
254 }
255
256 /** Create an immediate awaitable for an io_result with error and two values.
257
258 @param ec The error code.
259 @param t1 The first result value.
260 @param t2 The second result value.
261
262 @return An immediate awaitable containing `io_result<T1,T2>{ec, t1, t2}`.
263 */
264 template<class T1, class T2>
265 immediate<io_result<T1, T2>>
266 1 ready(std::error_code ec, T1 t1, T2 t2)
267 {
268 1 return {{ec, std::move(t1), std::move(t2)}};
269 }
270
271 /** Create an immediate awaitable for an io_result with error and three values.
272
273 @param ec The error code.
274 @param t1 The first result value.
275 @param t2 The second result value.
276 @param t3 The third result value.
277
278 @return An immediate awaitable containing `io_result<T1,T2,T3>{ec, t1, t2, t3}`.
279 */
280 template<class T1, class T2, class T3>
281 immediate<io_result<T1, T2, T3>>
282 1 ready(std::error_code ec, T1 t1, T2 t2, T3 t3)
283 {
284 1 return {{ec, std::move(t1), std::move(t2), std::move(t3)}};
285 }
286
287 } // namespace capy
288 } // namespace boost
289
290 #endif
291