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