TLA Line data 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 HIT 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 MIS 0 : return {make_error_code(std::errc::operation_canceled), 0};
72 HIT 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
|