include/boost/corosio/native/native_stream_file.hpp

94.6% Lines (35/0/37) 100.0% List of functions (22/0/22)
native_stream_file.hpp
f(x) Functions (22)
Function Calls Lines Blocks
boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::get_impl() :83 4x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::get_impl() :83 4x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::native_read_awaitable(boost::corosio::native_stream_file<boost::corosio::epoll_t{}>&, boost::capy::mutable_buffer) :97 2x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::native_read_awaitable(boost::corosio::native_stream_file<boost::corosio::select_t{}>&, boost::capy::mutable_buffer) :97 2x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_ready() const :105 2x 100.0% 88.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_ready() const :105 2x 100.0% 88.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_resume() const :112 2x 75.0% 57.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_resume() const :112 2x 75.0% 57.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :119 2x 100.0% 77.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :119 2x 100.0% 77.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_write_awaitable<boost::capy::const_buffer>::native_write_awaitable(boost::corosio::native_stream_file<boost::corosio::epoll_t{}>&, boost::capy::const_buffer) :137 2x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::native_write_awaitable(boost::corosio::native_stream_file<boost::corosio::select_t{}>&, boost::capy::const_buffer) :137 2x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_ready() const :145 2x 100.0% 88.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_ready() const :145 2x 100.0% 88.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_resume() const :152 2x 75.0% 57.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_resume() const :152 2x 75.0% 57.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :159 2x 100.0% 77.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :159 2x 100.0% 77.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_stream_file(boost::capy::execution_context&) :173 6x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_stream_file(boost::capy::execution_context&) :173 6x 100.0% 100.0% auto boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :204 2x 100.0% 100.0% auto boost::corosio::native_stream_file<boost::corosio::select_t{}>::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :204 2x 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_STREAM_FILE_HPP
11 #define BOOST_COROSIO_NATIVE_NATIVE_STREAM_FILE_HPP
12
13 #include <boost/corosio/stream_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_stream_file_service.hpp>
20 #endif
21
22 #if BOOST_COROSIO_HAS_IO_URING
23 #include <boost/corosio/native/detail/io_uring/io_uring_stream_file.hpp>
24 #endif
25
26 #if BOOST_COROSIO_HAS_IOCP
27 #include <boost/corosio/native/detail/iocp/win_file_service.hpp>
28 #endif
29 #endif // !BOOST_COROSIO_MRDOCS
30
31 namespace boost::corosio {
32
33 /** A sequential file with devirtualized async I/O operations.
34
35 This class template inherits from @ref stream_file and shadows
36 `read_some` / `write_some` with versions that call the backend
37 implementation directly, allowing the compiler to inline through
38 the entire call chain.
39
40 Non-async operations (`open`, `close`, `size`, `resize`, `seek`,
41 `sync_data`, `sync_all`) remain unchanged and dispatch through
42 the compiled library.
43
44 A `native_stream_file` IS-A `stream_file` and can be passed to
45 any function expecting `stream_file&` or `io_stream&`, in which
46 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 stream_file.
60
61 @par Example
62 @code
63 #include <boost/corosio/native/native_stream_file.hpp>
64
65 native_io_context<epoll> ctx;
66 native_stream_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(
71 capy::mutable_buffer(buf, sizeof(buf)));
72 @endcode
73
74 @see stream_file, epoll_t, iocp_t
75 */
76 template<auto Backend>
77 class native_stream_file : public stream_file
78 {
79 using backend_type = decltype(Backend);
80 using impl_type = typename backend_type::stream_file_type;
81 using service_type = typename backend_type::stream_file_service_type;
82
83 8x impl_type& get_impl() noexcept
84 {
85 8x return *static_cast<impl_type*>(h_.get());
86 }
87
88 template<class MutableBufferSequence>
89 struct native_read_awaitable
90 {
91 native_stream_file& self_;
92 MutableBufferSequence buffers_;
93 std::stop_token token_;
94 mutable std::error_code ec_;
95 mutable std::size_t bytes_transferred_ = 0;
96
97 4x native_read_awaitable(
98 native_stream_file& self,
99 MutableBufferSequence buffers) noexcept
100 4x : self_(self)
101 4x , buffers_(std::move(buffers))
102 {
103 4x }
104
105 4x bool await_ready() const noexcept
106 {
107 // A pre-set ec_ means the initiator failed before
108 // dispatch (e.g. a closed object).
109 4x return static_cast<bool>(ec_) || token_.stop_requested();
110 }
111
112 4x [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
113 {
114 4x if (token_.stop_requested())
115 return {make_error_code(std::errc::operation_canceled), 0};
116 4x return {ec_, bytes_transferred_};
117 }
118
119 4x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
120 -> std::coroutine_handle<>
121 {
122 4x token_ = env->stop_token;
123 12x return self_.get_impl().read_some(
124 12x h, env->executor, buffers_, token_, &ec_, &bytes_transferred_);
125 }
126 };
127
128 template<class ConstBufferSequence>
129 struct native_write_awaitable
130 {
131 native_stream_file& self_;
132 ConstBufferSequence buffers_;
133 std::stop_token token_;
134 mutable std::error_code ec_;
135 mutable std::size_t bytes_transferred_ = 0;
136
137 4x native_write_awaitable(
138 native_stream_file& self,
139 ConstBufferSequence buffers) noexcept
140 4x : self_(self)
141 4x , buffers_(std::move(buffers))
142 {
143 4x }
144
145 4x bool await_ready() const noexcept
146 {
147 // A pre-set ec_ means the initiator failed before
148 // dispatch (e.g. a closed object).
149 4x return static_cast<bool>(ec_) || token_.stop_requested();
150 }
151
152 4x [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
153 {
154 4x if (token_.stop_requested())
155 return {make_error_code(std::errc::operation_canceled), 0};
156 4x return {ec_, bytes_transferred_};
157 }
158
159 4x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
160 -> std::coroutine_handle<>
161 {
162 4x token_ = env->stop_token;
163 12x return self_.get_impl().write_some(
164 12x h, env->executor, buffers_, token_, &ec_, &bytes_transferred_);
165 }
166 };
167
168 public:
169 /** Construct a native stream file from an execution context.
170
171 @param ctx The execution context that will own this file.
172 */
173 12x explicit native_stream_file(capy::execution_context& ctx)
174 12x : io_object(create_handle<service_type>(ctx))
175 {
176 12x }
177
178 /** Construct a native stream 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<std::remove_cvref_t<Ex>, native_stream_file>) &&
184 capy::Executor<Ex>
185 explicit native_stream_file(Ex const& ex) : native_stream_file(ex.context())
186 {
187 }
188
189 /// Move construct.
190 native_stream_file(native_stream_file&&) noexcept = default;
191
192 /// Move assign.
193 native_stream_file& operator=(native_stream_file&&) noexcept = default;
194
195 native_stream_file(native_stream_file const&) = delete;
196 native_stream_file& operator=(native_stream_file const&) = delete;
197
198 /** Asynchronously read data from the file.
199
200 Calls the backend implementation directly, bypassing virtual
201 dispatch. Otherwise identical to @ref io_stream::read_some.
202 */
203 template<capy::MutableBufferSequence MB>
204 4x [[nodiscard]] auto read_some(MB const& buffers)
205 {
206 4x return native_read_awaitable<MB>(*this, buffers);
207 }
208
209 /** Asynchronously write data to the file.
210
211 Calls the backend implementation directly, bypassing virtual
212 dispatch. Otherwise identical to @ref io_stream::write_some.
213 */
214 template<capy::ConstBufferSequence CB>
215 4x [[nodiscard]] auto write_some(CB const& buffers)
216 {
217 4x return native_write_awaitable<CB>(*this, buffers);
218 }
219 };
220
221 } // namespace boost::corosio
222
223 #endif // BOOST_COROSIO_NATIVE_NATIVE_STREAM_FILE_HPP
224