LCOV - code coverage report
Current view: top level - boost/capy/ex - immediate.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 22 22
Test Date: 2026-01-30 23:43:15 Functions: 84.0 % 25 21

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot 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/executor_ref.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              :     /** Never called since await_ready() returns true. */
      86              :     constexpr void
      87              :     await_suspend(std::coroutine_handle<>) const noexcept
      88              :     {
      89              :     }
      90              : 
      91              :     /** IoAwaitable protocol overload.
      92              : 
      93              :         This overload allows `immediate` to satisfy the @ref IoAwaitable
      94              :         concept. Since the result is already available, the executor and
      95              :         stop token are unused.
      96              : 
      97              :         @param h The coroutine handle (unused).
      98              :         @param ex The executor (unused).
      99              :         @param token The stop token (unused).
     100              : 
     101              :         @return `std::noop_coroutine()` to indicate no suspension.
     102              :     */
     103              :     std::coroutine_handle<>
     104            1 :     await_suspend(
     105              :         std::coroutine_handle<> h,
     106              :         executor_ref ex,
     107              :         std::stop_token token = {}) const noexcept
     108              :     {
     109              :         (void)h;
     110              :         (void)ex;
     111              :         (void)token;
     112            1 :         return std::noop_coroutine();
     113              :     }
     114              : 
     115              :     /** Returns the wrapped value.
     116              : 
     117              :         @return The stored value, moved if non-const.
     118              :     */
     119              :     constexpr T
     120           24 :     await_resume() noexcept
     121              :     {
     122           24 :         return std::move(value_);
     123              :     }
     124              : 
     125              :     /** Returns the wrapped value (const overload). */
     126              :     constexpr T const&
     127              :     await_resume() const noexcept
     128              :     {
     129              :         return value_;
     130              :     }
     131              : };
     132              : 
     133              : //----------------------------------------------------------
     134              : 
     135              : /** Create an immediate awaitable for a successful io_result.
     136              : 
     137              :     This helper creates an @ref immediate wrapping an @ref io_result
     138              :     with no error and the provided values.
     139              : 
     140              :     @par Example
     141              :     @code
     142              :     immediate<io_result<std::size_t>>
     143              :     write(const_buffer buf)
     144              :     {
     145              :         auto n = write_sync(buf);
     146              :         return ready(n);  // success with n bytes
     147              :     }
     148              : 
     149              :     immediate<io_result<>>
     150              :     connect()
     151              :     {
     152              :         connect_sync();
     153              :         return ready();  // void success
     154              :     }
     155              :     @endcode
     156              : 
     157              :     @return An immediate awaitable containing a successful io_result.
     158              : 
     159              :     @see immediate, io_result
     160              : */
     161              : inline
     162              : immediate<io_result<>>
     163            3 : ready() noexcept
     164              : {
     165            3 :     return {{}};
     166              : }
     167              : 
     168              : /** Create an immediate awaitable for a successful io_result with one value.
     169              : 
     170              :     @param t1 The result value.
     171              : 
     172              :     @return An immediate awaitable containing `io_result<T1>{{}, t1}`.
     173              : */
     174              : template<class T1>
     175              : immediate<io_result<T1>>
     176            4 : ready(T1 t1)
     177              : {
     178            4 :     return {{{}, std::move(t1)}};
     179              : }
     180              : 
     181              : /** Create an immediate awaitable for a successful io_result with two values.
     182              : 
     183              :     @param t1 The first result value.
     184              :     @param t2 The second result value.
     185              : 
     186              :     @return An immediate awaitable containing `io_result<T1,T2>{{}, t1, t2}`.
     187              : */
     188              : template<class T1, class T2>
     189              : immediate<io_result<T1, T2>>
     190            2 : ready(T1 t1, T2 t2)
     191              : {
     192            2 :     return {{{}, std::move(t1), std::move(t2)}};
     193              : }
     194              : 
     195              : /** Create an immediate awaitable for a successful io_result with three values.
     196              : 
     197              :     @param t1 The first result value.
     198              :     @param t2 The second result value.
     199              :     @param t3 The third result value.
     200              : 
     201              :     @return An immediate awaitable containing `io_result<T1,T2,T3>{{}, t1, t2, t3}`.
     202              : */
     203              : template<class T1, class T2, class T3>
     204              : immediate<io_result<T1, T2, T3>>
     205            2 : ready(T1 t1, T2 t2, T3 t3)
     206              : {
     207            2 :     return {{{}, std::move(t1), std::move(t2), std::move(t3)}};
     208              : }
     209              : 
     210              : //----------------------------------------------------------
     211              : 
     212              : /** Create an immediate awaitable for a failed io_result.
     213              : 
     214              :     This helper creates an @ref immediate wrapping an @ref io_result
     215              :     with an error code.
     216              : 
     217              :     @par Example
     218              :     @code
     219              :     immediate<io_result<std::size_t>>
     220              :     write(const_buffer buf)
     221              :     {
     222              :         auto ec = write_sync(buf);
     223              :         if(ec)
     224              :             return ready(ec, std::size_t{0});
     225              :         return ready(buffer_size(buf));
     226              :     }
     227              :     @endcode
     228              : 
     229              :     @param ec The error code.
     230              : 
     231              :     @return An immediate awaitable containing a failed io_result.
     232              : 
     233              :     @see immediate, io_result
     234              : */
     235              : inline
     236              : immediate<io_result<>>
     237            1 : ready(std::error_code ec) noexcept
     238              : {
     239            1 :     return {{ec}};
     240              : }
     241              : 
     242              : /** Create an immediate awaitable for an io_result with error and one value.
     243              : 
     244              :     @param ec The error code.
     245              :     @param t1 The result value.
     246              : 
     247              :     @return An immediate awaitable containing `io_result<T1>{ec, t1}`.
     248              : */
     249              : template<class T1>
     250              : immediate<io_result<T1>>
     251            2 : ready(std::error_code ec, T1 t1)
     252              : {
     253            2 :     return {{ec, std::move(t1)}};
     254              : }
     255              : 
     256              : /** Create an immediate awaitable for an io_result with error and two values.
     257              : 
     258              :     @param ec The error code.
     259              :     @param t1 The first result value.
     260              :     @param t2 The second result value.
     261              : 
     262              :     @return An immediate awaitable containing `io_result<T1,T2>{ec, t1, t2}`.
     263              : */
     264              : template<class T1, class T2>
     265              : immediate<io_result<T1, T2>>
     266            1 : ready(std::error_code ec, T1 t1, T2 t2)
     267              : {
     268            1 :     return {{ec, std::move(t1), std::move(t2)}};
     269              : }
     270              : 
     271              : /** Create an immediate awaitable for an io_result with error and three values.
     272              : 
     273              :     @param ec The error code.
     274              :     @param t1 The first result value.
     275              :     @param t2 The second result value.
     276              :     @param t3 The third result value.
     277              : 
     278              :     @return An immediate awaitable containing `io_result<T1,T2,T3>{ec, t1, t2, t3}`.
     279              : */
     280              : template<class T1, class T2, class T3>
     281              : immediate<io_result<T1, T2, T3>>
     282            1 : ready(std::error_code ec, T1 t1, T2 t2, T3 t3)
     283              : {
     284            1 :     return {{ec, std::move(t1), std::move(t2), std::move(t3)}};
     285              : }
     286              : 
     287              : } // namespace capy
     288              : } // namespace boost
     289              : 
     290              : #endif
        

Generated by: LCOV version 2.3