100.00% Lines (33/33) 100.00% Functions (12/12)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2026 Michael Vandeberg 2   // Copyright (c) 2026 Michael Vandeberg
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/corosio 7   // Official repository: https://github.com/cppalliance/corosio
8   // 8   //
9   9  
10   #ifndef BOOST_COROSIO_DETAIL_OP_BASE_HPP 10   #ifndef BOOST_COROSIO_DETAIL_OP_BASE_HPP
11   #define BOOST_COROSIO_DETAIL_OP_BASE_HPP 11   #define BOOST_COROSIO_DETAIL_OP_BASE_HPP
12   12  
13   #include <boost/capy/io_result.hpp> 13   #include <boost/capy/io_result.hpp>
14   #include <boost/capy/ex/executor_ref.hpp> 14   #include <boost/capy/ex/executor_ref.hpp>
15   #include <boost/capy/ex/io_env.hpp> 15   #include <boost/capy/ex/io_env.hpp>
16   16  
17   #include <coroutine> 17   #include <coroutine>
18   #include <cstddef> 18   #include <cstddef>
19   #include <stop_token> 19   #include <stop_token>
20   #include <system_error> 20   #include <system_error>
21   21  
22   namespace boost::corosio::detail { 22   namespace boost::corosio::detail {
23   23  
24   /* CRTP base for awaitables that return io_result<std::size_t>. 24   /* CRTP base for awaitables that return io_result<std::size_t>.
25   25  
26   Derived classes must provide: 26   Derived classes must provide:
27   27  
28   std::coroutine_handle<> dispatch( 28   std::coroutine_handle<> dispatch(
29   std::coroutine_handle<> h, 29   std::coroutine_handle<> h,
30   capy::executor_ref ex) const; 30   capy::executor_ref ex) const;
31   31  
32   which forwards to the backend implementation method, passing 32   which forwards to the backend implementation method, passing
33   token_, &ec_, and &bytes_ as the cancellation/output parameters. 33   token_, &ec_, and &bytes_ as the cancellation/output parameters.
34   */ 34   */
35   template<class Derived> 35   template<class Derived>
36   class bytes_op_base 36   class bytes_op_base
37   { 37   {
38   friend Derived; 38   friend Derived;
HITCBC 39   454369 bytes_op_base() = default; 39   474508 bytes_op_base() = default;
40   40  
41   public: 41   public:
42   std::stop_token token_; 42   std::stop_token token_;
43   mutable std::error_code ec_; 43   mutable std::error_code ec_;
44   mutable std::size_t bytes_ = 0; 44   mutable std::size_t bytes_ = 0;
45   45  
HITCBC 46   454369 bool await_ready() const noexcept 46   474508 bool await_ready() const noexcept
47   { 47   {
48   // A pre-set ec_ means the initiator failed before dispatch 48   // A pre-set ec_ means the initiator failed before dispatch
49   // (e.g. a closed object); complete immediately with that error. 49   // (e.g. a closed object); complete immediately with that error.
HITCBC 50   454369 return static_cast<bool>(ec_) || token_.stop_requested(); 50   474508 return static_cast<bool>(ec_) || token_.stop_requested();
51   } 51   }
52   52  
HITCBC 53   454336 [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept 53   474475 [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
54   { 54   {
HITCBC 55   454336 if (token_.stop_requested()) 55   474475 if (token_.stop_requested())
HITCBC 56   243 return {make_error_code(std::errc::operation_canceled), 0}; 56   243 return {make_error_code(std::errc::operation_canceled), 0};
HITCBC 57   454093 return {ec_, bytes_}; 57   474232 return {ec_, bytes_};
58   } 58   }
59   59  
HITCBC 60   454353 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env) 60   474492 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
61   -> std::coroutine_handle<> 61   -> std::coroutine_handle<>
62   { 62   {
HITCBC 63   454353 token_ = env->stop_token; 63   474492 token_ = env->stop_token;
HITCBC 64   454353 return static_cast<Derived const*>(this)->dispatch( 64   474492 return static_cast<Derived const*>(this)->dispatch(
HITCBC 65   454353 h, env->executor); 65   474492 h, env->executor);
66   } 66   }
67   }; 67   };
68   68  
  69 + /* CRTP base for awaitables that return io_result<Value> for a
  70 + moved-out result object (e.g. the resolver's result lists).
  71 +
  72 + Derived classes must provide:
  73 +
  74 + std::coroutine_handle<> dispatch(
  75 + std::coroutine_handle<> h,
  76 + capy::executor_ref ex) const;
  77 +
  78 + which forwards to the backend implementation method, passing
  79 + token_, &ec_, and &value_ as the cancellation/output parameters.
  80 + */
  81 + template<class Derived, class Value>
  82 + class value_op_base
  83 + {
  84 + friend Derived;
HITGNC   85 + 50 value_op_base() = default;
  86 +
  87 + public:
  88 + std::stop_token token_;
  89 + mutable std::error_code ec_;
  90 + mutable Value value_{};
  91 +
HITGNC   92 + 50 bool await_ready() const noexcept
  93 + {
  94 + // A pre-set ec_ means the initiator failed before dispatch;
  95 + // complete immediately with that error.
HITGNC   96 + 50 return static_cast<bool>(ec_) || token_.stop_requested();
  97 + }
  98 +
HITGNC   99 + 48 [[nodiscard]] capy::io_result<Value> await_resume() const noexcept
  100 + {
HITGNC   101 + 48 if (token_.stop_requested())
HITGNC   102 + 2 return {make_error_code(std::errc::operation_canceled), {}};
HITGNC   103 + 46 return {ec_, std::move(value_)};
  104 + }
  105 +
HITGNC   106 + 50 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
  107 + -> std::coroutine_handle<>
  108 + {
HITGNC   109 + 50 token_ = env->stop_token;
HITGNC   110 + 50 return static_cast<Derived const*>(this)->dispatch(
HITGNC   111 + 50 h, env->executor);
  112 + }
  113 + };
  114 +
69   /* CRTP base for awaitables that return io_result<>. 115   /* CRTP base for awaitables that return io_result<>.
70   116  
71   Derived classes must provide: 117   Derived classes must provide:
72   118  
73   std::coroutine_handle<> dispatch( 119   std::coroutine_handle<> dispatch(
74   std::coroutine_handle<> h, 120   std::coroutine_handle<> h,
75   capy::executor_ref ex) const; 121   capy::executor_ref ex) const;
76   122  
77   which forwards to the backend implementation method, passing 123   which forwards to the backend implementation method, passing
78   token_ and &ec_ as the cancellation/output parameters. 124   token_ and &ec_ as the cancellation/output parameters.
79   */ 125   */
80   template<class Derived> 126   template<class Derived>
81   class void_op_base 127   class void_op_base
82   { 128   {
83   friend Derived; 129   friend Derived;
HITCBC 84   7654 void_op_base() = default; 130   6683 void_op_base() = default;
85   131  
86   public: 132   public:
87   std::stop_token token_; 133   std::stop_token token_;
88   mutable std::error_code ec_; 134   mutable std::error_code ec_;
89   135  
HITCBC 90   7654 bool await_ready() const noexcept 136   6683 bool await_ready() const noexcept
91   { 137   {
92   // A pre-set ec_ means the initiator failed before dispatch 138   // A pre-set ec_ means the initiator failed before dispatch
93   // (e.g. auto-open); complete immediately with that error. 139   // (e.g. auto-open); complete immediately with that error.
HITCBC 94   7654 return static_cast<bool>(ec_) || token_.stop_requested(); 140   6683 return static_cast<bool>(ec_) || token_.stop_requested();
95   } 141   }
96   142  
HITCBC 97   7641 [[nodiscard]] capy::io_result<> await_resume() const noexcept 143   6670 [[nodiscard]] capy::io_result<> await_resume() const noexcept
98   { 144   {
HITCBC 99   7641 if (token_.stop_requested()) 145   6670 if (token_.stop_requested())
HITCBC 100   32 return {make_error_code(std::errc::operation_canceled)}; 146   32 return {make_error_code(std::errc::operation_canceled)};
HITCBC 101   7609 return {ec_}; 147   6638 return {ec_};
102   } 148   }
103   149  
HITCBC 104   7650 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env) 150   6679 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
105   -> std::coroutine_handle<> 151   -> std::coroutine_handle<>
106   { 152   {
HITCBC 107   7650 token_ = env->stop_token; 153   6679 token_ = env->stop_token;
HITCBC 108   7650 return static_cast<Derived const*>(this)->dispatch( 154   6679 return static_cast<Derived const*>(this)->dispatch(
HITCBC 109   7650 h, env->executor); 155   6679 h, env->executor);
110   } 156   }
111   }; 157   };
112   158  
113   } // namespace boost::corosio::detail 159   } // namespace boost::corosio::detail
114   160  
115   #endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP 161   #endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP