2 // impl/buffered_write_stream.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP
12 #define BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/handler_alloc_helpers.hpp>
19 #include <boost/asio/detail/handler_cont_helpers.hpp>
20 #include <boost/asio/detail/handler_invoke_helpers.hpp>
21 #include <boost/asio/detail/handler_type_requirements.hpp>
23 #include <boost/asio/detail/push_options.hpp>
28 template <typename Stream>
29 std::size_t buffered_write_stream<Stream>::flush()
31 std::size_t bytes_written = write(next_layer_,
32 buffer(storage_.data(), storage_.size()));
33 storage_.consume(bytes_written);
37 template <typename Stream>
38 std::size_t buffered_write_stream<Stream>::flush(boost::system::error_code& ec)
40 std::size_t bytes_written = write(next_layer_,
41 buffer(storage_.data(), storage_.size()),
43 storage_.consume(bytes_written);
49 template <typename WriteHandler>
50 class buffered_flush_handler
53 buffered_flush_handler(detail::buffered_stream_storage& storage,
54 WriteHandler& handler)
60 #if defined(BOOST_ASIO_HAS_MOVE)
61 buffered_flush_handler(const buffered_flush_handler& other)
62 : storage_(other.storage_),
63 handler_(other.handler_)
67 buffered_flush_handler(buffered_flush_handler&& other)
68 : storage_(other.storage_),
69 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
72 #endif // defined(BOOST_ASIO_HAS_MOVE)
74 void operator()(const boost::system::error_code& ec,
75 const std::size_t bytes_written)
77 storage_.consume(bytes_written);
78 handler_(ec, bytes_written);
82 detail::buffered_stream_storage& storage_;
83 WriteHandler handler_;
86 template <typename WriteHandler>
87 inline void* asio_handler_allocate(std::size_t size,
88 buffered_flush_handler<WriteHandler>* this_handler)
90 return boost_asio_handler_alloc_helpers::allocate(
91 size, this_handler->handler_);
94 template <typename WriteHandler>
95 inline void asio_handler_deallocate(void* pointer, std::size_t size,
96 buffered_flush_handler<WriteHandler>* this_handler)
98 boost_asio_handler_alloc_helpers::deallocate(
99 pointer, size, this_handler->handler_);
102 template <typename WriteHandler>
103 inline bool asio_handler_is_continuation(
104 buffered_flush_handler<WriteHandler>* this_handler)
106 return boost_asio_handler_cont_helpers::is_continuation(
107 this_handler->handler_);
110 template <typename Function, typename WriteHandler>
111 inline void asio_handler_invoke(Function& function,
112 buffered_flush_handler<WriteHandler>* this_handler)
114 boost_asio_handler_invoke_helpers::invoke(
115 function, this_handler->handler_);
118 template <typename Function, typename WriteHandler>
119 inline void asio_handler_invoke(const Function& function,
120 buffered_flush_handler<WriteHandler>* this_handler)
122 boost_asio_handler_invoke_helpers::invoke(
123 function, this_handler->handler_);
127 template <typename Stream>
128 template <typename WriteHandler>
129 BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
130 void (boost::system::error_code, std::size_t))
131 buffered_write_stream<Stream>::async_flush(
132 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
134 // If you get an error on the following line it means that your handler does
135 // not meet the documented type requirements for a WriteHandler.
136 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
138 detail::async_result_init<
139 WriteHandler, void (boost::system::error_code, std::size_t)> init(
140 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
142 async_write(next_layer_, buffer(storage_.data(), storage_.size()),
143 detail::buffered_flush_handler<BOOST_ASIO_HANDLER_TYPE(
144 WriteHandler, void (boost::system::error_code, std::size_t))>(
145 storage_, init.handler));
147 return init.result.get();
150 template <typename Stream>
151 template <typename ConstBufferSequence>
152 std::size_t buffered_write_stream<Stream>::write_some(
153 const ConstBufferSequence& buffers)
155 if (boost::asio::buffer_size(buffers) == 0)
158 if (storage_.size() == storage_.capacity())
161 return this->copy(buffers);
164 template <typename Stream>
165 template <typename ConstBufferSequence>
166 std::size_t buffered_write_stream<Stream>::write_some(
167 const ConstBufferSequence& buffers, boost::system::error_code& ec)
169 ec = boost::system::error_code();
171 if (boost::asio::buffer_size(buffers) == 0)
174 if (storage_.size() == storage_.capacity() && !flush(ec))
177 return this->copy(buffers);
182 template <typename ConstBufferSequence, typename WriteHandler>
183 class buffered_write_some_handler
186 buffered_write_some_handler(detail::buffered_stream_storage& storage,
187 const ConstBufferSequence& buffers, WriteHandler& handler)
194 #if defined(BOOST_ASIO_HAS_MOVE)
195 buffered_write_some_handler(const buffered_write_some_handler& other)
196 : storage_(other.storage_),
197 buffers_(other.buffers_),
198 handler_(other.handler_)
202 buffered_write_some_handler(buffered_write_some_handler&& other)
203 : storage_(other.storage_),
204 buffers_(other.buffers_),
205 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
208 #endif // defined(BOOST_ASIO_HAS_MOVE)
210 void operator()(const boost::system::error_code& ec, std::size_t)
214 const std::size_t length = 0;
215 handler_(ec, length);
219 std::size_t orig_size = storage_.size();
220 std::size_t space_avail = storage_.capacity() - orig_size;
221 std::size_t bytes_avail = boost::asio::buffer_size(buffers_);
222 std::size_t length = bytes_avail < space_avail
223 ? bytes_avail : space_avail;
224 storage_.resize(orig_size + length);
225 const std::size_t bytes_copied = boost::asio::buffer_copy(
226 storage_.data() + orig_size, buffers_, length);
227 handler_(ec, bytes_copied);
232 detail::buffered_stream_storage& storage_;
233 ConstBufferSequence buffers_;
234 WriteHandler handler_;
237 template <typename ConstBufferSequence, typename WriteHandler>
238 inline void* asio_handler_allocate(std::size_t size,
239 buffered_write_some_handler<
240 ConstBufferSequence, WriteHandler>* this_handler)
242 return boost_asio_handler_alloc_helpers::allocate(
243 size, this_handler->handler_);
246 template <typename ConstBufferSequence, typename WriteHandler>
247 inline void asio_handler_deallocate(void* pointer, std::size_t size,
248 buffered_write_some_handler<
249 ConstBufferSequence, WriteHandler>* this_handler)
251 boost_asio_handler_alloc_helpers::deallocate(
252 pointer, size, this_handler->handler_);
255 template <typename ConstBufferSequence, typename WriteHandler>
256 inline bool asio_handler_is_continuation(
257 buffered_write_some_handler<
258 ConstBufferSequence, WriteHandler>* this_handler)
260 return boost_asio_handler_cont_helpers::is_continuation(
261 this_handler->handler_);
264 template <typename Function, typename ConstBufferSequence,
265 typename WriteHandler>
266 inline void asio_handler_invoke(Function& function,
267 buffered_write_some_handler<
268 ConstBufferSequence, WriteHandler>* this_handler)
270 boost_asio_handler_invoke_helpers::invoke(
271 function, this_handler->handler_);
274 template <typename Function, typename ConstBufferSequence,
275 typename WriteHandler>
276 inline void asio_handler_invoke(const Function& function,
277 buffered_write_some_handler<
278 ConstBufferSequence, WriteHandler>* this_handler)
280 boost_asio_handler_invoke_helpers::invoke(
281 function, this_handler->handler_);
283 } // namespace detail
285 template <typename Stream>
286 template <typename ConstBufferSequence, typename WriteHandler>
287 BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
288 void (boost::system::error_code, std::size_t))
289 buffered_write_stream<Stream>::async_write_some(
290 const ConstBufferSequence& buffers,
291 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
293 // If you get an error on the following line it means that your handler does
294 // not meet the documented type requirements for a WriteHandler.
295 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
297 detail::async_result_init<
298 WriteHandler, void (boost::system::error_code, std::size_t)> init(
299 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
301 if (boost::asio::buffer_size(buffers) == 0
302 || storage_.size() < storage_.capacity())
304 next_layer_.async_write_some(boost::asio::const_buffers_1(0, 0),
305 detail::buffered_write_some_handler<
306 ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE(
307 WriteHandler, void (boost::system::error_code, std::size_t))>(
308 storage_, buffers, init.handler));
312 this->async_flush(detail::buffered_write_some_handler<
313 ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE(
314 WriteHandler, void (boost::system::error_code, std::size_t))>(
315 storage_, buffers, init.handler));
318 return init.result.get();
321 template <typename Stream>
322 template <typename ConstBufferSequence>
323 std::size_t buffered_write_stream<Stream>::copy(
324 const ConstBufferSequence& buffers)
326 std::size_t orig_size = storage_.size();
327 std::size_t space_avail = storage_.capacity() - orig_size;
328 std::size_t bytes_avail = boost::asio::buffer_size(buffers);
329 std::size_t length = bytes_avail < space_avail ? bytes_avail : space_avail;
330 storage_.resize(orig_size + length);
331 return boost::asio::buffer_copy(
332 storage_.data() + orig_size, buffers, length);
338 #include <boost/asio/detail/pop_options.hpp>
340 #endif // BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP