include/boost/corosio/native/native_stream_file.hpp

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