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