include/boost/corosio/native/native_random_access_file.hpp

96.0% Lines (48/50) 100.0% List of functions (34/34) 62.5% Branches (20/32)
native_random_access_file.hpp
f(x) Functions (34)
Function Calls Lines Branches Blocks
boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::~native_random_access_file() :68 16x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::~native_random_access_file() :68 16x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::get_impl() :74 7x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::get_impl() :74 7x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::native_read_at_awaitable(boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>&&) :80 8x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::~native_read_at_awaitable() :80 16x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::native_read_at_awaitable(boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>&&) :80 8x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::~native_read_at_awaitable() :80 16x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::native_read_at_awaitable(boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>&, unsigned long long, boost::capy::mutable_buffer) :89 8x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::native_read_at_awaitable(boost::corosio::native_random_access_file<boost::corosio::select_t{}>&, unsigned long long, boost::capy::mutable_buffer) :89 8x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::await_ready() const :99 4x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::await_ready() const :99 4x 100.0% 50.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::await_resume() const :106 4x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::await_resume() const :106 4x 100.0% 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :113 4x 100.0% 50.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :113 4x 83.3% 50.0% 50.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::native_write_at_awaitable(boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_write_at_awaitable<boost::capy::const_buffer>&&) :124 6x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::~native_write_at_awaitable() :124 12x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::native_write_at_awaitable(boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_write_at_awaitable<boost::capy::const_buffer>&&) :124 6x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::~native_write_at_awaitable() :124 12x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::native_write_at_awaitable(boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>&, unsigned long long, boost::capy::const_buffer) :133 6x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::native_write_at_awaitable(boost::corosio::native_random_access_file<boost::corosio::select_t{}>&, unsigned long long, boost::capy::const_buffer) :133 6x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::await_ready() const :143 3x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::await_ready() const :143 3x 100.0% 50.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::await_resume() const :150 3x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::await_resume() const :150 3x 100.0% 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :157 3x 100.0% 50.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :157 3x 83.3% 50.0% 50.0% boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::native_random_access_file(boost::capy::execution_context&) :172 16x 100.0% 100.0% boost::corosio::native_random_access_file<boost::corosio::select_t{}>::native_random_access_file(boost::capy::execution_context&) :172 16x 100.0% 100.0% auto boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::read_some_at<boost::capy::mutable_buffer>(unsigned long long, boost::capy::mutable_buffer const&) :208 4x 100.0% 100.0% auto boost::corosio::native_random_access_file<boost::corosio::select_t{}>::read_some_at<boost::capy::mutable_buffer>(unsigned long long, boost::capy::mutable_buffer const&) :208 4x 100.0% 100.0% auto boost::corosio::native_random_access_file<boost::corosio::kqueue_t{}>::write_some_at<boost::capy::const_buffer>(unsigned long long, boost::capy::const_buffer const&) :219 3x 100.0% 100.0% auto boost::corosio::native_random_access_file<boost::corosio::select_t{}>::write_some_at<boost::capy::const_buffer>(unsigned long long, boost::capy::const_buffer const&) :219 3x 100.0% 100.0%
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
3 // Copyright (c) 2026 Michael Vandeberg
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/corosio
9 //
10
11 #ifndef BOOST_COROSIO_NATIVE_NATIVE_RANDOM_ACCESS_FILE_HPP
12 #define BOOST_COROSIO_NATIVE_NATIVE_RANDOM_ACCESS_FILE_HPP
13
14 #include <boost/corosio/random_access_file.hpp>
15 #include <boost/corosio/backend.hpp>
16
17 #ifndef BOOST_COROSIO_MRDOCS
18 #if BOOST_COROSIO_HAS_EPOLL || BOOST_COROSIO_HAS_SELECT || \
19 BOOST_COROSIO_HAS_KQUEUE
20 #include <boost/corosio/native/detail/posix/posix_random_access_file_service.hpp>
21 #endif
22
23 #if BOOST_COROSIO_HAS_URING
24 #include <boost/corosio/native/detail/uring/uring_random_access_file.hpp>
25 #endif
26
27 #if BOOST_COROSIO_HAS_IOCP
28 #include <boost/corosio/native/detail/iocp/win_random_access_file_service.hpp>
29 #endif
30 #endif // !BOOST_COROSIO_MRDOCS
31
32 namespace boost::corosio {
33
34 /** A random-access file with devirtualized async I/O operations.
35
36 This class template inherits from @ref random_access_file and
37 shadows `read_some_at` / `write_some_at` with versions that
38 call the backend implementation directly, allowing the compiler
39 to inline through the entire call chain.
40
41 Non-async operations (`open`, `close`, `size`, `resize`,
42 `sync_data`, `sync_all`) remain unchanged and dispatch through
43 the compiled library.
44
45 A `native_random_access_file` IS-A `random_access_file` and
46 can be passed to any function expecting `random_access_file&`,
47 in which case virtual dispatch is used transparently.
48
49 @note On POSIX platforms, file I/O is dispatched to a thread
50 pool regardless of the chosen reactor backend, so all three
51 reactor tags (`epoll`, `select`, `kqueue`) resolve to the same
52 underlying implementation. The `Backend` template parameter
53 exists for API symmetry with @ref native_tcp_socket and friends.
54 The vtable savings are smaller relative to the thread-pool /
55 overlapped-I/O cost than they are for socket operations.
56
57 @tparam Backend A backend tag value (e.g., `epoll`, `iocp`).
58
59 @par Thread Safety
60 Same as @ref random_access_file.
61
62 @par Example
63 @par !example native_random_access_file
64
65 @see random_access_file, epoll_t, iocp_t
66 */
67 template<auto Backend>
68 class native_random_access_file : public random_access_file
69 {
70 using backend_type = decltype(Backend);
71 using impl_type = typename backend_type::random_access_file_type;
72 using service_type = typename backend_type::random_access_file_service_type;
73
74 14x impl_type& get_impl() noexcept
75 {
76 14x return *static_cast<impl_type*>(h_.get());
77 }
78
79 template<class MutableBufferSequence>
80 struct native_read_at_awaitable
81 {
82 native_random_access_file& self_;
83 std::uint64_t offset_;
84 MutableBufferSequence buffers_;
85 std::stop_token token_;
86 mutable std::error_code ec_;
87 8x mutable std::size_t bytes_transferred_ = 0;
88
89 24x native_read_at_awaitable(
90 native_random_access_file& self,
91 std::uint64_t offset,
92 MutableBufferSequence buffers) noexcept
93 8x : self_(self)
94 8x , offset_(offset)
95 8x , buffers_(std::move(buffers))
96 8x {
97 16x }
98
99 8x bool await_ready() const noexcept
100 {
101 // A pre-set ec_ means the initiator failed before
102 // dispatch (e.g. a closed object).
103
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
8x return static_cast<bool>(ec_) || token_.stop_requested();
104 }
105
106 8x [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
107 {
108
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 3 times.
8x if (token_.stop_requested())
109 2x return {make_error_code(std::errc::operation_canceled), 0};
110 6x return {ec_, bytes_transferred_};
111 8x }
112
113 8x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
114 -> std::coroutine_handle<>
115 {
116 8x token_ = env->stop_token;
117
4/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
16x return self_.get_impl().read_some_at(
118 8x offset_, h, env->executor, buffers_, token_, &ec_,
119 8x &bytes_transferred_);
120 }
121 };
122
123 template<class ConstBufferSequence>
124 struct native_write_at_awaitable
125 {
126 native_random_access_file& self_;
127 std::uint64_t offset_;
128 ConstBufferSequence buffers_;
129 std::stop_token token_;
130 mutable std::error_code ec_;
131 6x mutable std::size_t bytes_transferred_ = 0;
132
133 18x native_write_at_awaitable(
134 native_random_access_file& self,
135 std::uint64_t offset,
136 ConstBufferSequence buffers) noexcept
137 6x : self_(self)
138 6x , offset_(offset)
139 6x , buffers_(std::move(buffers))
140 6x {
141 12x }
142
143 6x bool await_ready() const noexcept
144 {
145 // A pre-set ec_ means the initiator failed before
146 // dispatch (e.g. a closed object).
147
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
6x return static_cast<bool>(ec_) || token_.stop_requested();
148 }
149
150 6x [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
151 {
152
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 2 times.
6x if (token_.stop_requested())
153 2x return {make_error_code(std::errc::operation_canceled), 0};
154 4x return {ec_, bytes_transferred_};
155 6x }
156
157 6x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
158 -> std::coroutine_handle<>
159 {
160 6x token_ = env->stop_token;
161
4/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
12x return self_.get_impl().write_some_at(
162 6x offset_, h, env->executor, buffers_, token_, &ec_,
163 6x &bytes_transferred_);
164 }
165 };
166
167 public:
168 /** Construct a native random-access file from an execution context.
169
170 @param ctx The execution context that will own this file.
171 */
172 32x explicit native_random_access_file(capy::execution_context& ctx)
173 16x : random_access_file(create_handle<service_type>(ctx))
174 32x {
175 32x }
176
177 /** Construct a native random-access file from an executor.
178
179 @param ex The executor whose context will own this file.
180 */
181 template<class Ex>
182 requires(!std::same_as<
183 std::remove_cvref_t<Ex>,
184 native_random_access_file>) &&
185 capy::Executor<Ex>
186 explicit native_random_access_file(Ex const& ex)
187 : native_random_access_file(ex.context())
188 {
189 }
190
191 /// Move construct.
192 native_random_access_file(native_random_access_file&&) noexcept = default;
193
194 /// Move assign.
195 native_random_access_file&
196 operator=(native_random_access_file&&) noexcept = default;
197
198 native_random_access_file(native_random_access_file const&) = delete;
199 native_random_access_file&
200 operator=(native_random_access_file const&) = delete;
201
202 /** Asynchronously read at the given offset.
203
204 Calls the backend implementation directly, bypassing virtual
205 dispatch. Otherwise identical to @ref random_access_file::read_some_at.
206 */
207 template<capy::MutableBufferSequence MB>
208 8x [[nodiscard]] auto read_some_at(std::uint64_t offset, MB const& buffers)
209 {
210 8x return native_read_at_awaitable<MB>(*this, offset, buffers);
211 }
212
213 /** Asynchronously write at the given offset.
214
215 Calls the backend implementation directly, bypassing virtual
216 dispatch. Otherwise identical to @ref random_access_file::write_some_at.
217 */
218 template<capy::ConstBufferSequence CB>
219 6x [[nodiscard]] auto write_some_at(std::uint64_t offset, CB const& buffers)
220 {
221 6x return native_write_at_awaitable<CB>(*this, offset, buffers);
222 }
223 };
224
225 } // namespace boost::corosio
226
227 #endif // BOOST_COROSIO_NATIVE_NATIVE_RANDOM_ACCESS_FILE_HPP
228