100.00% Lines (42/42) 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/error.hpp> 13   #include <boost/capy/error.hpp>
14   #include <boost/capy/continuation.hpp> 14   #include <boost/capy/continuation.hpp>
15   #include <boost/capy/results.hpp> 15   #include <boost/capy/results.hpp>
16   #include <boost/capy/ex/executor_ref.hpp> 16   #include <boost/capy/ex/executor_ref.hpp>
17   #include <boost/capy/ex/await_context.hpp> 17   #include <boost/capy/ex/await_context.hpp>
18   18  
19   #include <coroutine> 19   #include <coroutine>
20   #include <cstddef> 20   #include <cstddef>
21   #include <stop_token> 21   #include <stop_token>
22   #include <system_error> 22   #include <system_error>
23   23  
24   namespace boost::corosio::detail { 24   namespace boost::corosio::detail {
25   25  
26   /* CRTP base for awaitables that return results<std::size_t>. 26   /* CRTP base for awaitables that return results<std::size_t>.
27   27  
28   Derived classes must provide: 28   Derived classes must provide:
29   29  
30   std::coroutine_handle<> dispatch( 30   std::coroutine_handle<> dispatch(
31   capy::continuation& cont, 31   capy::continuation& cont,
32   capy::executor_ref ex) const; 32   capy::executor_ref ex) const;
33   33  
34   which forwards to the backend implementation method, passing 34   which forwards to the backend implementation method, passing
35   token_, &ec_, and &bytes_ as the cancellation/output parameters. 35   token_, &ec_, and &bytes_ as the cancellation/output parameters.
36   */ 36   */
37   template<class Derived> 37   template<class Derived>
38   class bytes_op_base 38   class bytes_op_base
39   { 39   {
40   friend Derived; 40   friend Derived;
HITCBC 41   452658 bytes_op_base() = default; 41   476006 bytes_op_base() = default;
42   42  
43   public: 43   public:
44   std::stop_token token_; 44   std::stop_token token_;
45   mutable std::error_code ec_; 45   mutable std::error_code ec_;
46   mutable std::size_t bytes_ = 0; 46   mutable std::size_t bytes_ = 0;
47   // Lives in the awaiting frame until resumption, so a completion 47   // Lives in the awaiting frame until resumption, so a completion
48   // posted through an executor never shares the object's state. 48   // posted through an executor never shares the object's state.
49   mutable capy::continuation cont_; 49   mutable capy::continuation cont_;
50   50  
HITCBC 51   452658 bool await_ready() const noexcept 51   476006 bool await_ready() const noexcept
52   { 52   {
53   // A pre-set ec_ means the initiator failed before dispatch 53   // A pre-set ec_ means the initiator failed before dispatch
54   // (e.g. a closed object); complete immediately with that error. 54   // (e.g. a closed object); complete immediately with that error.
HITCBC 55   452658 return static_cast<bool>(ec_); 55   476006 return static_cast<bool>(ec_);
56   } 56   }
57   57  
HITCBC 58   452195 [[nodiscard]] capy::results<std::size_t> await_resume() const noexcept 58   475543 [[nodiscard]] capy::results<std::size_t> await_resume() const noexcept
59   { 59   {
HITCBC 60   452195 return {ec_, bytes_}; 60   475543 return {ec_, bytes_};
61   } 61   }
62   62  
HITCBC 63   452622 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env) 63   475970 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env)
64   -> std::coroutine_handle<> 64   -> std::coroutine_handle<>
65   { 65   {
HITCBC 66   452622 token_ = env->stop_token; 66   475970 token_ = env->stop_token;
67   // A pre-stopped token short-circuits before dispatch so no I/O 67   // A pre-stopped token short-circuits before dispatch so no I/O
68   // is performed. A stop landing after dispatch is decoded by the 68   // is performed. A stop landing after dispatch is decoded by the
69   // backend, and a completed transfer is reported verbatim: the 69   // backend, and a completed transfer is reported verbatim: the
70   // stream contracts forbid discarding the byte count. 70   // stream contracts forbid discarding the byte count.
HITCBC 71   452622 if (token_.stop_requested()) 71   475970 if (token_.stop_requested())
72   { 72   {
HITCBC 73   129 ec_ = capy::error::canceled; 73   119 ec_ = capy::error::canceled;
HITCBC 74   129 return h; 74   119 return h;
75   } 75   }
HITCBC 76   452493 cont_.h = h; 76   475851 cont_.h = h;
HITCBC 77   452493 cont_.owner = env->owner; 77   475851 cont_.owner = env->owner;
HITCBC 78   452493 return static_cast<Derived const*>(this)->dispatch( 78   475851 return static_cast<Derived const*>(this)->dispatch(
HITCBC 79   452493 cont_, env->executor); 79   475851 cont_, env->executor);
80   } 80   }
81   }; 81   };
82   82  
83   /* CRTP base for awaitables that return results<Value> for a 83   /* CRTP base for awaitables that return results<Value> for a
84   moved-out result object (e.g. the resolver's result lists). 84   moved-out result object (e.g. the resolver's result lists).
85   85  
86   Derived classes must provide: 86   Derived classes must provide:
87   87  
88   std::coroutine_handle<> dispatch( 88   std::coroutine_handle<> dispatch(
89   capy::continuation& cont, 89   capy::continuation& cont,
90   capy::executor_ref ex) const; 90   capy::executor_ref ex) const;
91   91  
92   which forwards to the backend implementation method, passing 92   which forwards to the backend implementation method, passing
93   token_, &ec_, and &value_ as the cancellation/output parameters. 93   token_, &ec_, and &value_ as the cancellation/output parameters.
94   */ 94   */
95   template<class Derived, class Value> 95   template<class Derived, class Value>
96   class value_op_base 96   class value_op_base
97   { 97   {
98   friend Derived; 98   friend Derived;
HITCBC 99   205894 value_op_base() = default; 99   206085 value_op_base() = default;
100   100  
101   public: 101   public:
102   std::stop_token token_; 102   std::stop_token token_;
103   mutable std::error_code ec_; 103   mutable std::error_code ec_;
104   mutable Value value_{}; 104   mutable Value value_{};
105   // See bytes_op_base::cont_. 105   // See bytes_op_base::cont_.
106   mutable capy::continuation cont_; 106   mutable capy::continuation cont_;
107   107  
HITCBC 108   205894 bool await_ready() const noexcept 108   206085 bool await_ready() const noexcept
109   { 109   {
110   // A pre-set ec_ means the initiator failed before dispatch; 110   // A pre-set ec_ means the initiator failed before dispatch;
111   // complete immediately with that error. 111   // complete immediately with that error.
HITCBC 112   205894 return static_cast<bool>(ec_); 112   206085 return static_cast<bool>(ec_);
113   } 113   }
114   114  
HITCBC 115   202670 [[nodiscard]] capy::results<Value> await_resume() const noexcept 115   202861 [[nodiscard]] capy::results<Value> await_resume() const noexcept
116   { 116   {
HITCBC 117   202670 return {ec_, std::move(value_)}; 117   202861 return {ec_, std::move(value_)};
118   } 118   }
119   119  
HITCBC 120   205894 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env) 120   206085 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env)
121   -> std::coroutine_handle<> 121   -> std::coroutine_handle<>
122   { 122   {
HITCBC 123   205894 token_ = env->stop_token; 123   206085 token_ = env->stop_token;
124   // A pre-stopped token short-circuits before dispatch; a stop 124   // A pre-stopped token short-circuits before dispatch; a stop
125   // landing after dispatch leaves the completed result intact. 125   // landing after dispatch leaves the completed result intact.
HITCBC 126   205894 if (token_.stop_requested()) 126   206085 if (token_.stop_requested())
127   { 127   {
HITCBC 128   30 ec_ = capy::error::canceled; 128   34 ec_ = capy::error::canceled;
HITCBC 129   30 return h; 129   34 return h;
130   } 130   }
HITCBC 131   205864 cont_.h = h; 131   206051 cont_.h = h;
HITCBC 132   205864 cont_.owner = env->owner; 132   206051 cont_.owner = env->owner;
HITCBC 133   205864 return static_cast<Derived const*>(this)->dispatch( 133   206051 return static_cast<Derived const*>(this)->dispatch(
HITCBC 134   205864 cont_, env->executor); 134   206051 cont_, env->executor);
135   } 135   }
136   }; 136   };
137   137  
138   /* CRTP base for awaitables that return results<>. 138   /* CRTP base for awaitables that return results<>.
139   139  
140   Derived classes must provide: 140   Derived classes must provide:
141   141  
142   std::coroutine_handle<> dispatch( 142   std::coroutine_handle<> dispatch(
143   capy::continuation& cont, 143   capy::continuation& cont,
144   capy::executor_ref ex) const; 144   capy::executor_ref ex) const;
145   145  
146   which forwards to the backend implementation method, passing 146   which forwards to the backend implementation method, passing
147   token_ and &ec_ as the cancellation/output parameters. 147   token_ and &ec_ as the cancellation/output parameters.
148   */ 148   */
149   template<class Derived> 149   template<class Derived>
150   class void_op_base 150   class void_op_base
151   { 151   {
152   friend Derived; 152   friend Derived;
HITCBC 153   17242 void_op_base() = default; 153   17039 void_op_base() = default;
154   154  
155   public: 155   public:
156   std::stop_token token_; 156   std::stop_token token_;
157   mutable std::error_code ec_; 157   mutable std::error_code ec_;
158   // See bytes_op_base::cont_. 158   // See bytes_op_base::cont_.
159   mutable capy::continuation cont_; 159   mutable capy::continuation cont_;
160   160  
HITCBC 161   17242 bool await_ready() const noexcept 161   17039 bool await_ready() const noexcept
162   { 162   {
163   // A pre-set ec_ means the initiator failed before dispatch 163   // A pre-set ec_ means the initiator failed before dispatch
164   // (e.g. auto-open); complete immediately with that error. 164   // (e.g. auto-open); complete immediately with that error.
HITCBC 165   17242 return static_cast<bool>(ec_); 165   17039 return static_cast<bool>(ec_);
166   } 166   }
167   167  
HITCBC 168   9808 [[nodiscard]] capy::results<> await_resume() const noexcept 168   9487 [[nodiscard]] capy::results<> await_resume() const noexcept
169   { 169   {
HITCBC 170   9808 return {ec_}; 170   9487 return {ec_};
171   } 171   }
172   172  
HITCBC 173   17220 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env) 173   17017 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env)
174   -> std::coroutine_handle<> 174   -> std::coroutine_handle<>
175   { 175   {
HITCBC 176   17220 token_ = env->stop_token; 176   17017 token_ = env->stop_token;
177   // A pre-stopped token short-circuits before dispatch; a stop 177   // A pre-stopped token short-circuits before dispatch; a stop
178   // landing after dispatch leaves the completed result intact. 178   // landing after dispatch leaves the completed result intact.
HITCBC 179   17220 if (token_.stop_requested()) 179   17017 if (token_.stop_requested())
180   { 180   {
HITCBC 181   1059 ec_ = capy::error::canceled; 181   1064 ec_ = capy::error::canceled;
HITCBC 182   1059 return h; 182   1064 return h;
183   } 183   }
HITCBC 184   16161 cont_.h = h; 184   15953 cont_.h = h;
HITCBC 185   16161 cont_.owner = env->owner; 185   15953 cont_.owner = env->owner;
HITCBC 186   16161 return static_cast<Derived const*>(this)->dispatch( 186   15953 return static_cast<Derived const*>(this)->dispatch(
HITCBC 187   16161 cont_, env->executor); 187   15953 cont_, env->executor);
188   } 188   }
189   }; 189   };
190   190  
191   } // namespace boost::corosio::detail 191   } // namespace boost::corosio::detail
192   192  
193   #endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP 193   #endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP