1//
2// impl/write.hpp
3// ~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 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_IMPL_WRITE_HPP
12#define BOOST_ASIO_IMPL_WRITE_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/buffer.hpp>
19#include <boost/asio/completion_condition.hpp>
20#include <boost/asio/detail/array_fwd.hpp>
21#include <boost/asio/detail/base_from_completion_cond.hpp>
22#include <boost/asio/detail/bind_handler.hpp>
23#include <boost/asio/detail/consuming_buffers.hpp>
24#include <boost/asio/detail/dependent_type.hpp>
25#include <boost/asio/detail/handler_alloc_helpers.hpp>
26#include <boost/asio/detail/handler_cont_helpers.hpp>
27#include <boost/asio/detail/handler_invoke_helpers.hpp>
28#include <boost/asio/detail/handler_type_requirements.hpp>
29#include <boost/asio/detail/throw_error.hpp>
30
31#include <boost/asio/detail/push_options.hpp>
32
33namespace boost {
34namespace asio {
35
36template <typename SyncWriteStream, typename ConstBufferSequence,
37 typename CompletionCondition>
38std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
39 CompletionCondition completion_condition, boost::system::error_code& ec)
40{
41 ec = boost::system::error_code();
42 boost::asio::detail::consuming_buffers<
43 const_buffer, ConstBufferSequence> tmp(buffers);
44 std::size_t total_transferred = 0;
45 tmp.prepare(detail::adapt_completion_condition_result(
46 completion_condition(ec, total_transferred)));
47 while (tmp.begin() != tmp.end())
48 {
49 std::size_t bytes_transferred = s.write_some(tmp, ec);
50 tmp.consume(bytes_transferred);
51 total_transferred += bytes_transferred;
52 tmp.prepare(detail::adapt_completion_condition_result(
53 completion_condition(ec, total_transferred)));
54 }
55 return total_transferred;
56}
57
58template <typename SyncWriteStream, typename ConstBufferSequence>
59inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers)
60{
61 boost::system::error_code ec;
62 std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
63 boost::asio::detail::throw_error(ec, "write");
64 return bytes_transferred;
65}
66
67template <typename SyncWriteStream, typename ConstBufferSequence>
68inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
69 boost::system::error_code& ec)
70{
71 return write(s, buffers, transfer_all(), ec);
72}
73
74template <typename SyncWriteStream, typename ConstBufferSequence,
75 typename CompletionCondition>
76inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
77 CompletionCondition completion_condition)
78{
79 boost::system::error_code ec;
80 std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
81 boost::asio::detail::throw_error(ec, "write");
82 return bytes_transferred;
83}
84
85#if !defined(BOOST_ASIO_NO_IOSTREAM)
86
87template <typename SyncWriteStream, typename Allocator,
88 typename CompletionCondition>
89std::size_t write(SyncWriteStream& s,
90 boost::asio::basic_streambuf<Allocator>& b,
91 CompletionCondition completion_condition, boost::system::error_code& ec)
92{
93 std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
94 b.consume(bytes_transferred);
95 return bytes_transferred;
96}
97
98template <typename SyncWriteStream, typename Allocator>
99inline std::size_t write(SyncWriteStream& s,
100 boost::asio::basic_streambuf<Allocator>& b)
101{
102 boost::system::error_code ec;
103 std::size_t bytes_transferred = write(s, b, transfer_all(), ec);
104 boost::asio::detail::throw_error(ec, "write");
105 return bytes_transferred;
106}
107
108template <typename SyncWriteStream, typename Allocator>
109inline std::size_t write(SyncWriteStream& s,
110 boost::asio::basic_streambuf<Allocator>& b,
111 boost::system::error_code& ec)
112{
113 return write(s, b, transfer_all(), ec);
114}
115
116template <typename SyncWriteStream, typename Allocator,
117 typename CompletionCondition>
118inline std::size_t write(SyncWriteStream& s,
119 boost::asio::basic_streambuf<Allocator>& b,
120 CompletionCondition completion_condition)
121{
122 boost::system::error_code ec;
123 std::size_t bytes_transferred = write(s, b, completion_condition, ec);
124 boost::asio::detail::throw_error(ec, "write");
125 return bytes_transferred;
126}
127
128#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
129
130namespace detail
131{
132 template <typename AsyncWriteStream, typename ConstBufferSequence,
133 typename CompletionCondition, typename WriteHandler>
134 class write_op
135 : detail::base_from_completion_cond<CompletionCondition>
136 {
137 public:
138 write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
139 CompletionCondition completion_condition, WriteHandler& handler)
140 : detail::base_from_completion_cond<
141 CompletionCondition>(completion_condition),
142 stream_(stream),
143 buffers_(buffers),
144 start_(0),
145 total_transferred_(0),
146 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
147 {
148 }
149
150#if defined(BOOST_ASIO_HAS_MOVE)
151 write_op(const write_op& other)
152 : detail::base_from_completion_cond<CompletionCondition>(other),
153 stream_(other.stream_),
154 buffers_(other.buffers_),
155 start_(other.start_),
156 total_transferred_(other.total_transferred_),
157 handler_(other.handler_)
158 {
159 }
160
161 write_op(write_op&& other)
162 : detail::base_from_completion_cond<CompletionCondition>(other),
163 stream_(other.stream_),
164 buffers_(other.buffers_),
165 start_(other.start_),
166 total_transferred_(other.total_transferred_),
167 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
168 {
169 }
170#endif // defined(BOOST_ASIO_HAS_MOVE)
171
172 void operator()(const boost::system::error_code& ec,
173 std::size_t bytes_transferred, int start = 0)
174 {
175 switch (start_ = start)
176 {
177 case 1:
178 buffers_.prepare(this->check_for_completion(ec, total_transferred_));
179 for (;;)
180 {
181 stream_.async_write_some(buffers_,
182 BOOST_ASIO_MOVE_CAST(write_op)(*this));
183 return; default:
184 total_transferred_ += bytes_transferred;
185 buffers_.consume(bytes_transferred);
186 buffers_.prepare(this->check_for_completion(ec, total_transferred_));
187 if ((!ec && bytes_transferred == 0)
188 || buffers_.begin() == buffers_.end())
189 break;
190 }
191
192 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
193 }
194 }
195
196 //private:
197 AsyncWriteStream& stream_;
198 boost::asio::detail::consuming_buffers<
199 const_buffer, ConstBufferSequence> buffers_;
200 int start_;
201 std::size_t total_transferred_;
202 WriteHandler handler_;
203 };
204
205 template <typename AsyncWriteStream,
206 typename CompletionCondition, typename WriteHandler>
207 class write_op<AsyncWriteStream, boost::asio::mutable_buffers_1,
208 CompletionCondition, WriteHandler>
209 : detail::base_from_completion_cond<CompletionCondition>
210 {
211 public:
212 write_op(AsyncWriteStream& stream,
213 const boost::asio::mutable_buffers_1& buffers,
214 CompletionCondition completion_condition,
215 WriteHandler& handler)
216 : detail::base_from_completion_cond<
217 CompletionCondition>(completion_condition),
218 stream_(stream),
219 buffer_(buffers),
220 start_(0),
221 total_transferred_(0),
222 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
223 {
224 }
225
226#if defined(BOOST_ASIO_HAS_MOVE)
227 write_op(const write_op& other)
228 : detail::base_from_completion_cond<CompletionCondition>(other),
229 stream_(other.stream_),
230 buffer_(other.buffer_),
231 start_(other.start_),
232 total_transferred_(other.total_transferred_),
233 handler_(other.handler_)
234 {
235 }
236
237 write_op(write_op&& other)
238 : detail::base_from_completion_cond<CompletionCondition>(other),
239 stream_(other.stream_),
240 buffer_(other.buffer_),
241 start_(other.start_),
242 total_transferred_(other.total_transferred_),
243 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
244 {
245 }
246#endif // defined(BOOST_ASIO_HAS_MOVE)
247
248 void operator()(const boost::system::error_code& ec,
249 std::size_t bytes_transferred, int start = 0)
250 {
251 std::size_t n = 0;
252 switch (start_ = start)
253 {
254 case 1:
255 n = this->check_for_completion(ec, total_transferred_);
256 for (;;)
257 {
258 stream_.async_write_some(
259 boost::asio::buffer(buffer_ + total_transferred_, n),
260 BOOST_ASIO_MOVE_CAST(write_op)(*this));
261 return; default:
262 total_transferred_ += bytes_transferred;
263 if ((!ec && bytes_transferred == 0)
264 || (n = this->check_for_completion(ec, total_transferred_)) == 0
265 || total_transferred_ == boost::asio::buffer_size(buffer_))
266 break;
267 }
268
269 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
270 }
271 }
272
273 //private:
274 AsyncWriteStream& stream_;
275 boost::asio::mutable_buffer buffer_;
276 int start_;
277 std::size_t total_transferred_;
278 WriteHandler handler_;
279 };
280
281 template <typename AsyncWriteStream,
282 typename CompletionCondition, typename WriteHandler>
283 class write_op<AsyncWriteStream, boost::asio::const_buffers_1,
284 CompletionCondition, WriteHandler>
285 : detail::base_from_completion_cond<CompletionCondition>
286 {
287 public:
288 write_op(AsyncWriteStream& stream,
289 const boost::asio::const_buffers_1& buffers,
290 CompletionCondition completion_condition,
291 WriteHandler& handler)
292 : detail::base_from_completion_cond<
293 CompletionCondition>(completion_condition),
294 stream_(stream),
295 buffer_(buffers),
296 start_(0),
297 total_transferred_(0),
298 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
299 {
300 }
301
302#if defined(BOOST_ASIO_HAS_MOVE)
303 write_op(const write_op& other)
304 : detail::base_from_completion_cond<CompletionCondition>(other),
305 stream_(other.stream_),
306 buffer_(other.buffer_),
307 start_(other.start_),
308 total_transferred_(other.total_transferred_),
309 handler_(other.handler_)
310 {
311 }
312
313 write_op(write_op&& other)
314 : detail::base_from_completion_cond<CompletionCondition>(other),
315 stream_(other.stream_),
316 buffer_(other.buffer_),
317 start_(other.start_),
318 total_transferred_(other.total_transferred_),
319 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
320 {
321 }
322#endif // defined(BOOST_ASIO_HAS_MOVE)
323
324 void operator()(const boost::system::error_code& ec,
325 std::size_t bytes_transferred, int start = 0)
326 {
327 std::size_t n = 0;
328 switch (start_ = start)
329 {
330 case 1:
331 n = this->check_for_completion(ec, total_transferred_);
332 for (;;)
333 {
334 stream_.async_write_some(
335 boost::asio::buffer(buffer_ + total_transferred_, n),
336 BOOST_ASIO_MOVE_CAST(write_op)(*this));
337 return; default:
338 total_transferred_ += bytes_transferred;
339 if ((!ec && bytes_transferred == 0)
340 || (n = this->check_for_completion(ec, total_transferred_)) == 0
341 || total_transferred_ == boost::asio::buffer_size(buffer_))
342 break;
343 }
344
345 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
346 }
347 }
348
349 //private:
350 AsyncWriteStream& stream_;
351 boost::asio::const_buffer buffer_;
352 int start_;
353 std::size_t total_transferred_;
354 WriteHandler handler_;
355 };
356
357 template <typename AsyncWriteStream, typename Elem,
358 typename CompletionCondition, typename WriteHandler>
359 class write_op<AsyncWriteStream, boost::array<Elem, 2>,
360 CompletionCondition, WriteHandler>
361 : detail::base_from_completion_cond<CompletionCondition>
362 {
363 public:
364 write_op(AsyncWriteStream& stream, const boost::array<Elem, 2>& buffers,
365 CompletionCondition completion_condition, WriteHandler& handler)
366 : detail::base_from_completion_cond<
367 CompletionCondition>(completion_condition),
368 stream_(stream),
369 buffers_(buffers),
370 start_(0),
371 total_transferred_(0),
372 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
373 {
374 }
375
376#if defined(BOOST_ASIO_HAS_MOVE)
377 write_op(const write_op& other)
378 : detail::base_from_completion_cond<CompletionCondition>(other),
379 stream_(other.stream_),
380 buffers_(other.buffers_),
381 start_(other.start_),
382 total_transferred_(other.total_transferred_),
383 handler_(other.handler_)
384 {
385 }
386
387 write_op(write_op&& other)
388 : detail::base_from_completion_cond<CompletionCondition>(other),
389 stream_(other.stream_),
390 buffers_(other.buffers_),
391 start_(other.start_),
392 total_transferred_(other.total_transferred_),
393 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
394 {
395 }
396#endif // defined(BOOST_ASIO_HAS_MOVE)
397
398 void operator()(const boost::system::error_code& ec,
399 std::size_t bytes_transferred, int start = 0)
400 {
401 typename boost::asio::detail::dependent_type<Elem,
402 boost::array<boost::asio::const_buffer, 2> >::type bufs = {{
403 boost::asio::const_buffer(buffers_[0]),
404 boost::asio::const_buffer(buffers_[1]) }};
405 std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
406 std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
407 std::size_t n = 0;
408 switch (start_ = start)
409 {
410 case 1:
411 n = this->check_for_completion(ec, total_transferred_);
412 for (;;)
413 {
414 bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
415 bufs[1] = boost::asio::buffer(
416 bufs[1] + (total_transferred_ < buffer_size0
417 ? 0 : total_transferred_ - buffer_size0),
418 n - boost::asio::buffer_size(bufs[0]));
419 stream_.async_write_some(bufs, BOOST_ASIO_MOVE_CAST(write_op)(*this));
420 return; default:
421 total_transferred_ += bytes_transferred;
422 if ((!ec && bytes_transferred == 0)
423 || (n = this->check_for_completion(ec, total_transferred_)) == 0
424 || total_transferred_ == buffer_size0 + buffer_size1)
425 break;
426 }
427
428 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
429 }
430 }
431
432 //private:
433 AsyncWriteStream& stream_;
434 boost::array<Elem, 2> buffers_;
435 int start_;
436 std::size_t total_transferred_;
437 WriteHandler handler_;
438 };
439
440#if defined(BOOST_ASIO_HAS_STD_ARRAY)
441
442 template <typename AsyncWriteStream, typename Elem,
443 typename CompletionCondition, typename WriteHandler>
444 class write_op<AsyncWriteStream, std::array<Elem, 2>,
445 CompletionCondition, WriteHandler>
446 : detail::base_from_completion_cond<CompletionCondition>
447 {
448 public:
449 write_op(AsyncWriteStream& stream, const std::array<Elem, 2>& buffers,
450 CompletionCondition completion_condition, WriteHandler& handler)
451 : detail::base_from_completion_cond<
452 CompletionCondition>(completion_condition),
453 stream_(stream),
454 buffers_(buffers),
455 start_(0),
456 total_transferred_(0),
457 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
458 {
459 }
460
461#if defined(BOOST_ASIO_HAS_MOVE)
462 write_op(const write_op& other)
463 : detail::base_from_completion_cond<CompletionCondition>(other),
464 stream_(other.stream_),
465 buffers_(other.buffers_),
466 start_(other.start_),
467 total_transferred_(other.total_transferred_),
468 handler_(other.handler_)
469 {
470 }
471
472 write_op(write_op&& other)
473 : detail::base_from_completion_cond<CompletionCondition>(other),
474 stream_(other.stream_),
475 buffers_(other.buffers_),
476 start_(other.start_),
477 total_transferred_(other.total_transferred_),
478 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
479 {
480 }
481#endif // defined(BOOST_ASIO_HAS_MOVE)
482
483 void operator()(const boost::system::error_code& ec,
484 std::size_t bytes_transferred, int start = 0)
485 {
486 typename boost::asio::detail::dependent_type<Elem,
487 std::array<boost::asio::const_buffer, 2> >::type bufs = {{
488 boost::asio::const_buffer(buffers_[0]),
489 boost::asio::const_buffer(buffers_[1]) }};
490 std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
491 std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
492 std::size_t n = 0;
493 switch (start_ = start)
494 {
495 case 1:
496 n = this->check_for_completion(ec, total_transferred_);
497 for (;;)
498 {
499 bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
500 bufs[1] = boost::asio::buffer(
501 bufs[1] + (total_transferred_ < buffer_size0
502 ? 0 : total_transferred_ - buffer_size0),
503 n - boost::asio::buffer_size(bufs[0]));
504 stream_.async_write_some(bufs, BOOST_ASIO_MOVE_CAST(write_op)(*this));
505 return; default:
506 total_transferred_ += bytes_transferred;
507 if ((!ec && bytes_transferred == 0)
508 || (n = this->check_for_completion(ec, total_transferred_)) == 0
509 || total_transferred_ == buffer_size0 + buffer_size1)
510 break;
511 }
512
513 handler_(ec, static_cast<const std::size_t&>(total_transferred_));
514 }
515 }
516
517 //private:
518 AsyncWriteStream& stream_;
519 std::array<Elem, 2> buffers_;
520 int start_;
521 std::size_t total_transferred_;
522 WriteHandler handler_;
523 };
524
525#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
526
527 template <typename AsyncWriteStream, typename ConstBufferSequence,
528 typename CompletionCondition, typename WriteHandler>
529 inline void* asio_handler_allocate(std::size_t size,
530 write_op<AsyncWriteStream, ConstBufferSequence,
531 CompletionCondition, WriteHandler>* this_handler)
532 {
533 return boost_asio_handler_alloc_helpers::allocate(
534 size, this_handler->handler_);
535 }
536
537 template <typename AsyncWriteStream, typename ConstBufferSequence,
538 typename CompletionCondition, typename WriteHandler>
539 inline void asio_handler_deallocate(void* pointer, std::size_t size,
540 write_op<AsyncWriteStream, ConstBufferSequence,
541 CompletionCondition, WriteHandler>* this_handler)
542 {
543 boost_asio_handler_alloc_helpers::deallocate(
544 pointer, size, this_handler->handler_);
545 }
546
547 template <typename AsyncWriteStream, typename ConstBufferSequence,
548 typename CompletionCondition, typename WriteHandler>
549 inline bool asio_handler_is_continuation(
550 write_op<AsyncWriteStream, ConstBufferSequence,
551 CompletionCondition, WriteHandler>* this_handler)
552 {
553 return this_handler->start_ == 0 ? true
554 : boost_asio_handler_cont_helpers::is_continuation(
555 this_handler->handler_);
556 }
557
558 template <typename Function, typename AsyncWriteStream,
559 typename ConstBufferSequence, typename CompletionCondition,
560 typename WriteHandler>
561 inline void asio_handler_invoke(Function& function,
562 write_op<AsyncWriteStream, ConstBufferSequence,
563 CompletionCondition, WriteHandler>* this_handler)
564 {
565 boost_asio_handler_invoke_helpers::invoke(
566 function, this_handler->handler_);
567 }
568
569 template <typename Function, typename AsyncWriteStream,
570 typename ConstBufferSequence, typename CompletionCondition,
571 typename WriteHandler>
572 inline void asio_handler_invoke(const Function& function,
573 write_op<AsyncWriteStream, ConstBufferSequence,
574 CompletionCondition, WriteHandler>* this_handler)
575 {
576 boost_asio_handler_invoke_helpers::invoke(
577 function, this_handler->handler_);
578 }
579} // namespace detail
580
581template <typename AsyncWriteStream, typename ConstBufferSequence,
582 typename CompletionCondition, typename WriteHandler>
583inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
584 void (boost::system::error_code, std::size_t))
585async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
586 CompletionCondition completion_condition,
587 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
588{
589 // If you get an error on the following line it means that your handler does
590 // not meet the documented type requirements for a WriteHandler.
591 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
592
593 detail::async_result_init<
594 WriteHandler, void (boost::system::error_code, std::size_t)> init(
595 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
596
597 detail::write_op<AsyncWriteStream, ConstBufferSequence,
598 CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
599 WriteHandler, void (boost::system::error_code, std::size_t))>(
600 s, buffers, completion_condition, init.handler)(
601 boost::system::error_code(), 0, 1);
602
603 return init.result.get();
604}
605
606template <typename AsyncWriteStream, typename ConstBufferSequence,
607 typename WriteHandler>
608inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
609 void (boost::system::error_code, std::size_t))
610async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
611 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
612{
613 // If you get an error on the following line it means that your handler does
614 // not meet the documented type requirements for a WriteHandler.
615 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
616
617 detail::async_result_init<
618 WriteHandler, void (boost::system::error_code, std::size_t)> init(
619 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
620
621 detail::write_op<AsyncWriteStream, ConstBufferSequence,
622 detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(
623 WriteHandler, void (boost::system::error_code, std::size_t))>(
624 s, buffers, transfer_all(), init.handler)(
625 boost::system::error_code(), 0, 1);
626
627 return init.result.get();
628}
629
630#if !defined(BOOST_ASIO_NO_IOSTREAM)
631
632namespace detail
633{
634 template <typename Allocator, typename WriteHandler>
635 class write_streambuf_handler
636 {
637 public:
638 write_streambuf_handler(boost::asio::basic_streambuf<Allocator>& streambuf,
639 WriteHandler& handler)
640 : streambuf_(streambuf),
641 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
642 {
643 }
644
645#if defined(BOOST_ASIO_HAS_MOVE)
646 write_streambuf_handler(const write_streambuf_handler& other)
647 : streambuf_(other.streambuf_),
648 handler_(other.handler_)
649 {
650 }
651
652 write_streambuf_handler(write_streambuf_handler&& other)
653 : streambuf_(other.streambuf_),
654 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
655 {
656 }
657#endif // defined(BOOST_ASIO_HAS_MOVE)
658
659 void operator()(const boost::system::error_code& ec,
660 const std::size_t bytes_transferred)
661 {
662 streambuf_.consume(bytes_transferred);
663 handler_(ec, bytes_transferred);
664 }
665
666 //private:
667 boost::asio::basic_streambuf<Allocator>& streambuf_;
668 WriteHandler handler_;
669 };
670
671 template <typename Allocator, typename WriteHandler>
672 inline void* asio_handler_allocate(std::size_t size,
673 write_streambuf_handler<Allocator, WriteHandler>* this_handler)
674 {
675 return boost_asio_handler_alloc_helpers::allocate(
676 size, this_handler->handler_);
677 }
678
679 template <typename Allocator, typename WriteHandler>
680 inline void asio_handler_deallocate(void* pointer, std::size_t size,
681 write_streambuf_handler<Allocator, WriteHandler>* this_handler)
682 {
683 boost_asio_handler_alloc_helpers::deallocate(
684 pointer, size, this_handler->handler_);
685 }
686
687 template <typename Allocator, typename WriteHandler>
688 inline bool asio_handler_is_continuation(
689 write_streambuf_handler<Allocator, WriteHandler>* this_handler)
690 {
691 return boost_asio_handler_cont_helpers::is_continuation(
692 this_handler->handler_);
693 }
694
695 template <typename Function, typename Allocator, typename WriteHandler>
696 inline void asio_handler_invoke(Function& function,
697 write_streambuf_handler<Allocator, WriteHandler>* this_handler)
698 {
699 boost_asio_handler_invoke_helpers::invoke(
700 function, this_handler->handler_);
701 }
702
703 template <typename Function, typename Allocator, typename WriteHandler>
704 inline void asio_handler_invoke(const Function& function,
705 write_streambuf_handler<Allocator, WriteHandler>* this_handler)
706 {
707 boost_asio_handler_invoke_helpers::invoke(
708 function, this_handler->handler_);
709 }
710} // namespace detail
711
712template <typename AsyncWriteStream, typename Allocator,
713 typename CompletionCondition, typename WriteHandler>
714inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
715 void (boost::system::error_code, std::size_t))
716async_write(AsyncWriteStream& s,
717 boost::asio::basic_streambuf<Allocator>& b,
718 CompletionCondition completion_condition,
719 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
720{
721 // If you get an error on the following line it means that your handler does
722 // not meet the documented type requirements for a WriteHandler.
723 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
724
725 detail::async_result_init<
726 WriteHandler, void (boost::system::error_code, std::size_t)> init(
727 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
728
729 async_write(s, b.data(), completion_condition,
730 detail::write_streambuf_handler<Allocator, BOOST_ASIO_HANDLER_TYPE(
731 WriteHandler, void (boost::system::error_code, std::size_t))>(
732 b, init.handler));
733
734 return init.result.get();
735}
736
737template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
738inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
739 void (boost::system::error_code, std::size_t))
740async_write(AsyncWriteStream& s,
741 boost::asio::basic_streambuf<Allocator>& b,
742 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
743{
744 // If you get an error on the following line it means that your handler does
745 // not meet the documented type requirements for a WriteHandler.
746 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
747
748 detail::async_result_init<
749 WriteHandler, void (boost::system::error_code, std::size_t)> init(
750 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
751
752 async_write(s, b.data(), transfer_all(),
753 detail::write_streambuf_handler<Allocator, BOOST_ASIO_HANDLER_TYPE(
754 WriteHandler, void (boost::system::error_code, std::size_t))>(
755 b, init.handler));
756
757 return init.result.get();
758}
759
760#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
761
762} // namespace asio
763} // namespace boost
764
765#include <boost/asio/detail/pop_options.hpp>
766
767#endif // BOOST_ASIO_IMPL_WRITE_HPP
768