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 428588 : 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 428588 : 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 428588 : return static_cast<bool>(ec_) || token_.stop_requested();
51 : }
52 :
53 428555 : [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
54 : {
55 428555 : if (token_.stop_requested())
56 237 : return {make_error_code(std::errc::operation_canceled), 0};
57 428318 : return {ec_, bytes_};
58 : }
59 :
60 428572 : auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
61 : -> std::coroutine_handle<>
62 : {
63 428572 : token_ = env->stop_token;
64 428572 : return static_cast<Derived const*>(this)->dispatch(
65 428572 : 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 4535 : void_op_base() = default;
131 :
132 : public:
133 : std::stop_token token_;
134 : mutable std::error_code ec_;
135 :
136 4535 : 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 4535 : return static_cast<bool>(ec_) || token_.stop_requested();
141 : }
142 :
143 4522 : [[nodiscard]] capy::io_result<> await_resume() const noexcept
144 : {
145 4522 : if (token_.stop_requested())
146 32 : return {make_error_code(std::errc::operation_canceled)};
147 4490 : return {ec_};
148 : }
149 :
150 4531 : auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
151 : -> std::coroutine_handle<>
152 : {
153 4531 : token_ = env->stop_token;
154 4531 : return static_cast<Derived const*>(this)->dispatch(
155 4531 : h, env->executor);
156 : }
157 : };
158 :
159 : } // namespace boost::corosio::detail
160 :
161 : #endif // BOOST_COROSIO_DETAIL_OP_BASE_HPP
|