include/boost/corosio/io/io_stream.hpp

100.0% Lines (7/7) 100.0% Functions (4/4)
include/boost/corosio/io/io_stream.hpp
Line Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2026 Steve Gerbino
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_IO_IO_STREAM_HPP
12 #define BOOST_COROSIO_IO_IO_STREAM_HPP
13
14 #include <boost/corosio/detail/config.hpp>
15 #include <boost/corosio/io/io_read_stream.hpp>
16 #include <boost/corosio/io/io_write_stream.hpp>
17 #include <boost/corosio/io_buffer_param.hpp>
18 #include <boost/capy/ex/executor_ref.hpp>
19
20 #include <coroutine>
21 #include <cstddef>
22 #include <stop_token>
23 #include <system_error>
24
25 namespace boost::corosio {
26
27 /** Platform stream with read/write operations.
28
29 Combines @ref io_read_stream and @ref io_write_stream into
30 a single bidirectional stream. The `read_some` and `write_some`
31 operations are inherited from the base classes and dispatch
32 through `do_read_some` / `do_write_some`, which this class
33 implements by forwarding to the platform `implementation`.
34
35 The implementation hierarchy stays linear (no diamond):
36 `io_object::implementation` -> `io_stream::implementation`
37 -> `tcp_socket::implementation` -> backend impl.
38
39 @par Semantics
40 Concrete classes wrap direct platform I/O completed by the kernel.
41 Functions taking `io_stream&` signal "platform implementation
42 required" - use this when you need actual kernel I/O rather than
43 a mock or test double.
44
45 For generic stream algorithms that work with test mocks,
46 use `template<capy::Stream S>` instead of `io_stream&`.
47
48 @par Thread Safety
49 Distinct objects: Safe.
50 Shared objects: Unsafe. All calls to a single stream must be made
51 from the same implicit or explicit serialization context.
52
53 @par Example
54 @code
55 // Read until buffer full or EOF
56 capy::task<> read_all( io_stream& stream, std::span<char> buf )
57 {
58 std::size_t total = 0;
59 while( total < buf.size() )
60 {
61 auto [ec, n] = co_await stream.read_some(
62 capy::buffer( buf.data() + total, buf.size() - total ) );
63 if( ec == capy::cond::eof )
64 break;
65 if( ec.failed() )
66 capy::detail::throw_system_error( ec );
67 total += n;
68 }
69 }
70 @endcode
71
72 @see io_read_stream, io_write_stream, tcp_socket
73 */
74 class BOOST_COROSIO_DECL io_stream
75 : public io_read_stream
76 , public io_write_stream
77 {
78 public:
79 /** Platform-specific stream implementation interface.
80
81 Derived classes implement this interface to provide kernel-level
82 read and write operations for each supported platform (IOCP,
83 epoll, kqueue, io_uring).
84 */
85 struct implementation : io_object::implementation
86 {
87 /// Initiate platform read operation.
88 virtual std::coroutine_handle<> read_some(
89 std::coroutine_handle<>,
90 capy::executor_ref,
91 io_buffer_param,
92 std::stop_token,
93 std::error_code*,
94 std::size_t*) = 0;
95
96 /// Initiate platform write operation.
97 virtual std::coroutine_handle<> write_some(
98 std::coroutine_handle<>,
99 capy::executor_ref,
100 io_buffer_param,
101 std::stop_token,
102 std::error_code*,
103 std::size_t*) = 0;
104 };
105
106 protected:
107 16642 io_stream() noexcept = default;
108
109 /// Construct stream from a handle.
110 explicit io_stream(handle h) noexcept : io_object(std::move(h)) {}
111
112 /// Dispatch read through implementation vtable.
113 199835 std::coroutine_handle<> do_read_some(
114 std::coroutine_handle<> h,
115 capy::executor_ref ex,
116 io_buffer_param buffers,
117 std::stop_token token,
118 std::error_code* ec,
119 std::size_t* bytes) override
120 {
121 199835 return get().read_some(h, ex, buffers, std::move(token), ec, bytes);
122 }
123
124 /// Dispatch write through implementation vtable.
125 199473 std::coroutine_handle<> do_write_some(
126 std::coroutine_handle<> h,
127 capy::executor_ref ex,
128 io_buffer_param buffers,
129 std::stop_token token,
130 std::error_code* ec,
131 std::size_t* bytes) override
132 {
133 199473 return get().write_some(h, ex, buffers, std::move(token), ec, bytes);
134 }
135
136 private:
137 /// Return implementation downcasted to stream interface.
138 399308 implementation& get() const noexcept
139 {
140 399308 return *static_cast<implementation*>(h_.get());
141 }
142 };
143
144 } // namespace boost::corosio
145
146 #endif
147