TLA Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2026 Michael Vandeberg
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/capy
9 : //
10 :
11 : #ifndef BOOST_CAPY_EX_IMMEDIATE_HPP
12 : #define BOOST_CAPY_EX_IMMEDIATE_HPP
13 :
14 : #include <boost/capy/detail/config.hpp>
15 : #include <boost/capy/ex/io_env.hpp>
16 : #include <boost/capy/io_result.hpp>
17 :
18 : #include <coroutine>
19 : #include <stop_token>
20 : #include <utility>
21 :
22 : namespace boost {
23 : namespace capy {
24 :
25 : /** An awaitable that completes immediately with a value.
26 :
27 : This awaitable wraps a synchronous result so it can be used in
28 : contexts that require an awaitable type. It never suspends -
29 : `await_ready()` always returns `true`, so the coroutine machinery
30 : is optimized away by the compiler.
31 :
32 : Use this to adapt synchronous operations to satisfy async concepts
33 : like @ref IoAwaitable without the overhead of a full coroutine frame.
34 :
35 : @tparam T The result type to wrap.
36 :
37 : @par Example
38 : @par !example example_1
39 :
40 :
41 : @par Building synchronous I/O operations
42 : @par !example example_2
43 :
44 :
45 : @see ready, io_result
46 : */
47 : template<class T>
48 : struct immediate
49 : {
50 : /** The wrapped value. */
51 : T value_;
52 :
53 : /** Always returns true - this awaitable never suspends.
54 :
55 : @return Always `true`, so the awaiting coroutine does not suspend
56 : and `await_suspend` is never called.
57 : */
58 : constexpr bool
59 HIT 21 : await_ready() const noexcept
60 : {
61 21 : return true;
62 : }
63 :
64 : /** IoAwaitable protocol overload.
65 :
66 : This overload allows `immediate` to satisfy the @ref IoAwaitable
67 : concept. Since the result is already available, the environment
68 : is unused.
69 :
70 : @param h The coroutine handle (unused).
71 : @param env The execution environment (unused).
72 :
73 : @return `std::noop_coroutine()` to indicate no suspension.
74 : */
75 : std::coroutine_handle<>
76 1 : await_suspend(
77 : std::coroutine_handle<> h,
78 : io_env const* env) const noexcept
79 : {
80 : (void)h;
81 : (void)env;
82 1 : return std::noop_coroutine();
83 : }
84 :
85 : /** Returns the wrapped value.
86 :
87 : @return The stored value, moved if non-const.
88 : */
89 : [[nodiscard]] constexpr T
90 24 : await_resume() noexcept
91 : {
92 24 : return std::move(value_);
93 : }
94 :
95 : /** Returns the wrapped value (const overload).
96 :
97 : @return A reference to the stored value. Nothing is moved, so the
98 : reference is valid only while the `immediate` is alive.
99 : */
100 : [[nodiscard]] constexpr T const&
101 : await_resume() const noexcept
102 : {
103 : return value_;
104 : }
105 : };
106 :
107 : /** Create an immediate awaitable for a successful io_result.
108 :
109 : This helper creates an @ref immediate wrapping an @ref io_result
110 : with no error and the provided values.
111 :
112 : @par Example
113 : @par !example example_1
114 :
115 :
116 : @return An immediate awaitable containing a successful io_result.
117 :
118 : @see immediate, io_result
119 : */
120 : inline
121 : immediate<io_result<>>
122 3 : ready() noexcept
123 : {
124 3 : return {{}};
125 : }
126 :
127 : /** Create an immediate awaitable for a successful io_result with one value.
128 :
129 : @param t1 The result value.
130 :
131 : @return An immediate awaitable containing `io_result<T1>{std::error_code(), t1}`.
132 : */
133 : template<class T1>
134 : immediate<io_result<T1>>
135 4 : ready(T1 t1)
136 : {
137 4 : return {{std::error_code(), std::move(t1)}};
138 : }
139 :
140 : /** Create an immediate awaitable for a successful io_result with two values.
141 :
142 : @param t1 The first result value.
143 : @param t2 The second result value.
144 :
145 : @return An immediate awaitable containing `io_result<T1,T2>{std::error_code(), t1, t2}`.
146 : */
147 : template<class T1, class T2>
148 : immediate<io_result<T1, T2>>
149 2 : ready(T1 t1, T2 t2)
150 : {
151 2 : return {{std::error_code(), std::move(t1), std::move(t2)}};
152 : }
153 :
154 : /** Create an immediate awaitable for a successful io_result with three values.
155 :
156 : @param t1 The first result value.
157 : @param t2 The second result value.
158 : @param t3 The third result value.
159 :
160 : @return An immediate awaitable containing `io_result<T1,T2,T3>{std::error_code(), t1, t2, t3}`.
161 : */
162 : template<class T1, class T2, class T3>
163 : immediate<io_result<T1, T2, T3>>
164 2 : ready(T1 t1, T2 t2, T3 t3)
165 : {
166 2 : return {{std::error_code(), std::move(t1), std::move(t2), std::move(t3)}};
167 : }
168 :
169 : /** Create an immediate awaitable for a failed io_result.
170 :
171 : This helper creates an @ref immediate wrapping an @ref io_result
172 : with an error code.
173 :
174 : @par Example
175 : @par !example example_2
176 :
177 :
178 : @param ec The error code.
179 :
180 : @return An immediate awaitable containing a failed io_result.
181 :
182 : @see immediate, io_result
183 : */
184 : inline
185 : immediate<io_result<>>
186 1 : ready(std::error_code ec) noexcept
187 : {
188 1 : return {{ec}};
189 : }
190 :
191 : /** Create an immediate awaitable for an io_result with error and one value.
192 :
193 : @param ec The error code.
194 : @param t1 The result value.
195 :
196 : @return An immediate awaitable containing `io_result<T1>{ec, t1}`.
197 : */
198 : template<class T1>
199 : immediate<io_result<T1>>
200 2 : ready(std::error_code ec, T1 t1)
201 : {
202 2 : return {{ec, std::move(t1)}};
203 : }
204 :
205 : /** Create an immediate awaitable for an io_result with error and two values.
206 :
207 : @param ec The error code.
208 : @param t1 The first result value.
209 : @param t2 The second result value.
210 :
211 : @return An immediate awaitable containing `io_result<T1,T2>{ec, t1, t2}`.
212 : */
213 : template<class T1, class T2>
214 : immediate<io_result<T1, T2>>
215 1 : ready(std::error_code ec, T1 t1, T2 t2)
216 : {
217 1 : return {{ec, std::move(t1), std::move(t2)}};
218 : }
219 :
220 : /** Create an immediate awaitable for an io_result with error and three values.
221 :
222 : @param ec The error code.
223 : @param t1 The first result value.
224 : @param t2 The second result value.
225 : @param t3 The third result value.
226 :
227 : @return An immediate awaitable containing `io_result<T1,T2,T3>{ec, t1, t2, t3}`.
228 : */
229 : template<class T1, class T2, class T3>
230 : immediate<io_result<T1, T2, T3>>
231 1 : ready(std::error_code ec, T1 t1, T2 t2, T3 t3)
232 : {
233 1 : return {{ec, std::move(t1), std::move(t2), std::move(t3)}};
234 : }
235 :
236 : } // namespace capy
237 : } // namespace boost
238 :
239 : #endif
|