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