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