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