include/boost/corosio/native/native_stream_file.hpp

100.0% Lines (23 / 23) 100.0% Functions (14 / 14)
native_stream_file.hpp
f(x) Functions (14)
Function Calls Lines Blocks
boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::get_impl() :75 4x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::get_impl() :75 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) :87 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) :87 3x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :95 2x 100.0% 75.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :95 2x 100.0% 75.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) :109 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) :109 3x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_write_awaitable<boost::capy::const_buffer>::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :117 2x 100.0% 75.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :117 2x 100.0% 75.0% boost::corosio::native_stream_file<boost::corosio::epoll_t{}>::native_stream_file(boost::capy::execution_context&) :129 8x 100.0% 100.0% boost::corosio::native_stream_file<boost::corosio::select_t{}>::native_stream_file(boost::capy::execution_context&) :129 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&) :166 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&) :166 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 #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_stream_file_service.hpp>
22 #endif
23
24 #if BOOST_COROSIO_HAS_URING
25 #include <boost/corosio/native/detail/uring/uring_stream_file.hpp>
26 #endif
27
28 #if BOOST_COROSIO_HAS_IOCP
29 #include <boost/corosio/native/detail/iocp/win_file_service.hpp>
30 #endif
31 #endif // !BOOST_COROSIO_MRDOCS
32
33 namespace boost::corosio {
34
35 /** Reads and writes a file sequentially, calling the backend directly.
36
37 This class template inherits from @ref stream_file. It shadows
38 `read_some` / `write_some` with versions that call the backend
39 implementation directly. The compiler can then inline through the
40 entire call chain.
41
42 Non-async operations (`open`, `close`, `size`, `resize`, `seek`,
43 `sync_data`, `sync_all`) remain unchanged and dispatch through
44 the compiled library.
45
46 A `native_stream_file` IS-A `stream_file` and can be passed to
47 any function expecting `stream_file&` or `io_stream&`, in which
48 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 stream_file.
62
63 @par Example
64 @par !example native_stream_file
65
66 @see stream_file, epoll_t, iocp_t
67 */
68 template<auto Backend>
69 class native_stream_file : public stream_file
70 {
71 using backend_type = decltype(Backend);
72 using impl_type = typename backend_type::stream_file_type;
73 using service_type = typename backend_type::stream_file_service_type;
74
75 8x impl_type& get_impl() noexcept
76 {
77 8x return *static_cast<impl_type*>(h_.get());
78 }
79
80 template<class MutableBufferSequence>
81 struct native_read_awaitable
82 : detail::bytes_op_base<native_read_awaitable<MutableBufferSequence>>
83 {
84 native_stream_file& self_;
85 MutableBufferSequence buffers_;
86
87 6x native_read_awaitable(
88 native_stream_file& self, MutableBufferSequence buffers) noexcept
89 6x : self_(self)
90 6x , buffers_(std::move(buffers))
91 {
92 6x }
93
94 std::coroutine_handle<>
95 4x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
96 {
97 12x return self_.get_impl().read_some(
98 12x h, ex, buffers_, this->token_, &this->ec_, &this->bytes_);
99 }
100 };
101
102 template<class ConstBufferSequence>
103 struct native_write_awaitable
104 : detail::bytes_op_base<native_write_awaitable<ConstBufferSequence>>
105 {
106 native_stream_file& self_;
107 ConstBufferSequence buffers_;
108
109 6x native_write_awaitable(
110 native_stream_file& self, ConstBufferSequence buffers) noexcept
111 6x : self_(self)
112 6x , buffers_(std::move(buffers))
113 {
114 6x }
115
116 std::coroutine_handle<>
117 4x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
118 {
119 12x return self_.get_impl().write_some(
120 12x h, ex, buffers_, this->token_, &this->ec_, &this->bytes_);
121 }
122 };
123
124 public:
125 /** Construct a native stream file from an execution context.
126
127 @param ctx The execution context that owns this file.
128 */
129 16x explicit native_stream_file(capy::execution_context& ctx)
130 16x : io_object(create_handle<service_type>(ctx))
131 {
132 16x }
133
134 /** Construct a native stream file from an executor.
135
136 @param ex The executor whose context owns this file.
137 */
138 template<class Ex>
139 requires(!std::same_as<std::remove_cvref_t<Ex>, native_stream_file>) &&
140 capy::Executor<Ex>
141 explicit native_stream_file(Ex const& ex) : native_stream_file(ex.context())
142 {
143 }
144
145 /// Move construct.
146 native_stream_file(native_stream_file&&) noexcept = default;
147
148 /// Move assign.
149 native_stream_file& operator=(native_stream_file&&) noexcept = default;
150
151 /// Copy construction is disabled; the handle is uniquely owned.
152 native_stream_file(native_stream_file const&) = delete;
153 /// Copy assignment is disabled; the handle is uniquely owned.
154 native_stream_file& operator=(native_stream_file const&) = delete;
155
156 /** Asynchronously read data from the file.
157
158 Calls the backend implementation directly, bypassing virtual
159 dispatch. Otherwise identical to @ref io_stream::read_some.
160
161 @param buffers The buffers to read into.
162
163 @return An awaitable yielding the error code and the byte count read.
164 */
165 template<capy::MutableBufferSequence MB>
166 6x [[nodiscard]] auto read_some(MB const& buffers)
167 {
168 6x return native_read_awaitable<MB>(*this, buffers);
169 }
170
171 /** Asynchronously write data to the file.
172
173 Calls the backend implementation directly, bypassing virtual
174 dispatch. Otherwise identical to @ref io_stream::write_some.
175
176 @param buffers The buffer data to write.
177
178 @return An awaitable yielding the error code and the byte count written.
179 */
180 template<capy::ConstBufferSequence CB>
181 6x [[nodiscard]] auto write_some(CB const& buffers)
182 {
183 6x return native_write_awaitable<CB>(*this, buffers);
184 }
185 };
186
187 } // namespace boost::corosio
188
189 #endif // BOOST_COROSIO_NATIVE_NATIVE_STREAM_FILE_HPP
190