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.falco@gmail.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/io_env.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 /** IoAwaitable protocol overload.
86
87 This overload allows `immediate` to satisfy the @ref IoAwaitable
88 concept. Since the result is already available, the environment
89 is unused.
90
91 @param h The coroutine handle (unused).
92 @param env The execution environment (unused).
93
94 @return `std::noop_coroutine()` to indicate no suspension.
95 */
96 std::coroutine_handle<>
97 1 await_suspend(
98 std::coroutine_handle<> h,
99 io_env const* env) const noexcept
100 {
101 (void)h;
102 (void)env;
103 1 return std::noop_coroutine();
104 }
105
106 /** Returns the wrapped value.
107
108 @return The stored value, moved if non-const.
109 */
110 constexpr T
111 24 await_resume() noexcept
112 {
113 24 return std::move(value_);
114 }
115
116 /** Returns the wrapped value (const overload). */
117 constexpr T const&
118 await_resume() const noexcept
119 {
120 return value_;
121 }
122 };
123
124 //----------------------------------------------------------
125
126 /** Create an immediate awaitable for a successful io_result.
127
128 This helper creates an @ref immediate wrapping an @ref io_result
129 with no error and the provided values.
130
131 @par Example
132 @code
133 immediate<io_result<std::size_t>>
134 write(const_buffer buf)
135 {
136 auto n = write_sync(buf);
137 return ready(n); // success with n bytes
138 }
139
140 immediate<io_result<>>
141 connect()
142 {
143 connect_sync();
144 return ready(); // void success
145 }
146 @endcode
147
148 @return An immediate awaitable containing a successful io_result.
149
150 @see immediate, io_result
151 */
152 inline
153 immediate<io_result<>>
154 3 ready() noexcept
155 {
156 3 return {{}};
157 }
158
159 /** Create an immediate awaitable for a successful io_result with one value.
160
161 @param t1 The result value.
162
163 @return An immediate awaitable containing `io_result<T1>{{}, t1}`.
164 */
165 template<class T1>
166 immediate<io_result<T1>>
167 4 ready(T1 t1)
168 {
169 4 return {{{}, std::move(t1)}};
170 }
171
172 /** Create an immediate awaitable for a successful io_result with two values.
173
174 @param t1 The first result value.
175 @param t2 The second result value.
176
177 @return An immediate awaitable containing `io_result<T1,T2>{{}, t1, t2}`.
178 */
179 template<class T1, class T2>
180 immediate<io_result<T1, T2>>
181 2 ready(T1 t1, T2 t2)
182 {
183 2 return {{{}, std::move(t1), std::move(t2)}};
184 }
185
186 /** Create an immediate awaitable for a successful io_result with three values.
187
188 @param t1 The first result value.
189 @param t2 The second result value.
190 @param t3 The third result value.
191
192 @return An immediate awaitable containing `io_result<T1,T2,T3>{{}, t1, t2, t3}`.
193 */
194 template<class T1, class T2, class T3>
195 immediate<io_result<T1, T2, T3>>
196 2 ready(T1 t1, T2 t2, T3 t3)
197 {
198 2 return {{{}, std::move(t1), std::move(t2), std::move(t3)}};
199 }
200
201 //----------------------------------------------------------
202
203 /** Create an immediate awaitable for a failed io_result.
204
205 This helper creates an @ref immediate wrapping an @ref io_result
206 with an error code.
207
208 @par Example
209 @code
210 immediate<io_result<std::size_t>>
211 write(const_buffer buf)
212 {
213 auto ec = write_sync(buf);
214 if(ec)
215 return ready(ec, std::size_t{0});
216 return ready(buffer_size(buf));
217 }
218 @endcode
219
220 @param ec The error code.
221
222 @return An immediate awaitable containing a failed io_result.
223
224 @see immediate, io_result
225 */
226 inline
227 immediate<io_result<>>
228 1 ready(std::error_code ec) noexcept
229 {
230 1 return {{ec}};
231 }
232
233 /** Create an immediate awaitable for an io_result with error and one value.
234
235 @param ec The error code.
236 @param t1 The result value.
237
238 @return An immediate awaitable containing `io_result<T1>{ec, t1}`.
239 */
240 template<class T1>
241 immediate<io_result<T1>>
242 2 ready(std::error_code ec, T1 t1)
243 {
244 2 return {{ec, std::move(t1)}};
245 }
246
247 /** Create an immediate awaitable for an io_result with error and two values.
248
249 @param ec The error code.
250 @param t1 The first result value.
251 @param t2 The second result value.
252
253 @return An immediate awaitable containing `io_result<T1,T2>{ec, t1, t2}`.
254 */
255 template<class T1, class T2>
256 immediate<io_result<T1, T2>>
257 1 ready(std::error_code ec, T1 t1, T2 t2)
258 {
259 1 return {{ec, std::move(t1), std::move(t2)}};
260 }
261
262 /** Create an immediate awaitable for an io_result with error and three values.
263
264 @param ec The error code.
265 @param t1 The first result value.
266 @param t2 The second result value.
267 @param t3 The third result value.
268
269 @return An immediate awaitable containing `io_result<T1,T2,T3>{ec, t1, t2, t3}`.
270 */
271 template<class T1, class T2, class T3>
272 immediate<io_result<T1, T2, T3>>
273 1 ready(std::error_code ec, T1 t1, T2 t2, T3 t3)
274 {
275 1 return {{ec, std::move(t1), std::move(t2), std::move(t3)}};
276 }
277
278 } // namespace capy
279 } // namespace boost
280
281 #endif
282