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