include/boost/corosio/native/native_win_random_access_handle.hpp

100.0% Lines (17/17) 100.0% List of functions (5/5) 100.0% Branches (3/3)
native_win_random_access_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_RANDOM_ACCESS_HANDLE_HPP
11 #define BOOST_COROSIO_NATIVE_NATIVE_WIN_RANDOM_ACCESS_HANDLE_HPP
12
13 #include <boost/corosio/detail/op_base.hpp>
14 #include <boost/corosio/win_random_access_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_random_access_handle_service.hpp>
21 #endif
22
23 namespace boost::corosio {
24
25 /** Drives an already-open overlapped handle at arbitrary offsets, calling the backend directly.
26
27 This class template inherits from @ref win_random_access_handle
28 and shadows `read_some_at` / `write_some_at` with versions that
29 call the backend implementation directly. The compiler can then
30 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_random_access_handle` IS-A
36 `win_random_access_handle` and can be passed to any function
37 expecting `win_random_access_handle&`, in which case virtual
38 dispatch is used 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_random_access_handle.
45
46 @par Example
47 @par !example native_win_random_access_handle
48
49 @see win_random_access_handle, iocp_t
50 */
51 template<auto Backend>
52 class native_win_random_access_handle : public win_random_access_handle
53 {
54 using backend_type = decltype(Backend);
55 using impl_type = typename backend_type::random_access_handle_type;
56 using service_type =
57 typename backend_type::random_access_handle_service_type;
58
59 1x impl_type& get_impl() noexcept
60 {
61 1x return *static_cast<impl_type*>(h_.get());
62 }
63
64 template<class MutableBufferSequence>
65 struct native_read_at_awaitable
66 : detail::bytes_op_base<native_read_at_awaitable<MutableBufferSequence>>
67 {
68 native_win_random_access_handle& self_;
69 std::uint64_t offset_;
70 MutableBufferSequence buffers_;
71 mutable capy::continuation cont_;
72
73 native_read_at_awaitable(
74 native_win_random_access_handle& self,
75 std::uint64_t offset,
76 MutableBufferSequence buffers) noexcept
77 : self_(self)
78 , offset_(offset)
79 , buffers_(std::move(buffers))
80 {
81 }
82
83 std::coroutine_handle<>
84 dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
85 {
86 cont_.h = h;
87 return self_.get_impl().read_some_at(
88 offset_, cont_, ex, buffers_, this->token_, &this->ec_,
89 &this->bytes_);
90 }
91 };
92
93 template<class ConstBufferSequence>
94 struct native_write_at_awaitable
95 : detail::bytes_op_base<native_write_at_awaitable<ConstBufferSequence>>
96 {
97 native_win_random_access_handle& self_;
98 std::uint64_t offset_;
99 ConstBufferSequence buffers_;
100 mutable capy::continuation cont_;
101
102 1x native_write_at_awaitable(
103 native_win_random_access_handle& self,
104 std::uint64_t offset,
105 ConstBufferSequence buffers) noexcept
106 1x : self_(self)
107 1x , offset_(offset)
108 1x , buffers_(std::move(buffers))
109 {
110 1x }
111
112 std::coroutine_handle<>
113 1x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
114 {
115 1x cont_.h = h;
116 2x return self_.get_impl().write_some_at(
117
1/1
✓ Branch 5 → 6 taken 1 time.
1x offset_, cont_, ex, buffers_, this->token_, &this->ec_,
118 2x &this->bytes_);
119 }
120 };
121
122 public:
123 /** Construct a `native_win_random_access_handle` from an execution context.
124
125 @param ctx The execution context that owns this object.
126 */
127 1x explicit native_win_random_access_handle(capy::execution_context& ctx)
128
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 3 → 4 taken 1 time.
1x : win_random_access_handle(handle(ctx, ctx.use_service<service_type>()))
129 {
130 1x }
131
132 /** Construct a `native_win_random_access_handle` from an executor.
133
134 The overload excludes `native_win_random_access_handle` itself
135 so that it cannot displace the move constructor.
136
137 @tparam Ex A type satisfying `capy::Executor`.
138 @param ex The executor whose context owns this object.
139 */
140 template<class Ex>
141 requires(!std::same_as<
142 std::remove_cvref_t<Ex>,
143 native_win_random_access_handle>) &&
144 capy::Executor<Ex>
145 explicit native_win_random_access_handle(Ex const& ex)
146 : native_win_random_access_handle(ex.context())
147 {
148 }
149
150 /** Transfer ownership of the handle from the source.
151
152 After the move, the source is in a moved-from state and may
153 only be destroyed or assigned to.
154
155 @pre No awaitables returned by the source's methods exist.
156 */
157 native_win_random_access_handle(
158 native_win_random_access_handle&&) noexcept = default;
159
160 /** Close any held handle and transfer ownership from the source.
161
162 After the move, the source is in a moved-from state and may
163 only be destroyed or assigned to.
164
165 @return `*this`.
166 @pre No awaitables returned by either object's methods exist.
167 */
168 native_win_random_access_handle&
169 operator=(native_win_random_access_handle&&) noexcept = default;
170
171 /// Copy construction is disabled; the handle is uniquely owned.
172 native_win_random_access_handle(
173 native_win_random_access_handle const&) = delete;
174 /// Copy assignment is disabled; the handle is uniquely owned.
175 native_win_random_access_handle&
176 operator=(native_win_random_access_handle const&) = delete;
177
178 /** Asynchronously read at the given offset.
179
180 Calls the backend implementation directly, bypassing virtual
181 dispatch. Unlike @ref win_random_access_handle::read_some_at,
182 it skips the `is_open()` check. A closed handle still completes
183 with `errc::bad_file_descriptor`. Do not call it on a moved-from
184 object.
185
186 @param offset The byte offset to read at.
187 @param buffers The buffers to read into.
188
189 @return An awaitable yielding the error code and the byte count read.
190 */
191 template<capy::MutableBufferSequence MB>
192 [[nodiscard]] auto read_some_at(std::uint64_t offset, MB const& buffers)
193 {
194 return native_read_at_awaitable<MB>(*this, offset, buffers);
195 }
196
197 /** Asynchronously write at the given offset.
198
199 Calls the backend implementation directly, bypassing virtual
200 dispatch. Unlike @ref win_random_access_handle::write_some_at,
201 it skips the `is_open()` check. A closed handle still completes
202 with `errc::bad_file_descriptor`. Do not call it on a moved-from
203 object.
204
205 @param offset The byte offset to write at.
206 @param buffers The buffer data to write.
207
208 @return An awaitable yielding the error code and the byte count written.
209 */
210 template<capy::ConstBufferSequence CB>
211 1x [[nodiscard]] auto write_some_at(std::uint64_t offset, CB const& buffers)
212 {
213 1x return native_write_at_awaitable<CB>(*this, offset, buffers);
214 }
215 };
216
217 } // namespace boost::corosio
218
219 #endif // BOOST_COROSIO_HAS_IOCP || BOOST_COROSIO_MRDOCS
220
221 #endif // BOOST_COROSIO_NATIVE_NATIVE_WIN_RANDOM_ACCESS_HANDLE_HPP
222