LCOV - code coverage report
Current view: top level - capy/ex - immediate.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 22 22
Test Date: 2026-02-12 14:50:59 Functions: 84.0 % 25 21

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

Generated by: LCOV version 2.3