TLA Line data 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 HIT 8 : impl_type& get_impl() noexcept
76 : {
77 8 : 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 6 : native_read_awaitable(
88 : native_stream_file& self, MutableBufferSequence buffers) noexcept
89 6 : : self_(self)
90 6 : , buffers_(std::move(buffers))
91 : {
92 6 : }
93 :
94 : std::coroutine_handle<>
95 4 : dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
96 : {
97 12 : return self_.get_impl().read_some(
98 12 : 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 6 : native_write_awaitable(
110 : native_stream_file& self, ConstBufferSequence buffers) noexcept
111 6 : : self_(self)
112 6 : , buffers_(std::move(buffers))
113 : {
114 6 : }
115 :
116 : std::coroutine_handle<>
117 4 : dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
118 : {
119 12 : return self_.get_impl().write_some(
120 12 : 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 16 : explicit native_stream_file(capy::execution_context& ctx)
130 16 : : io_object(handle(ctx, ctx.use_service<service_type>()))
131 : {
132 16 : }
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 6 : [[nodiscard]] auto read_some(MB const& buffers)
167 : {
168 6 : 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 6 : [[nodiscard]] auto write_some(CB const& buffers)
182 : {
183 6 : return native_write_awaitable<CB>(*this, buffers);
184 : }
185 : };
186 :
187 : } // namespace boost::corosio
188 :
189 : #endif // BOOST_COROSIO_NATIVE_NATIVE_STREAM_FILE_HPP
|