include/boost/capy/ex/immediate.hpp

100.0% Lines (22/22) 84.0% Functions (21/25)
Line TLA 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 21x await_ready() const noexcept
81 {
82 21x 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 1x await_suspend(
98 std::coroutine_handle<> h,
99 io_env const* env) const noexcept
100 {
101 (void)h;
102 (void)env;
103 1x 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 24x await_resume() noexcept
112 {
113 24x 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 /** Create an immediate awaitable for a successful io_result.
125
126 This helper creates an @ref immediate wrapping an @ref io_result
127 with no error and the provided values.
128
129 @par Example
130 @code
131 immediate<io_result<std::size_t>>
132 write(const_buffer buf)
133 {
134 auto n = write_sync(buf);
135 return ready(n); // success with n bytes
136 }
137
138 immediate<io_result<>>
139 connect()
140 {
141 connect_sync();
142 return ready(); // void success
143 }
144 @endcode
145
146 @return An immediate awaitable containing a successful io_result.
147
148 @see immediate, io_result
149 */
150 inline
151 immediate<io_result<>>
152 3x ready() noexcept
153 {
154 3x return {{}};
155 }
156
157 /** Create an immediate awaitable for a successful io_result with one value.
158
159 @param t1 The result value.
160
161 @return An immediate awaitable containing `io_result<T1>{{}, t1}`.
162 */
163 template<class T1>
164 immediate<io_result<T1>>
165 4x ready(T1 t1)
166 {
167 4x return {{{}, std::move(t1)}};
168 }
169
170 /** Create an immediate awaitable for a successful io_result with two values.
171
172 @param t1 The first result value.
173 @param t2 The second result value.
174
175 @return An immediate awaitable containing `io_result<T1,T2>{{}, t1, t2}`.
176 */
177 template<class T1, class T2>
178 immediate<io_result<T1, T2>>
179 2x ready(T1 t1, T2 t2)
180 {
181 2x return {{{}, std::move(t1), std::move(t2)}};
182 }
183
184 /** Create an immediate awaitable for a successful io_result with three values.
185
186 @param t1 The first result value.
187 @param t2 The second result value.
188 @param t3 The third result value.
189
190 @return An immediate awaitable containing `io_result<T1,T2,T3>{{}, t1, t2, t3}`.
191 */
192 template<class T1, class T2, class T3>
193 immediate<io_result<T1, T2, T3>>
194 2x ready(T1 t1, T2 t2, T3 t3)
195 {
196 2x return {{{}, std::move(t1), std::move(t2), std::move(t3)}};
197 }
198
199 /** Create an immediate awaitable for a failed io_result.
200
201 This helper creates an @ref immediate wrapping an @ref io_result
202 with an error code.
203
204 @par Example
205 @code
206 immediate<io_result<std::size_t>>
207 write(const_buffer buf)
208 {
209 auto ec = write_sync(buf);
210 if(ec)
211 return ready(ec, std::size_t{0});
212 return ready(buffer_size(buf));
213 }
214 @endcode
215
216 @param ec The error code.
217
218 @return An immediate awaitable containing a failed io_result.
219
220 @see immediate, io_result
221 */
222 inline
223 immediate<io_result<>>
224 1x ready(std::error_code ec) noexcept
225 {
226 1x return {{ec}};
227 }
228
229 /** Create an immediate awaitable for an io_result with error and one value.
230
231 @param ec The error code.
232 @param t1 The result value.
233
234 @return An immediate awaitable containing `io_result<T1>{ec, t1}`.
235 */
236 template<class T1>
237 immediate<io_result<T1>>
238 2x ready(std::error_code ec, T1 t1)
239 {
240 2x return {{ec, std::move(t1)}};
241 }
242
243 /** Create an immediate awaitable for an io_result with error and two values.
244
245 @param ec The error code.
246 @param t1 The first result value.
247 @param t2 The second result value.
248
249 @return An immediate awaitable containing `io_result<T1,T2>{ec, t1, t2}`.
250 */
251 template<class T1, class T2>
252 immediate<io_result<T1, T2>>
253 1x ready(std::error_code ec, T1 t1, T2 t2)
254 {
255 1x return {{ec, std::move(t1), std::move(t2)}};
256 }
257
258 /** Create an immediate awaitable for an io_result with error and three values.
259
260 @param ec The error code.
261 @param t1 The first result value.
262 @param t2 The second result value.
263 @param t3 The third result value.
264
265 @return An immediate awaitable containing `io_result<T1,T2,T3>{ec, t1, t2, t3}`.
266 */
267 template<class T1, class T2, class T3>
268 immediate<io_result<T1, T2, T3>>
269 1x ready(std::error_code ec, T1 t1, T2 t2, T3 t3)
270 {
271 1x return {{ec, std::move(t1), std::move(t2), std::move(t3)}};
272 }
273
274 } // namespace capy
275 } // namespace boost
276
277 #endif
278