1//
2// buffered_write_stream.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP
12#define BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <boost/asio/detail/config.hpp>
19#include <cstddef>
20#include <boost/asio/buffered_write_stream_fwd.hpp>
21#include <boost/asio/buffer.hpp>
22#include <boost/asio/completion_condition.hpp>
23#include <boost/asio/detail/bind_handler.hpp>
24#include <boost/asio/detail/buffered_stream_storage.hpp>
25#include <boost/asio/detail/noncopyable.hpp>
26#include <boost/asio/detail/type_traits.hpp>
27#include <boost/asio/error.hpp>
28#include <boost/asio/write.hpp>
29
30#include <boost/asio/detail/push_options.hpp>
31
32namespace boost {
33namespace asio {
34namespace detail {
35
36template <typename> class initiate_async_buffered_flush;
37template <typename> class initiate_async_buffered_write_some;
38
39} // namespace detail
40
41/// Adds buffering to the write-related operations of a stream.
42/**
43 * The buffered_write_stream class template can be used to add buffering to the
44 * synchronous and asynchronous write operations of a stream.
45 *
46 * @par Thread Safety
47 * @e Distinct @e objects: Safe.@n
48 * @e Shared @e objects: Unsafe.
49 *
50 * @par Concepts:
51 * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
52 */
53template <typename Stream>
54class buffered_write_stream
55 : private noncopyable
56{
57public:
58 /// The type of the next layer.
59 typedef remove_reference_t<Stream> next_layer_type;
60
61 /// The type of the lowest layer.
62 typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
63
64 /// The type of the executor associated with the object.
65 typedef typename lowest_layer_type::executor_type executor_type;
66
67#if defined(GENERATING_DOCUMENTATION)
68 /// The default buffer size.
69 static const std::size_t default_buffer_size = implementation_defined;
70#else
71 BOOST_ASIO_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
72#endif
73
74 /// Construct, passing the specified argument to initialise the next layer.
75 template <typename Arg>
76 explicit buffered_write_stream(Arg&& a)
77 : next_layer_(static_cast<Arg&&>(a)),
78 storage_(default_buffer_size)
79 {
80 }
81
82 /// Construct, passing the specified argument to initialise the next layer.
83 template <typename Arg>
84 buffered_write_stream(Arg&& a,
85 std::size_t buffer_size)
86 : next_layer_(static_cast<Arg&&>(a)),
87 storage_(buffer_size)
88 {
89 }
90
91 /// Get a reference to the next layer.
92 next_layer_type& next_layer()
93 {
94 return next_layer_;
95 }
96
97 /// Get a reference to the lowest layer.
98 lowest_layer_type& lowest_layer()
99 {
100 return next_layer_.lowest_layer();
101 }
102
103 /// Get a const reference to the lowest layer.
104 const lowest_layer_type& lowest_layer() const
105 {
106 return next_layer_.lowest_layer();
107 }
108
109 /// Get the executor associated with the object.
110 executor_type get_executor() noexcept
111 {
112 return next_layer_.lowest_layer().get_executor();
113 }
114
115 /// Close the stream.
116 void close()
117 {
118 next_layer_.close();
119 }
120
121 /// Close the stream.
122 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
123 {
124 next_layer_.close(ec);
125 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
126 }
127
128 /// Flush all data from the buffer to the next layer. Returns the number of
129 /// bytes written to the next layer on the last write operation. Throws an
130 /// exception on failure.
131 std::size_t flush();
132
133 /// Flush all data from the buffer to the next layer. Returns the number of
134 /// bytes written to the next layer on the last write operation, or 0 if an
135 /// error occurred.
136 std::size_t flush(boost::system::error_code& ec);
137
138 /// Start an asynchronous flush.
139 /**
140 * @par Completion Signature
141 * @code void(boost::system::error_code, std::size_t) @endcode
142 */
143 template <
144 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
145 std::size_t)) WriteHandler = default_completion_token_t<executor_type>>
146 auto async_flush(
147 WriteHandler&& handler = default_completion_token_t<executor_type>())
148 -> decltype(
149 async_initiate<WriteHandler,
150 void (boost::system::error_code, std::size_t)>(
151 declval<detail::initiate_async_buffered_flush<Stream>>(),
152 handler, declval<detail::buffered_stream_storage*>()));
153
154 /// Write the given data to the stream. Returns the number of bytes written.
155 /// Throws an exception on failure.
156 template <typename ConstBufferSequence>
157 std::size_t write_some(const ConstBufferSequence& buffers);
158
159 /// Write the given data to the stream. Returns the number of bytes written,
160 /// or 0 if an error occurred and the error handler did not throw.
161 template <typename ConstBufferSequence>
162 std::size_t write_some(const ConstBufferSequence& buffers,
163 boost::system::error_code& ec);
164
165 /// Start an asynchronous write. The data being written must be valid for the
166 /// lifetime of the asynchronous operation.
167 /**
168 * @par Completion Signature
169 * @code void(boost::system::error_code, std::size_t) @endcode
170 */
171 template <typename ConstBufferSequence,
172 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
173 std::size_t)) WriteHandler = default_completion_token_t<executor_type>>
174 auto async_write_some(const ConstBufferSequence& buffers,
175 WriteHandler&& handler = default_completion_token_t<executor_type>())
176 -> decltype(
177 async_initiate<WriteHandler,
178 void (boost::system::error_code, std::size_t)>(
179 declval<detail::initiate_async_buffered_write_some<Stream>>(),
180 handler, declval<detail::buffered_stream_storage*>(), buffers));
181
182 /// Read some data from the stream. Returns the number of bytes read. Throws
183 /// an exception on failure.
184 template <typename MutableBufferSequence>
185 std::size_t read_some(const MutableBufferSequence& buffers)
186 {
187 return next_layer_.read_some(buffers);
188 }
189
190 /// Read some data from the stream. Returns the number of bytes read or 0 if
191 /// an error occurred.
192 template <typename MutableBufferSequence>
193 std::size_t read_some(const MutableBufferSequence& buffers,
194 boost::system::error_code& ec)
195 {
196 return next_layer_.read_some(buffers, ec);
197 }
198
199 /// Start an asynchronous read. The buffer into which the data will be read
200 /// must be valid for the lifetime of the asynchronous operation.
201 /**
202 * @par Completion Signature
203 * @code void(boost::system::error_code, std::size_t) @endcode
204 */
205 template <typename MutableBufferSequence,
206 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
207 std::size_t)) ReadHandler = default_completion_token_t<executor_type>>
208 auto async_read_some(const MutableBufferSequence& buffers,
209 ReadHandler&& handler = default_completion_token_t<executor_type>())
210 -> decltype(
211 declval<conditional_t<true, Stream&, ReadHandler>>().async_read_some(
212 buffers, static_cast<ReadHandler&&>(handler)))
213 {
214 return next_layer_.async_read_some(buffers,
215 static_cast<ReadHandler&&>(handler));
216 }
217
218 /// Peek at the incoming data on the stream. Returns the number of bytes read.
219 /// Throws an exception on failure.
220 template <typename MutableBufferSequence>
221 std::size_t peek(const MutableBufferSequence& buffers)
222 {
223 return next_layer_.peek(buffers);
224 }
225
226 /// Peek at the incoming data on the stream. Returns the number of bytes read,
227 /// or 0 if an error occurred.
228 template <typename MutableBufferSequence>
229 std::size_t peek(const MutableBufferSequence& buffers,
230 boost::system::error_code& ec)
231 {
232 return next_layer_.peek(buffers, ec);
233 }
234
235 /// Determine the amount of data that may be read without blocking.
236 std::size_t in_avail()
237 {
238 return next_layer_.in_avail();
239 }
240
241 /// Determine the amount of data that may be read without blocking.
242 std::size_t in_avail(boost::system::error_code& ec)
243 {
244 return next_layer_.in_avail(ec);
245 }
246
247private:
248 /// Copy data into the internal buffer from the specified source buffer.
249 /// Returns the number of bytes copied.
250 template <typename ConstBufferSequence>
251 std::size_t copy(const ConstBufferSequence& buffers);
252
253 /// The next layer.
254 Stream next_layer_;
255
256 // The data in the buffer.
257 detail::buffered_stream_storage storage_;
258};
259
260} // namespace asio
261} // namespace boost
262
263#include <boost/asio/detail/pop_options.hpp>
264
265#include <boost/asio/impl/buffered_write_stream.hpp>
266
267#endif // BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP
268

source code of boost/libs/asio/include/boost/asio/buffered_write_stream.hpp