include/boost/corosio/native/native_random_access_file.hpp

100.0% Lines (29/29) 100.0% List of functions (8/8) 100.0% Branches (4/4)
native_random_access_file.hpp
f(x) Functions (8)
Function Calls Lines Branches Blocks
boost::corosio::native_random_access_file<boost::corosio::iocp_t{}>::get_impl() :75 5x 100.0% – 100.0% boost::corosio::native_random_access_file<boost::corosio::iocp_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::native_read_at_awaitable(boost::corosio::native_random_access_file<boost::corosio::iocp_t{}>&, unsigned long long, boost::capy::mutable_buffer) :89 4x 100.0% – 100.0% boost::corosio::native_random_access_file<boost::corosio::iocp_t{}>::native_read_at_awaitable<boost::capy::mutable_buffer>::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :100 3x 100.0% 100.0% 75.0% boost::corosio::native_random_access_file<boost::corosio::iocp_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::native_write_at_awaitable(boost::corosio::native_random_access_file<boost::corosio::iocp_t{}>&, unsigned long long, boost::capy::const_buffer) :118 3x 100.0% – 100.0% boost::corosio::native_random_access_file<boost::corosio::iocp_t{}>::native_write_at_awaitable<boost::capy::const_buffer>::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :129 2x 100.0% 100.0% 75.0% boost::corosio::native_random_access_file<boost::corosio::iocp_t{}>::native_random_access_file(boost::capy::execution_context&) :143 8x 100.0% 100.0% 100.0% auto boost::corosio::native_random_access_file<boost::corosio::iocp_t{}>::read_some_at<boost::capy::mutable_buffer>(unsigned long long, boost::capy::mutable_buffer const&) :186 4x 100.0% – 100.0% auto boost::corosio::native_random_access_file<boost::corosio::iocp_t{}>::write_some_at<boost::capy::const_buffer>(unsigned long long, boost::capy::const_buffer const&) :202 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 #include <boost/corosio/detail/op_base.hpp>
17
18 #ifndef BOOST_COROSIO_MRDOCS
19 #if BOOST_COROSIO_HAS_EPOLL || BOOST_COROSIO_HAS_SELECT || \
20 BOOST_COROSIO_HAS_KQUEUE
21 #include <boost/corosio/native/detail/posix/posix_random_access_file_service.hpp>
22 #endif
23
24 #if BOOST_COROSIO_HAS_URING
25 #include <boost/corosio/native/detail/uring/uring_random_access_file.hpp>
26 #endif
27
28 #if BOOST_COROSIO_HAS_IOCP
29 #include <boost/corosio/native/detail/iocp/win_random_access_file_service.hpp>
30 #endif
31 #endif // !BOOST_COROSIO_MRDOCS
32
33 namespace boost::corosio {
34
35 /** Reads and writes a file at arbitrary offsets, calling the backend directly.
36
37 This class template inherits from @ref random_access_file. It
38 shadows `read_some_at` / `write_some_at` with versions that call the
39 backend implementation directly. The compiler can then inline
40 through the entire call chain.
41
42 Non-async operations (`open`, `close`, `size`, `resize`,
43 `sync_data`, `sync_all`) remain unchanged and dispatch through
44 the compiled library.
45
46 A `native_random_access_file` IS-A `random_access_file` and
47 can be passed to any function expecting `random_access_file&`,
48 in which case virtual dispatch is used transparently.
49
50 @note On POSIX platforms, file I/O is dispatched to a thread pool
51 regardless of the chosen reactor backend. All three reactor tags
52 (`epoll`, `select`, `kqueue`) therefore resolve to the same
53 underlying implementation. The `Backend` template parameter
54 exists for API symmetry with @ref native_tcp_socket and friends.
55 The vtable savings are smaller relative to the thread-pool /
56 overlapped-I/O cost than they are for socket operations.
57
58 @tparam Backend A backend tag value (e.g., `epoll`, `iocp`).
59
60 @par Thread Safety
61 Same as @ref random_access_file.
62
63 @par Example
64 @par !example native_random_access_file
65
66 @see random_access_file, epoll_t, iocp_t
67 */
68 template<auto Backend>
69 class native_random_access_file : public random_access_file
70 {
71 using backend_type = decltype(Backend);
72 using impl_type = typename backend_type::random_access_file_type;
73 using service_type = typename backend_type::random_access_file_service_type;
74
75 5x impl_type& get_impl() noexcept
76 {
77 5x return *static_cast<impl_type*>(h_.get());
78 }
79
80 template<class MutableBufferSequence>
81 struct native_read_at_awaitable
82 : detail::bytes_op_base<native_read_at_awaitable<MutableBufferSequence>>
83 {
84 native_random_access_file& self_;
85 std::uint64_t offset_;
86 MutableBufferSequence buffers_;
87 mutable capy::continuation cont_;
88
89 4x native_read_at_awaitable(
90 native_random_access_file& self,
91 std::uint64_t offset,
92 MutableBufferSequence buffers) noexcept
93 4x : self_(self)
94 4x , offset_(offset)
95 4x , buffers_(std::move(buffers))
96 {
97 4x }
98
99 std::coroutine_handle<>
100 3x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
101 {
102 3x cont_.h = h;
103 6x return self_.get_impl().read_some_at(
104
1/1
✓ Branch 5 → 6 taken 3 times.
3x offset_, cont_, ex, buffers_, this->token_, &this->ec_,
105 6x &this->bytes_);
106 }
107 };
108
109 template<class ConstBufferSequence>
110 struct native_write_at_awaitable
111 : detail::bytes_op_base<native_write_at_awaitable<ConstBufferSequence>>
112 {
113 native_random_access_file& self_;
114 std::uint64_t offset_;
115 ConstBufferSequence buffers_;
116 mutable capy::continuation cont_;
117
118 3x native_write_at_awaitable(
119 native_random_access_file& self,
120 std::uint64_t offset,
121 ConstBufferSequence buffers) noexcept
122 3x : self_(self)
123 3x , offset_(offset)
124 3x , buffers_(std::move(buffers))
125 {
126 3x }
127
128 std::coroutine_handle<>
129 2x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
130 {
131 2x cont_.h = h;
132 4x return self_.get_impl().write_some_at(
133
1/1
✓ Branch 5 → 6 taken 2 times.
2x offset_, cont_, ex, buffers_, this->token_, &this->ec_,
134 4x &this->bytes_);
135 }
136 };
137
138 public:
139 /** Construct a native random-access file from an execution context.
140
141 @param ctx The execution context that owns this file.
142 */
143 8x explicit native_random_access_file(capy::execution_context& ctx)
144
2/2
✓ Branch 2 → 3 taken 8 times.
✓ Branch 3 → 4 taken 8 times.
8x : random_access_file(handle(ctx, ctx.use_service<service_type>()))
145 {
146 8x }
147
148 /** Construct a native random-access file from an executor.
149
150 @param ex The executor whose context owns this file.
151 */
152 template<class Ex>
153 requires(!std::same_as<
154 std::remove_cvref_t<Ex>,
155 native_random_access_file>) &&
156 capy::Executor<Ex>
157 explicit native_random_access_file(Ex const& ex)
158 : native_random_access_file(ex.context())
159 {
160 }
161
162 /// Move construct.
163 native_random_access_file(native_random_access_file&&) noexcept = default;
164
165 /// Move assign.
166 native_random_access_file&
167 operator=(native_random_access_file&&) noexcept = default;
168
169 /// Copy construction is disabled; the handle is uniquely owned.
170 native_random_access_file(native_random_access_file const&) = delete;
171 /// Copy assignment is disabled; the handle is uniquely owned.
172 native_random_access_file&
173 operator=(native_random_access_file const&) = delete;
174
175 /** Asynchronously read at the given offset.
176
177 Calls the backend implementation directly, bypassing virtual
178 dispatch. Otherwise identical to @ref random_access_file::read_some_at.
179
180 @param offset The byte offset to read at.
181 @param buffers The buffers to read into.
182
183 @return An awaitable yielding the error code and the byte count read.
184 */
185 template<capy::MutableBufferSequence MB>
186 4x [[nodiscard]] auto read_some_at(std::uint64_t offset, MB const& buffers)
187 {
188 4x return native_read_at_awaitable<MB>(*this, offset, buffers);
189 }
190
191 /** Asynchronously write at the given offset.
192
193 Calls the backend implementation directly, bypassing virtual
194 dispatch. Otherwise identical to @ref random_access_file::write_some_at.
195
196 @param offset The byte offset to write at.
197 @param buffers The buffer data to write.
198
199 @return An awaitable yielding the error code and the byte count written.
200 */
201 template<capy::ConstBufferSequence CB>
202 3x [[nodiscard]] auto write_some_at(std::uint64_t offset, CB const& buffers)
203 {
204 3x return native_write_at_awaitable<CB>(*this, offset, buffers);
205 }
206 };
207
208 } // namespace boost::corosio
209
210 #endif // BOOST_COROSIO_NATIVE_NATIVE_RANDOM_ACCESS_FILE_HPP
211