include/boost/corosio/native/native_stream_file.hpp

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