100.00% Lines (30/30) 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   443170 bytes_op_base() = default; 39   406132 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   443170 bool await_ready() const noexcept 46   406132 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   443170 return static_cast<bool>(ec_) || token_.stop_requested(); 50   406132 return static_cast<bool>(ec_) || token_.stop_requested();
51   } 51   }
52   52  
HITCBC 53   443137 [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept 53   406099 [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
54   { 54   {
HITCBC 55   443137 if (token_.stop_requested()) 55   406099 if (token_.stop_requested())
HITCBC 56   245 return {make_error_code(std::errc::operation_canceled), 0}; 56   245 return {make_error_code(std::errc::operation_canceled), 0};
HITCBC 57   442892 return {ec_, bytes_}; 57   405854 return {ec_, bytes_};
58   } 58   }
59   59  
HITCBC 60   443154 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env) 60   406116 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
61   -> std::coroutine_handle<> 61   -> std::coroutine_handle<>
62   { 62   {
HITCBC 63   443154 token_ = env->stop_token; 63   406116 token_ = env->stop_token;
HITCBC 64 - 443154 return static_cast<Derived const*>(this)->dispatch( 64 + 406116 return static_cast<Derived const*>(this)->dispatch(h, env->executor);
DCB 65 - 443154 h, env->executor);  
66   } 65   }
67   }; 66   };
68   67  
69   /* CRTP base for awaitables that return io_result<Value> for a 68   /* CRTP base for awaitables that return io_result<Value> for a
70   moved-out result object (e.g. the resolver's result lists). 69   moved-out result object (e.g. the resolver's result lists).
71   70  
72   Derived classes must provide: 71   Derived classes must provide:
73   72  
74   std::coroutine_handle<> dispatch( 73   std::coroutine_handle<> dispatch(
75   std::coroutine_handle<> h, 74   std::coroutine_handle<> h,
76   capy::executor_ref ex) const; 75   capy::executor_ref ex) const;
77   76  
78   which forwards to the backend implementation method, passing 77   which forwards to the backend implementation method, passing
79   token_, &ec_, and &value_ as the cancellation/output parameters. 78   token_, &ec_, and &value_ as the cancellation/output parameters.
80   */ 79   */
81   template<class Derived, class Value> 80   template<class Derived, class Value>
82   class value_op_base 81   class value_op_base
83   { 82   {
84   friend Derived; 83   friend Derived;
HITCBC 85   50 value_op_base() = default; 84   50 value_op_base() = default;
86   85  
87   public: 86   public:
88   std::stop_token token_; 87   std::stop_token token_;
89   mutable std::error_code ec_; 88   mutable std::error_code ec_;
90   mutable Value value_{}; 89   mutable Value value_{};
91   90  
HITCBC 92   50 bool await_ready() const noexcept 91   50 bool await_ready() const noexcept
93   { 92   {
94   // A pre-set ec_ means the initiator failed before dispatch; 93   // A pre-set ec_ means the initiator failed before dispatch;
95   // complete immediately with that error. 94   // complete immediately with that error.
HITCBC 96   50 return static_cast<bool>(ec_) || token_.stop_requested(); 95   50 return static_cast<bool>(ec_) || token_.stop_requested();
97   } 96   }
98   97  
HITCBC 99   48 [[nodiscard]] capy::io_result<Value> await_resume() const noexcept 98   48 [[nodiscard]] capy::io_result<Value> await_resume() const noexcept
100   { 99   {
HITCBC 101   48 if (token_.stop_requested()) 100   48 if (token_.stop_requested())
HITCBC 102   2 return {make_error_code(std::errc::operation_canceled), {}}; 101   2 return {make_error_code(std::errc::operation_canceled), {}};
HITCBC 103   46 return {ec_, std::move(value_)}; 102   46 return {ec_, std::move(value_)};
104   } 103   }
105   104  
HITCBC 106   50 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env) 105   50 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
107   -> std::coroutine_handle<> 106   -> std::coroutine_handle<>
108   { 107   {
HITCBC 109   50 token_ = env->stop_token; 108   50 token_ = env->stop_token;
HITCBC 110 - 50 return static_cast<Derived const*>(this)->dispatch( 109 + 50 return static_cast<Derived const*>(this)->dispatch(h, env->executor);
DCB 111 - 50 h, env->executor);  
112   } 110   }
113   }; 111   };
114   112  
115   /* CRTP base for awaitables that return io_result<>. 113   /* CRTP base for awaitables that return io_result<>.
116   114  
117   Derived classes must provide: 115   Derived classes must provide:
118   116  
119   std::coroutine_handle<> dispatch( 117   std::coroutine_handle<> dispatch(
120   std::coroutine_handle<> h, 118   std::coroutine_handle<> h,
121   capy::executor_ref ex) const; 119   capy::executor_ref ex) const;
122   120  
123   which forwards to the backend implementation method, passing 121   which forwards to the backend implementation method, passing
124   token_ and &ec_ as the cancellation/output parameters. 122   token_ and &ec_ as the cancellation/output parameters.
125   */ 123   */
126   template<class Derived> 124   template<class Derived>
127   class void_op_base 125   class void_op_base
128   { 126   {
129   friend Derived; 127   friend Derived;
HITCBC 130   4720 void_op_base() = default; 128   4742 void_op_base() = default;
131   129  
132   public: 130   public:
133   std::stop_token token_; 131   std::stop_token token_;
134   mutable std::error_code ec_; 132   mutable std::error_code ec_;
135   133  
HITCBC 136   4720 bool await_ready() const noexcept 134   4742 bool await_ready() const noexcept
137   { 135   {
138   // A pre-set ec_ means the initiator failed before dispatch 136   // A pre-set ec_ means the initiator failed before dispatch
139   // (e.g. auto-open); complete immediately with that error. 137   // (e.g. auto-open); complete immediately with that error.
HITCBC 140   4720 return static_cast<bool>(ec_) || token_.stop_requested(); 138   4742 return static_cast<bool>(ec_) || token_.stop_requested();
141   } 139   }
142   140  
HITCBC 143   4707 [[nodiscard]] capy::io_result<> await_resume() const noexcept 141   4729 [[nodiscard]] capy::io_result<> await_resume() const noexcept
144   { 142   {
HITCBC 145   4707 if (token_.stop_requested()) 143   4729 if (token_.stop_requested())
HITCBC 146   32 return {make_error_code(std::errc::operation_canceled)}; 144   32 return {make_error_code(std::errc::operation_canceled)};
HITCBC 147   4675 return {ec_}; 145   4697 return {ec_};
148   } 146   }
149   147  
HITCBC 150   4716 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env) 148   4738 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
151   -> std::coroutine_handle<> 149   -> std::coroutine_handle<>
152   { 150   {
HITCBC 153   4716 token_ = env->stop_token; 151   4738 token_ = env->stop_token;
HITCBC 154 - 4716 return static_cast<Derived const*>(this)->dispatch( 152 + 4738 return static_cast<Derived const*>(this)->dispatch(h, env->executor);
DCB 155 - 4716 h, env->executor);  
156   } 153   }
157   }; 154   };
158   155  
159   } // namespace boost::corosio::detail 156   } // namespace boost::corosio::detail
160   157  
161   #endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP 158   #endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP