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   @par !example example_1 38   @par !example example_1
39   39  
40   40  
41   @par Building synchronous I/O operations 41   @par Building synchronous I/O operations
42   @par !example example_2 42   @par !example example_2
43   43  
44   44  
45   @see ready, io_result 45   @see ready, io_result
46   */ 46   */
47   template<class T> 47   template<class T>
48   struct immediate 48   struct immediate
49   { 49   {
50   /** The wrapped value. */ 50   /** The wrapped value. */
51   T value_; 51   T value_;
52   52  
53   /** Always returns true - this awaitable never suspends. 53   /** Always returns true - this awaitable never suspends.
54   54  
55   @return Always `true`, so the awaiting coroutine does not suspend 55   @return Always `true`, so the awaiting coroutine does not suspend
56   and `await_suspend` is never called. 56   and `await_suspend` is never called.
57   */ 57   */
58   constexpr bool 58   constexpr bool
HITCBC 59   21 await_ready() const noexcept 59   21 await_ready() const noexcept
60   { 60   {
HITCBC 61   21 return true; 61   21 return true;
62   } 62   }
63   63  
64   /** IoAwaitable protocol overload. 64   /** IoAwaitable protocol overload.
65   65  
66   This overload allows `immediate` to satisfy the @ref IoAwaitable 66   This overload allows `immediate` to satisfy the @ref IoAwaitable
67   concept. Since the result is already available, the environment 67   concept. Since the result is already available, the environment
68   is unused. 68   is unused.
69   69  
70   @param h The coroutine handle (unused). 70   @param h The coroutine handle (unused).
71   @param env The execution environment (unused). 71   @param env The execution environment (unused).
72   72  
73   @return `std::noop_coroutine()` to indicate no suspension. 73   @return `std::noop_coroutine()` to indicate no suspension.
74   */ 74   */
75   std::coroutine_handle<> 75   std::coroutine_handle<>
HITCBC 76   1 await_suspend( 76   1 await_suspend(
77   std::coroutine_handle<> h, 77   std::coroutine_handle<> h,
78   io_env const* env) const noexcept 78   io_env const* env) const noexcept
79   { 79   {
80   (void)h; 80   (void)h;
81   (void)env; 81   (void)env;
HITCBC 82   1 return std::noop_coroutine(); 82   1 return std::noop_coroutine();
83   } 83   }
84   84  
85   /** Returns the wrapped value. 85   /** Returns the wrapped value.
86   86  
87   @return The stored value, moved if non-const. 87   @return The stored value, moved if non-const.
88   */ 88   */
89   [[nodiscard]] constexpr T 89   [[nodiscard]] constexpr T
HITCBC 90   24 await_resume() noexcept 90   24 await_resume() noexcept
91   { 91   {
HITCBC 92   24 return std::move(value_); 92   24 return std::move(value_);
93   } 93   }
94   94  
95   /** Returns the wrapped value (const overload). 95   /** Returns the wrapped value (const overload).
96   96  
97   @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
98   reference is valid only while the `immediate` is alive. 98   reference is valid only while the `immediate` is alive.
99   */ 99   */
100   [[nodiscard]] constexpr T const& 100   [[nodiscard]] constexpr T const&
101   await_resume() const noexcept 101   await_resume() const noexcept
102   { 102   {
103   return value_; 103   return value_;
104   } 104   }
105   }; 105   };
106   106  
107   /** Create an immediate awaitable for a successful io_result. 107   /** Create an immediate awaitable for a successful io_result.
108   108  
109   This helper creates an @ref immediate wrapping an @ref io_result 109   This helper creates an @ref immediate wrapping an @ref io_result
110   with no error and the provided values. 110   with no error and the provided values.
111   111  
112   @par Example 112   @par Example
113   @par !example example_1 113   @par !example example_1
114   114  
115   115  
116   @return An immediate awaitable containing a successful io_result. 116   @return An immediate awaitable containing a successful io_result.
117   117  
118   @see immediate, io_result 118   @see immediate, io_result
119   */ 119   */
120   inline 120   inline
121   immediate<io_result<>> 121   immediate<io_result<>>
HITCBC 122   3 ready() noexcept 122   3 ready() noexcept
123   { 123   {
HITCBC 124   3 return {{}}; 124   3 return {{}};
125   } 125   }
126   126  
127   /** 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.
128   128  
129   @param t1 The result value. 129   @param t1 The result value.
130   130  
131   @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}`.
132   */ 132   */
133   template<class T1> 133   template<class T1>
134   immediate<io_result<T1>> 134   immediate<io_result<T1>>
HITCBC 135   4 ready(T1 t1) 135   4 ready(T1 t1)
136   { 136   {
HITCBC 137   4 return {{std::error_code(), std::move(t1)}}; 137   4 return {{std::error_code(), std::move(t1)}};
138   } 138   }
139   139  
140   /** 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.
141   141  
142   @param t1 The first result value. 142   @param t1 The first result value.
143   @param t2 The second result value. 143   @param t2 The second result value.
144   144  
145   @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}`.
146   */ 146   */
147   template<class T1, class T2> 147   template<class T1, class T2>
148   immediate<io_result<T1, T2>> 148   immediate<io_result<T1, T2>>
HITCBC 149   2 ready(T1 t1, T2 t2) 149   2 ready(T1 t1, T2 t2)
150   { 150   {
HITCBC 151   2 return {{std::error_code(), std::move(t1), std::move(t2)}}; 151   2 return {{std::error_code(), std::move(t1), std::move(t2)}};
152   } 152   }
153   153  
154   /** 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.
155   155  
156   @param t1 The first result value. 156   @param t1 The first result value.
157   @param t2 The second result value. 157   @param t2 The second result value.
158   @param t3 The third result value. 158   @param t3 The third result value.
159   159  
160   @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}`.
161   */ 161   */
162   template<class T1, class T2, class T3> 162   template<class T1, class T2, class T3>
163   immediate<io_result<T1, T2, T3>> 163   immediate<io_result<T1, T2, T3>>
HITCBC 164   2 ready(T1 t1, T2 t2, T3 t3) 164   2 ready(T1 t1, T2 t2, T3 t3)
165   { 165   {
HITCBC 166   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)}};
167   } 167   }
168   168  
169   /** Create an immediate awaitable for a failed io_result. 169   /** Create an immediate awaitable for a failed io_result.
170   170  
171   This helper creates an @ref immediate wrapping an @ref io_result 171   This helper creates an @ref immediate wrapping an @ref io_result
172   with an error code. 172   with an error code.
173   173  
174   @par Example 174   @par Example
175   @par !example example_2 175   @par !example example_2
176   176  
177   177  
178   @param ec The error code. 178   @param ec The error code.
179   179  
180   @return An immediate awaitable containing a failed io_result. 180   @return An immediate awaitable containing a failed io_result.
181   181  
182   @see immediate, io_result 182   @see immediate, io_result
183   */ 183   */
184   inline 184   inline
185   immediate<io_result<>> 185   immediate<io_result<>>
HITCBC 186   1 ready(std::error_code ec) noexcept 186   1 ready(std::error_code ec) noexcept
187   { 187   {
HITCBC 188   1 return {{ec}}; 188   1 return {{ec}};
189   } 189   }
190   190  
191   /** 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.
192   192  
193   @param ec The error code. 193   @param ec The error code.
194   @param t1 The result value. 194   @param t1 The result value.
195   195  
196   @return An immediate awaitable containing `io_result<T1>{ec, t1}`. 196   @return An immediate awaitable containing `io_result<T1>{ec, t1}`.
197   */ 197   */
198   template<class T1> 198   template<class T1>
199   immediate<io_result<T1>> 199   immediate<io_result<T1>>
HITCBC 200   2 ready(std::error_code ec, T1 t1) 200   2 ready(std::error_code ec, T1 t1)
201   { 201   {
HITCBC 202   2 return {{ec, std::move(t1)}}; 202   2 return {{ec, std::move(t1)}};
203   } 203   }
204   204  
205   /** 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.
206   206  
207   @param ec The error code. 207   @param ec The error code.
208   @param t1 The first result value. 208   @param t1 The first result value.
209   @param t2 The second result value. 209   @param t2 The second result value.
210   210  
211   @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}`.
212   */ 212   */
213   template<class T1, class T2> 213   template<class T1, class T2>
214   immediate<io_result<T1, T2>> 214   immediate<io_result<T1, T2>>
HITCBC 215   1 ready(std::error_code ec, T1 t1, T2 t2) 215   1 ready(std::error_code ec, T1 t1, T2 t2)
216   { 216   {
HITCBC 217   1 return {{ec, std::move(t1), std::move(t2)}}; 217   1 return {{ec, std::move(t1), std::move(t2)}};
218   } 218   }
219   219  
220   /** 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.
221   221  
222   @param ec The error code. 222   @param ec The error code.
223   @param t1 The first result value. 223   @param t1 The first result value.
224   @param t2 The second result value. 224   @param t2 The second result value.
225   @param t3 The third result value. 225   @param t3 The third result value.
226   226  
227   @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}`.
228   */ 228   */
229   template<class T1, class T2, class T3> 229   template<class T1, class T2, class T3>
230   immediate<io_result<T1, T2, T3>> 230   immediate<io_result<T1, T2, T3>>
HITCBC 231   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)
232   { 232   {
HITCBC 233   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)}};
234   } 234   }
235   235  
236   } // namespace capy 236   } // namespace capy
237   } // namespace boost 237   } // namespace boost
238   238  
239   #endif 239   #endif