include/boost/corosio/io/io_write_stream.hpp

94.1% Lines (16/17) 100.0% Functions (14/14)
include/boost/corosio/io/io_write_stream.hpp
Line Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/corosio
8 //
9
10 #ifndef BOOST_COROSIO_IO_IO_WRITE_STREAM_HPP
11 #define BOOST_COROSIO_IO_IO_WRITE_STREAM_HPP
12
13 #include <boost/corosio/detail/config.hpp>
14 #include <boost/corosio/io/io_object.hpp>
15 #include <boost/corosio/io_buffer_param.hpp>
16 #include <boost/capy/io_result.hpp>
17 #include <boost/capy/ex/executor_ref.hpp>
18 #include <boost/capy/ex/io_env.hpp>
19
20 #include <coroutine>
21 #include <cstddef>
22 #include <stop_token>
23 #include <system_error>
24
25 namespace boost::corosio {
26
27 /** Abstract base for streams that support async writes.
28
29 Provides the `write_some` operation via a pure virtual
30 `do_write_some` dispatch point. Concrete classes override
31 `do_write_some` to route through their implementation.
32
33 Uses virtual inheritance from @ref io_object so that
34 @ref io_stream can combine this with @ref io_read_stream
35 without duplicating the `io_object` base.
36
37 @par Thread Safety
38 Distinct objects: Safe.
39 Shared objects: Unsafe.
40
41 @see io_read_stream, io_stream, io_object
42 */
43 class BOOST_COROSIO_DECL io_write_stream : virtual public io_object
44 {
45 protected:
46 /// Awaitable for async write operations.
47 template<class ConstBufferSequence>
48 struct write_some_awaitable
49 {
50 io_write_stream& ios_;
51 ConstBufferSequence buffers_;
52 std::stop_token token_;
53 mutable std::error_code ec_;
54 mutable std::size_t bytes_transferred_ = 0;
55
56 196223 write_some_awaitable(
57 io_write_stream& ios, ConstBufferSequence buffers) noexcept
58 196223 : ios_(ios)
59 196223 , buffers_(std::move(buffers))
60 {
61 196223 }
62
63 196223 bool await_ready() const noexcept
64 {
65 196223 return token_.stop_requested();
66 }
67
68 196223 capy::io_result<std::size_t> await_resume() const noexcept
69 {
70 196223 if (token_.stop_requested())
71 return {make_error_code(std::errc::operation_canceled), 0};
72 196223 return {ec_, bytes_transferred_};
73 }
74
75 196223 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
76 -> std::coroutine_handle<>
77 {
78 196223 token_ = env->stop_token;
79 392446 return ios_.do_write_some(
80 588669 h, env->executor, buffers_, token_, &ec_, &bytes_transferred_);
81 }
82 };
83
84 /** Dispatch a write through the concrete implementation.
85
86 @param h Coroutine handle to resume on completion.
87 @param ex Executor for dispatching the completion.
88 @param buffers Source buffer sequence.
89 @param token Stop token for cancellation.
90 @param ec Output error code.
91 @param bytes Output bytes transferred.
92
93 @return Coroutine handle to resume immediately.
94 */
95 virtual std::coroutine_handle<> do_write_some(
96 std::coroutine_handle<>,
97 capy::executor_ref,
98 io_buffer_param,
99 std::stop_token,
100 std::error_code*,
101 std::size_t*) = 0;
102
103 16083 io_write_stream() noexcept = default;
104
105 /// Construct from a handle.
106 explicit io_write_stream(handle h) noexcept : io_object(std::move(h)) {}
107
108 public:
109 /** Asynchronously write data to the stream.
110
111 Suspends the calling coroutine and initiates a kernel-level
112 write. The coroutine resumes when at least one byte is written,
113 an error occurs, or the operation is cancelled.
114
115 @param buffers The buffer sequence containing data to write.
116
117 @return An awaitable yielding `(error_code, std::size_t)`.
118
119 @see io_stream::read_some
120 */
121 template<capy::ConstBufferSequence CB>
122 196223 auto write_some(CB const& buffers)
123 {
124 196223 return write_some_awaitable<CB>(*this, buffers);
125 }
126 };
127
128 } // namespace boost::corosio
129
130 #endif
131