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