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/error.hpp> 13   #include <boost/capy/error.hpp>
14   #include <boost/capy/io_result.hpp> 14   #include <boost/capy/io_result.hpp>
15   #include <boost/capy/ex/executor_ref.hpp> 15   #include <boost/capy/ex/executor_ref.hpp>
16   #include <boost/capy/ex/io_env.hpp> 16   #include <boost/capy/ex/io_env.hpp>
17   17  
18   #include <coroutine> 18   #include <coroutine>
19   #include <cstddef> 19   #include <cstddef>
20   #include <stop_token> 20   #include <stop_token>
21   #include <system_error> 21   #include <system_error>
22   22  
23   namespace boost::corosio::detail { 23   namespace boost::corosio::detail {
24   24  
25   /* CRTP base for awaitables that return io_result<std::size_t>. 25   /* CRTP base for awaitables that return io_result<std::size_t>.
26   26  
27   Derived classes must provide: 27   Derived classes must provide:
28   28  
29   std::coroutine_handle<> dispatch( 29   std::coroutine_handle<> dispatch(
30   std::coroutine_handle<> h, 30   std::coroutine_handle<> h,
31   capy::executor_ref ex) const; 31   capy::executor_ref ex) const;
32   32  
33   which forwards to the backend implementation method, passing 33   which forwards to the backend implementation method, passing
34   token_, &ec_, and &bytes_ as the cancellation/output parameters. 34   token_, &ec_, and &bytes_ as the cancellation/output parameters.
35   */ 35   */
36   template<class Derived> 36   template<class Derived>
37   class bytes_op_base 37   class bytes_op_base
38   { 38   {
39   friend Derived; 39   friend Derived;
HITCBC 40   421610 bytes_op_base() = default; 40   441972 bytes_op_base() = default;
41   41  
42   public: 42   public:
43   std::stop_token token_; 43   std::stop_token token_;
44   mutable std::error_code ec_; 44   mutable std::error_code ec_;
45   mutable std::size_t bytes_ = 0; 45   mutable std::size_t bytes_ = 0;
46   46  
HITCBC 47   421610 bool await_ready() const noexcept 47   441972 bool await_ready() const noexcept
48   { 48   {
49   // A pre-set ec_ means the initiator failed before dispatch 49   // A pre-set ec_ means the initiator failed before dispatch
50   // (e.g. a closed object); complete immediately with that error. 50   // (e.g. a closed object); complete immediately with that error.
HITCBC 51   421610 return static_cast<bool>(ec_); 51   441972 return static_cast<bool>(ec_);
52   } 52   }
53   53  
HITCBC 54   421575 [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept 54   441937 [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
55   { 55   {
HITCBC 56   421575 return {ec_, bytes_}; 56   441937 return {ec_, bytes_};
57   } 57   }
58   58  
HITCBC 59   421574 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env) 59   441936 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
60   -> std::coroutine_handle<> 60   -> std::coroutine_handle<>
61   { 61   {
HITCBC 62   421574 token_ = env->stop_token; 62   441936 token_ = env->stop_token;
63   // A pre-stopped token short-circuits before dispatch so no I/O 63   // A pre-stopped token short-circuits before dispatch so no I/O
64   // is performed. A stop landing after dispatch is decoded by the 64   // is performed. A stop landing after dispatch is decoded by the
65   // backend, and a completed transfer is reported verbatim: the 65   // backend, and a completed transfer is reported verbatim: the
66   // stream contracts forbid discarding the byte count. 66   // stream contracts forbid discarding the byte count.
HITCBC 67   421574 if (token_.stop_requested()) 67   441936 if (token_.stop_requested())
68   { 68   {
HITCBC 69   73 ec_ = capy::error::canceled; 69   73 ec_ = capy::error::canceled;
HITCBC 70   73 return h; 70   73 return h;
71   } 71   }
HITCBC 72   421501 return static_cast<Derived const*>(this)->dispatch(h, env->executor); 72   441863 return static_cast<Derived const*>(this)->dispatch(h, env->executor);
73   } 73   }
74   }; 74   };
75   75  
76   /* CRTP base for awaitables that return io_result<Value> for a 76   /* CRTP base for awaitables that return io_result<Value> for a
77   moved-out result object (e.g. the resolver's result lists). 77   moved-out result object (e.g. the resolver's result lists).
78   78  
79   Derived classes must provide: 79   Derived classes must provide:
80   80  
81   std::coroutine_handle<> dispatch( 81   std::coroutine_handle<> dispatch(
82   std::coroutine_handle<> h, 82   std::coroutine_handle<> h,
83   capy::executor_ref ex) const; 83   capy::executor_ref ex) const;
84   84  
85   which forwards to the backend implementation method, passing 85   which forwards to the backend implementation method, passing
86   token_, &ec_, and &value_ as the cancellation/output parameters. 86   token_, &ec_, and &value_ as the cancellation/output parameters.
87   */ 87   */
88   template<class Derived, class Value> 88   template<class Derived, class Value>
89   class value_op_base 89   class value_op_base
90   { 90   {
91   friend Derived; 91   friend Derived;
HITCBC 92   1202 value_op_base() = default; 92   1202 value_op_base() = default;
93   93  
94   public: 94   public:
95   std::stop_token token_; 95   std::stop_token token_;
96   mutable std::error_code ec_; 96   mutable std::error_code ec_;
97   mutable Value value_{}; 97   mutable Value value_{};
98   98  
HITCBC 99   1202 bool await_ready() const noexcept 99   1202 bool await_ready() const noexcept
100   { 100   {
101   // A pre-set ec_ means the initiator failed before dispatch; 101   // A pre-set ec_ means the initiator failed before dispatch;
102   // complete immediately with that error. 102   // complete immediately with that error.
HITCBC 103   1202 return static_cast<bool>(ec_); 103   1202 return static_cast<bool>(ec_);
104   } 104   }
105   105  
HITCBC 106   1188 [[nodiscard]] capy::io_result<Value> await_resume() const noexcept 106   1188 [[nodiscard]] capy::io_result<Value> await_resume() const noexcept
107   { 107   {
HITCBC 108   1188 return {ec_, std::move(value_)}; 108   1188 return {ec_, std::move(value_)};
109   } 109   }
110   110  
HITCBC 111   1202 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env) 111   1202 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
112   -> std::coroutine_handle<> 112   -> std::coroutine_handle<>
113   { 113   {
HITCBC 114   1202 token_ = env->stop_token; 114   1202 token_ = env->stop_token;
115   // A pre-stopped token short-circuits before dispatch; a stop 115   // A pre-stopped token short-circuits before dispatch; a stop
116   // landing after dispatch leaves the completed result intact. 116   // landing after dispatch leaves the completed result intact.
HITCBC 117   1202 if (token_.stop_requested()) 117   1202 if (token_.stop_requested())
118   { 118   {
HITCBC 119   43 ec_ = capy::error::canceled; 119   42 ec_ = capy::error::canceled;
HITCBC 120   43 return h; 120   42 return h;
121   } 121   }
HITCBC 122   1159 return static_cast<Derived const*>(this)->dispatch(h, env->executor); 122   1160 return static_cast<Derived const*>(this)->dispatch(h, env->executor);
123   } 123   }
124   }; 124   };
125   125  
126   /* CRTP base for awaitables that return io_result<>. 126   /* CRTP base for awaitables that return io_result<>.
127   127  
128   Derived classes must provide: 128   Derived classes must provide:
129   129  
130   std::coroutine_handle<> dispatch( 130   std::coroutine_handle<> dispatch(
131   std::coroutine_handle<> h, 131   std::coroutine_handle<> h,
132   capy::executor_ref ex) const; 132   capy::executor_ref ex) const;
133   133  
134   which forwards to the backend implementation method, passing 134   which forwards to the backend implementation method, passing
135   token_ and &ec_ as the cancellation/output parameters. 135   token_ and &ec_ as the cancellation/output parameters.
136   */ 136   */
137   template<class Derived> 137   template<class Derived>
138   class void_op_base 138   class void_op_base
139   { 139   {
140   friend Derived; 140   friend Derived;
HITCBC 141   9362 void_op_base() = default; 141   9130 void_op_base() = default;
142   142  
143   public: 143   public:
144   std::stop_token token_; 144   std::stop_token token_;
145   mutable std::error_code ec_; 145   mutable std::error_code ec_;
146   146  
HITCBC 147   9362 bool await_ready() const noexcept 147   9130 bool await_ready() const noexcept
148   { 148   {
149   // A pre-set ec_ means the initiator failed before dispatch 149   // A pre-set ec_ means the initiator failed before dispatch
150   // (e.g. auto-open); complete immediately with that error. 150   // (e.g. auto-open); complete immediately with that error.
HITCBC 151   9362 return static_cast<bool>(ec_); 151   9130 return static_cast<bool>(ec_);
152   } 152   }
153   153  
HITCBC 154   4759 [[nodiscard]] capy::io_result<> await_resume() const noexcept 154   4643 [[nodiscard]] capy::io_result<> await_resume() const noexcept
155   { 155   {
HITCBC 156   4759 return {ec_}; 156   4643 return {ec_};
157   } 157   }
158   158  
HITCBC 159   9340 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env) 159   9108 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
160   -> std::coroutine_handle<> 160   -> std::coroutine_handle<>
161   { 161   {
HITCBC 162   9340 token_ = env->stop_token; 162   9108 token_ = env->stop_token;
163   // A pre-stopped token short-circuits before dispatch; a stop 163   // A pre-stopped token short-circuits before dispatch; a stop
164   // landing after dispatch leaves the completed result intact. 164   // landing after dispatch leaves the completed result intact.
HITCBC 165   9340 if (token_.stop_requested()) 165   9108 if (token_.stop_requested())
166   { 166   {
HITCBC 167   51 ec_ = capy::error::canceled; 167   51 ec_ = capy::error::canceled;
HITCBC 168   51 return h; 168   51 return h;
169   } 169   }
HITCBC 170   9289 return static_cast<Derived const*>(this)->dispatch(h, env->executor); 170   9057 return static_cast<Derived const*>(this)->dispatch(h, env->executor);
171   } 171   }
172   }; 172   };
173   173  
174   } // namespace boost::corosio::detail 174   } // namespace boost::corosio::detail
175   175  
176   #endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP 176   #endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP