include/boost/corosio/native/native_random_access_file.hpp

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