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   461215 bytes_op_base() = default; 41   386895 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   461215 bool await_ready() const noexcept 51   386895 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   461215 return static_cast<bool>(ec_); 55   386895 return static_cast<bool>(ec_);
56   } 56   }
57   57  
HITCBC 58   460752 [[nodiscard]] capy::results<std::size_t> await_resume() const noexcept 58   386432 [[nodiscard]] capy::results<std::size_t> await_resume() const noexcept
59   { 59   {
HITCBC 60   460752 return {ec_, bytes_}; 60   386432 return {ec_, bytes_};
61   } 61   }
62   62  
HITCBC 63   461179 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env) 63   386859 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env)
64   -> std::coroutine_handle<> 64   -> std::coroutine_handle<>
65   { 65   {
HITCBC 66   461179 token_ = env->stop_token; 66   386859 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   461179 if (token_.stop_requested()) 71   386859 if (token_.stop_requested())
72   { 72   {
HITCBC 73   139 ec_ = capy::error::canceled; 73   145 ec_ = capy::error::canceled;
HITCBC 74   139 return h; 74   145 return h;
75   } 75   }
HITCBC 76   461040 cont_.h = h; 76   386714 cont_.h = h;
HITCBC 77   461040 cont_.owner = env->owner; 77   386714 cont_.owner = env->owner;
HITCBC 78   461040 return static_cast<Derived const*>(this)->dispatch( 78   386714 return static_cast<Derived const*>(this)->dispatch(
HITCBC 79   461040 cont_, env->executor); 79   386714 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   206100 value_op_base() = default; 99   205958 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   206100 bool await_ready() const noexcept 108   205958 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   206100 return static_cast<bool>(ec_); 112   205958 return static_cast<bool>(ec_);
113   } 113   }
114   114  
HITCBC 115   202876 [[nodiscard]] capy::results<Value> await_resume() const noexcept 115   202734 [[nodiscard]] capy::results<Value> await_resume() const noexcept
116   { 116   {
HITCBC 117   202876 return {ec_, std::move(value_)}; 117   202734 return {ec_, std::move(value_)};
118   } 118   }
119   119  
HITCBC 120   206100 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env) 120   205958 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env)
121   -> std::coroutine_handle<> 121   -> std::coroutine_handle<>
122   { 122   {
HITCBC 123   206100 token_ = env->stop_token; 123   205958 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   206100 if (token_.stop_requested()) 126   205958 if (token_.stop_requested())
127   { 127   {
HITCBC 128   44 ec_ = capy::error::canceled; 128   52 ec_ = capy::error::canceled;
HITCBC 129   44 return h; 129   52 return h;
130   } 130   }
HITCBC 131   206056 cont_.h = h; 131   205906 cont_.h = h;
HITCBC 132   206056 cont_.owner = env->owner; 132   205906 cont_.owner = env->owner;
HITCBC 133   206056 return static_cast<Derived const*>(this)->dispatch( 133   205906 return static_cast<Derived const*>(this)->dispatch(
HITCBC 134   206056 cont_, env->executor); 134   205906 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   16599 void_op_base() = default; 153   17050 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   16599 bool await_ready() const noexcept 161   17050 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   16599 return static_cast<bool>(ec_); 165   17050 return static_cast<bool>(ec_);
166   } 166   }
167   167  
HITCBC 168   9194 [[nodiscard]] capy::results<> await_resume() const noexcept 168   9607 [[nodiscard]] capy::results<> await_resume() const noexcept
169   { 169   {
HITCBC 170   9194 return {ec_}; 170   9607 return {ec_};
171   } 171   }
172   172  
HITCBC 173   16577 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env) 173   17028 auto await_suspend(std::coroutine_handle<> h, capy::await_context const* env)
174   -> std::coroutine_handle<> 174   -> std::coroutine_handle<>
175   { 175   {
HITCBC 176   16577 token_ = env->stop_token; 176   17028 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   16577 if (token_.stop_requested()) 179   17028 if (token_.stop_requested())
180   { 180   {
HITCBC 181   1039 ec_ = capy::error::canceled; 181   1059 ec_ = capy::error::canceled;
HITCBC 182   1039 return h; 182   1059 return h;
183   } 183   }
HITCBC 184   15538 cont_.h = h; 184   15969 cont_.h = h;
HITCBC 185   15538 cont_.owner = env->owner; 185   15969 cont_.owner = env->owner;
HITCBC 186   15538 return static_cast<Derived const*>(this)->dispatch( 186   15969 return static_cast<Derived const*>(this)->dispatch(
HITCBC 187   15538 cont_, env->executor); 187   15969 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