include/boost/corosio/native/native_random_access_file.hpp

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