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