TLA Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2026 Steve Gerbino
4 : // Copyright (c) 2026 Michael Vandeberg
5 : //
6 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 : //
9 : // Official repository: https://github.com/cppalliance/corosio
10 : //
11 :
12 : #ifndef BOOST_COROSIO_IO_IO_STREAM_HPP
13 : #define BOOST_COROSIO_IO_IO_STREAM_HPP
14 :
15 : #include <boost/corosio/detail/config.hpp>
16 : #include <boost/corosio/io/io_read_stream.hpp>
17 : #include <boost/corosio/io/io_write_stream.hpp>
18 : #include <boost/corosio/detail/buffer_param.hpp>
19 : #include <boost/capy/ex/executor_ref.hpp>
20 :
21 : #include <coroutine>
22 : #include <cstddef>
23 : #include <stop_token>
24 : #include <system_error>
25 :
26 : namespace boost::corosio {
27 :
28 : /** Reads and writes bytes through a platform I/O backend.
29 :
30 : Combines @ref io_read_stream and @ref io_write_stream into
31 : a single bidirectional stream. The `read_some` and `write_some`
32 : operations are inherited from the base classes and dispatch through
33 : `do_read_some` / `do_write_some`. This class implements those by
34 : forwarding to the platform `implementation`.
35 :
36 : The implementation hierarchy stays linear (no diamond):
37 : `io_object::implementation` -> `io_stream::implementation`
38 : -> `tcp_socket::implementation` -> backend impl.
39 :
40 : @par Semantics
41 : Concrete classes wrap direct platform I/O completed by the kernel.
42 : Functions taking `io_stream&` signal that platform implementation
43 : is required. Use this when you need actual kernel I/O rather than
44 : a mock or test double.
45 :
46 : For generic stream algorithms that work with test mocks,
47 : use `template<capy::Stream S>` instead of `io_stream&`.
48 :
49 : @par Thread Safety
50 : Distinct objects: Safe.
51 : Shared objects: Unsafe. All calls to a single stream must be made
52 : from the same implicit or explicit serialization context.
53 :
54 : @par Example
55 : @par !example io_stream
56 :
57 : @see io_read_stream, io_write_stream, tcp_socket
58 : */
59 : class BOOST_COROSIO_DECL io_stream
60 : : public io_read_stream
61 : , public io_write_stream
62 : {
63 : public:
64 : /** Declares the read and write operations a platform backend
65 : must implement.
66 :
67 : Derived classes implement this interface to provide kernel-level
68 : read and write operations for each supported platform (IOCP,
69 : epoll, kqueue, io_uring).
70 : */
71 : struct implementation : io_object::implementation
72 : {
73 : /** Initiate platform read operation.
74 :
75 : @param h Coroutine handle to resume on completion.
76 : @param ex Executor for dispatching the completion.
77 : @param buffers Target buffer sequence.
78 : @param token Stop token for cancellation.
79 : @param ec Output error code.
80 : @param bytes Output bytes transferred.
81 :
82 : @return Coroutine handle to resume immediately.
83 : */
84 : virtual std::coroutine_handle<> read_some(
85 : std::coroutine_handle<> h,
86 : capy::executor_ref ex,
87 : buffer_param buffers,
88 : std::stop_token token,
89 : std::error_code* ec,
90 : std::size_t* bytes) = 0;
91 :
92 : /** Initiate platform write operation.
93 :
94 : @param h Coroutine handle to resume on completion.
95 : @param ex Executor for dispatching the completion.
96 : @param buffers Source buffer sequence.
97 : @param token Stop token for cancellation.
98 : @param ec Output error code.
99 : @param bytes Output bytes transferred.
100 :
101 : @return Coroutine handle to resume immediately.
102 : */
103 : virtual std::coroutine_handle<> write_some(
104 : std::coroutine_handle<> h,
105 : capy::executor_ref ex,
106 : buffer_param buffers,
107 : std::stop_token token,
108 : std::error_code* ec,
109 : std::size_t* bytes) = 0;
110 : };
111 :
112 : protected:
113 : /// Default construct; the handle is supplied through @ref io_object.
114 HIT 10651 : io_stream() noexcept = default;
115 :
116 : /// Construct stream from a handle.
117 : explicit io_stream(handle h) noexcept : io_object(std::move(h)) {}
118 :
119 : /** Dispatch read through implementation vtable.
120 :
121 : @param h Coroutine handle to resume on completion.
122 : @param ex Executor for dispatching the completion.
123 : @param buffers Target buffer sequence.
124 : @param token Stop token for cancellation.
125 : @param ec Output error code.
126 : @param bytes Output bytes transferred.
127 :
128 : @return Coroutine handle to resume immediately.
129 : */
130 205597 : std::coroutine_handle<> do_read_some(
131 : std::coroutine_handle<> h,
132 : capy::executor_ref ex,
133 : buffer_param buffers,
134 : std::stop_token token,
135 : std::error_code* ec,
136 : std::size_t* bytes) override
137 : {
138 205597 : return get().read_some(h, ex, buffers, std::move(token), ec, bytes);
139 : }
140 :
141 : /** Dispatch write through implementation vtable.
142 :
143 : @param h Coroutine handle to resume on completion.
144 : @param ex Executor for dispatching the completion.
145 : @param buffers Source buffer sequence.
146 : @param token Stop token for cancellation.
147 : @param ec Output error code.
148 : @param bytes Output bytes transferred.
149 :
150 : @return Coroutine handle to resume immediately.
151 : */
152 204828 : std::coroutine_handle<> do_write_some(
153 : std::coroutine_handle<> h,
154 : capy::executor_ref ex,
155 : buffer_param buffers,
156 : std::stop_token token,
157 : std::error_code* ec,
158 : std::size_t* bytes) override
159 : {
160 204828 : return get().write_some(h, ex, buffers, std::move(token), ec, bytes);
161 : }
162 :
163 : private:
164 : /// Return implementation downcasted to stream interface.
165 410425 : implementation& get() const noexcept
166 : {
167 410425 : return *static_cast<implementation*>(h_.get());
168 : }
169 : };
170 :
171 : } // namespace boost::corosio
172 :
173 : #endif
|