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