include/boost/corosio/native/native_win_stream_handle.hpp

100.0% Lines (14/14) 100.0% List of functions (5/5) 100.0% Branches (3/3)
native_win_stream_handle.hpp
f(x) Functions (5)
Line Branch TLA Hits 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_NATIVE_NATIVE_WIN_STREAM_HANDLE_HPP
11 #define BOOST_COROSIO_NATIVE_NATIVE_WIN_STREAM_HANDLE_HPP
12
13 #include <boost/corosio/detail/op_base.hpp>
14 #include <boost/corosio/win_stream_handle.hpp>
15 #include <boost/corosio/backend.hpp>
16
17 #if BOOST_COROSIO_HAS_IOCP || defined(BOOST_COROSIO_MRDOCS)
18
19 #ifndef BOOST_COROSIO_MRDOCS
20 #include <boost/corosio/native/detail/iocp/win_stream_handle_service.hpp>
21 #endif
22
23 namespace boost::corosio {
24
25 /** Drives an already-open overlapped Windows handle, calling the backend directly.
26
27 This class template inherits from @ref win_stream_handle and
28 shadows the async operations (`read_some`, `write_some`) with
29 versions that call the backend implementation directly. This
30 lets the compiler inline through the entire call chain.
31
32 Non-async operations (`assign`, `release`, `close`, `cancel`)
33 remain unchanged and dispatch through the compiled library.
34
35 A `native_win_stream_handle` IS-A `win_stream_handle` and can be
36 passed to any function expecting `win_stream_handle&` or
37 `io_stream&`, in which case virtual dispatch is used
38 transparently.
39
40 @tparam Backend A backend tag value (e.g., `iocp`) whose type
41 provides the concrete implementation types.
42
43 @par Thread Safety
44 Same as @ref win_stream_handle.
45
46 @see win_stream_handle, iocp_t
47 */
48 template<auto Backend>
49 class native_win_stream_handle : public win_stream_handle
50 {
51 using backend_type = decltype(Backend);
52 using impl_type = typename backend_type::stream_handle_type;
53 using service_type = typename backend_type::stream_handle_service_type;
54
55 1x impl_type& get_impl() noexcept
56 {
57 1x return *static_cast<impl_type*>(h_.get());
58 }
59
60 template<class MutableBufferSequence>
61 struct native_read_awaitable
62 : detail::bytes_op_base<native_read_awaitable<MutableBufferSequence>>
63 {
64 native_win_stream_handle& self_;
65 MutableBufferSequence buffers_;
66
67 1x native_read_awaitable(
68 native_win_stream_handle& self,
69 MutableBufferSequence buffers) noexcept
70 1x : self_(self)
71 1x , buffers_(std::move(buffers))
72 {
73 1x }
74
75 std::coroutine_handle<>
76 1x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
77 {
78
1/1
✓ Branch 5 → 6 taken 1 time.
3x return self_.get_impl().read_some(
79 3x h, ex, buffers_, this->token_, &this->ec_, &this->bytes_);
80 }
81 };
82
83 template<class ConstBufferSequence>
84 struct native_write_awaitable
85 : detail::bytes_op_base<native_write_awaitable<ConstBufferSequence>>
86 {
87 native_win_stream_handle& self_;
88 ConstBufferSequence buffers_;
89
90 native_write_awaitable(
91 native_win_stream_handle& self,
92 ConstBufferSequence buffers) noexcept
93 : self_(self)
94 , buffers_(std::move(buffers))
95 {
96 }
97
98 std::coroutine_handle<>
99 dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
100 {
101 return self_.get_impl().write_some(
102 h, ex, buffers_, this->token_, &this->ec_, &this->bytes_);
103 }
104 };
105
106 public:
107 /** Construct a `native_win_stream_handle` from an execution context.
108
109 @param ctx The execution context that owns this object.
110 */
111 1x explicit native_win_stream_handle(capy::execution_context& ctx)
112
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 3 → 4 taken 1 time.
1x : io_object(handle(ctx, ctx.use_service<service_type>()))
113 {
114 1x }
115
116 /** Construct a `native_win_stream_handle` from an executor.
117
118 The overload excludes `native_win_stream_handle` itself so that
119 it cannot displace the move constructor.
120
121 @tparam Ex A type satisfying `capy::Executor`.
122 @param ex The executor whose context owns this object.
123 */
124 template<class Ex>
125 requires(!std::same_as<
126 std::remove_cvref_t<Ex>,
127 native_win_stream_handle>) &&
128 capy::Executor<Ex>
129 explicit native_win_stream_handle(Ex const& ex)
130 : native_win_stream_handle(ex.context())
131 {
132 }
133
134 /** Transfer ownership of the handle from the source.
135
136 After the move, the source is in a moved-from state and may
137 only be destroyed or assigned to.
138
139 @pre No awaitables returned by the source's methods exist.
140 */
141 native_win_stream_handle(native_win_stream_handle&&) noexcept = default;
142
143 /** Close any held handle and transfer ownership from the source.
144
145 After the move, the source is in a moved-from state and may
146 only be destroyed or assigned to.
147
148 @return `*this`.
149 @pre No awaitables returned by either object's methods exist.
150 */
151 native_win_stream_handle&
152 operator=(native_win_stream_handle&&) noexcept = default;
153
154 /// Copy construction is disabled; the handle is uniquely owned.
155 native_win_stream_handle(native_win_stream_handle const&) = delete;
156 /// Copy assignment is disabled; the handle is uniquely owned.
157 native_win_stream_handle&
158 operator=(native_win_stream_handle const&) = delete;
159
160 /** Asynchronously read data from the handle.
161
162 Calls the backend implementation directly, bypassing virtual
163 dispatch. Otherwise identical to @ref io_stream::read_some.
164
165 @param buffers The buffer sequence to read into.
166
167 @return An awaitable yielding `(error_code, std::size_t)`.
168 */
169 template<capy::MutableBufferSequence MB>
170 1x [[nodiscard]] auto read_some(MB const& buffers)
171 {
172 1x return native_read_awaitable<MB>(*this, buffers);
173 }
174
175 /** Asynchronously write data to the handle.
176
177 Calls the backend implementation directly, bypassing virtual
178 dispatch. Otherwise identical to @ref io_stream::write_some.
179
180 @param buffers The buffer sequence to write from.
181
182 @return An awaitable yielding `(error_code, std::size_t)`.
183 */
184 template<capy::ConstBufferSequence CB>
185 [[nodiscard]] auto write_some(CB const& buffers)
186 {
187 return native_write_awaitable<CB>(*this, buffers);
188 }
189 };
190
191 } // namespace boost::corosio
192
193 #endif // BOOST_COROSIO_HAS_IOCP || BOOST_COROSIO_MRDOCS
194
195 #endif // BOOST_COROSIO_NATIVE_NATIVE_WIN_STREAM_HANDLE_HPP
196