Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / asio / impl / write.hpp
1 //
2 // impl/write.hpp
3 // ~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2019 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/associated_allocator.hpp>
19 #include <boost/asio/associated_executor.hpp>
20 #include <boost/asio/buffer.hpp>
21 #include <boost/asio/completion_condition.hpp>
22 #include <boost/asio/detail/array_fwd.hpp>
23 #include <boost/asio/detail/base_from_completion_cond.hpp>
24 #include <boost/asio/detail/bind_handler.hpp>
25 #include <boost/asio/detail/consuming_buffers.hpp>
26 #include <boost/asio/detail/dependent_type.hpp>
27 #include <boost/asio/detail/handler_alloc_helpers.hpp>
28 #include <boost/asio/detail/handler_cont_helpers.hpp>
29 #include <boost/asio/detail/handler_invoke_helpers.hpp>
30 #include <boost/asio/detail/handler_type_requirements.hpp>
31 #include <boost/asio/detail/non_const_lvalue.hpp>
32 #include <boost/asio/detail/throw_error.hpp>
33
34 #include <boost/asio/detail/push_options.hpp>
35
36 namespace boost {
37 namespace asio {
38
39 namespace detail
40 {
41   template <typename SyncWriteStream, typename ConstBufferSequence,
42       typename ConstBufferIterator, typename CompletionCondition>
43   std::size_t write_buffer_sequence(SyncWriteStream& s,
44       const ConstBufferSequence& buffers, const ConstBufferIterator&,
45       CompletionCondition completion_condition, boost::system::error_code& ec)
46   {
47     ec = boost::system::error_code();
48     boost::asio::detail::consuming_buffers<const_buffer,
49         ConstBufferSequence, ConstBufferIterator> tmp(buffers);
50     while (!tmp.empty())
51     {
52       if (std::size_t max_size = detail::adapt_completion_condition_result(
53             completion_condition(ec, tmp.total_consumed())))
54         tmp.consume(s.write_some(tmp.prepare(max_size), ec));
55       else
56         break;
57     }
58     return tmp.total_consumed();;
59   }
60 } // namespace detail
61
62 template <typename SyncWriteStream, typename ConstBufferSequence,
63     typename CompletionCondition>
64 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
65     CompletionCondition completion_condition, boost::system::error_code& ec,
66     typename enable_if<
67       is_const_buffer_sequence<ConstBufferSequence>::value
68     >::type*)
69 {
70   return detail::write_buffer_sequence(s, buffers,
71       boost::asio::buffer_sequence_begin(buffers),
72       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
73 }
74
75 template <typename SyncWriteStream, typename ConstBufferSequence>
76 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
77     typename enable_if<
78       is_const_buffer_sequence<ConstBufferSequence>::value
79     >::type*)
80 {
81   boost::system::error_code ec;
82   std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
83   boost::asio::detail::throw_error(ec, "write");
84   return bytes_transferred;
85 }
86
87 template <typename SyncWriteStream, typename ConstBufferSequence>
88 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
89     boost::system::error_code& ec,
90     typename enable_if<
91       is_const_buffer_sequence<ConstBufferSequence>::value
92     >::type*)
93 {
94   return write(s, buffers, transfer_all(), ec);
95 }
96
97 template <typename SyncWriteStream, typename ConstBufferSequence,
98     typename CompletionCondition>
99 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
100     CompletionCondition completion_condition,
101     typename enable_if<
102       is_const_buffer_sequence<ConstBufferSequence>::value
103     >::type*)
104 {
105   boost::system::error_code ec;
106   std::size_t bytes_transferred = write(s, buffers,
107       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
108   boost::asio::detail::throw_error(ec, "write");
109   return bytes_transferred;
110 }
111
112 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
113
114 template <typename SyncWriteStream, typename DynamicBuffer_v1,
115     typename CompletionCondition>
116 std::size_t write(SyncWriteStream& s,
117     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
118     CompletionCondition completion_condition, boost::system::error_code& ec,
119     typename enable_if<
120       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
121         && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
122     >::type*)
123 {
124   typename decay<DynamicBuffer_v1>::type b(
125       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
126
127   std::size_t bytes_transferred = write(s, b.data(),
128       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
129   b.consume(bytes_transferred);
130   return bytes_transferred;
131 }
132
133 template <typename SyncWriteStream, typename DynamicBuffer_v1>
134 inline std::size_t write(SyncWriteStream& s,
135     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
136     typename enable_if<
137       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
138         && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
139     >::type*)
140 {
141   boost::system::error_code ec;
142   std::size_t bytes_transferred = write(s,
143       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
144       transfer_all(), ec);
145   boost::asio::detail::throw_error(ec, "write");
146   return bytes_transferred;
147 }
148
149 template <typename SyncWriteStream, typename DynamicBuffer_v1>
150 inline std::size_t write(SyncWriteStream& s,
151     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
152     boost::system::error_code& ec,
153     typename enable_if<
154       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
155         && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
156     >::type*)
157 {
158   return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
159       transfer_all(), ec);
160 }
161
162 template <typename SyncWriteStream, typename DynamicBuffer_v1,
163     typename CompletionCondition>
164 inline std::size_t write(SyncWriteStream& s,
165     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
166     CompletionCondition completion_condition,
167     typename enable_if<
168       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
169         && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
170     >::type*)
171 {
172   boost::system::error_code ec;
173   std::size_t bytes_transferred = write(s,
174       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
175       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
176   boost::asio::detail::throw_error(ec, "write");
177   return bytes_transferred;
178 }
179
180 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
181 #if !defined(BOOST_ASIO_NO_IOSTREAM)
182
183 template <typename SyncWriteStream, typename Allocator,
184     typename CompletionCondition>
185 inline std::size_t write(SyncWriteStream& s,
186     boost::asio::basic_streambuf<Allocator>& b,
187     CompletionCondition completion_condition, boost::system::error_code& ec)
188 {
189   return write(s, basic_streambuf_ref<Allocator>(b),
190       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
191 }
192
193 template <typename SyncWriteStream, typename Allocator>
194 inline std::size_t write(SyncWriteStream& s,
195     boost::asio::basic_streambuf<Allocator>& b)
196 {
197   return write(s, basic_streambuf_ref<Allocator>(b));
198 }
199
200 template <typename SyncWriteStream, typename Allocator>
201 inline std::size_t write(SyncWriteStream& s,
202     boost::asio::basic_streambuf<Allocator>& b,
203     boost::system::error_code& ec)
204 {
205   return write(s, basic_streambuf_ref<Allocator>(b), ec);
206 }
207
208 template <typename SyncWriteStream, typename Allocator,
209     typename CompletionCondition>
210 inline std::size_t write(SyncWriteStream& s,
211     boost::asio::basic_streambuf<Allocator>& b,
212     CompletionCondition completion_condition)
213 {
214   return write(s, basic_streambuf_ref<Allocator>(b),
215       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
216 }
217
218 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
219 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
220 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
221
222 template <typename SyncWriteStream, typename DynamicBuffer_v2,
223     typename CompletionCondition>
224 std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
225     CompletionCondition completion_condition, boost::system::error_code& ec,
226     typename enable_if<
227       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
228     >::type*)
229 {
230   std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()),
231       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
232   buffers.consume(bytes_transferred);
233   return bytes_transferred;
234 }
235
236 template <typename SyncWriteStream, typename DynamicBuffer_v2>
237 inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
238     typename enable_if<
239       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
240     >::type*)
241 {
242   boost::system::error_code ec;
243   std::size_t bytes_transferred = write(s,
244       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
245       transfer_all(), ec);
246   boost::asio::detail::throw_error(ec, "write");
247   return bytes_transferred;
248 }
249
250 template <typename SyncWriteStream, typename DynamicBuffer_v2>
251 inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
252     boost::system::error_code& ec,
253     typename enable_if<
254       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
255     >::type*)
256 {
257   return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
258       transfer_all(), ec);
259 }
260
261 template <typename SyncWriteStream, typename DynamicBuffer_v2,
262     typename CompletionCondition>
263 inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
264     CompletionCondition completion_condition,
265     typename enable_if<
266       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
267     >::type*)
268 {
269   boost::system::error_code ec;
270   std::size_t bytes_transferred = write(s,
271       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
272       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
273   boost::asio::detail::throw_error(ec, "write");
274   return bytes_transferred;
275 }
276
277 namespace detail
278 {
279   template <typename AsyncWriteStream, typename ConstBufferSequence,
280       typename ConstBufferIterator, typename CompletionCondition,
281       typename WriteHandler>
282   class write_op
283     : detail::base_from_completion_cond<CompletionCondition>
284   {
285   public:
286     write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
287         CompletionCondition& completion_condition, WriteHandler& handler)
288       : detail::base_from_completion_cond<
289           CompletionCondition>(completion_condition),
290         stream_(stream),
291         buffers_(buffers),
292         start_(0),
293         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
294     {
295     }
296
297 #if defined(BOOST_ASIO_HAS_MOVE)
298     write_op(const write_op& other)
299       : detail::base_from_completion_cond<CompletionCondition>(other),
300         stream_(other.stream_),
301         buffers_(other.buffers_),
302         start_(other.start_),
303         handler_(other.handler_)
304     {
305     }
306
307     write_op(write_op&& other)
308       : detail::base_from_completion_cond<CompletionCondition>(
309           BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
310             CompletionCondition>)(other)),
311         stream_(other.stream_),
312         buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
313         start_(other.start_),
314         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
315     {
316     }
317 #endif // defined(BOOST_ASIO_HAS_MOVE)
318
319     void operator()(const boost::system::error_code& ec,
320         std::size_t bytes_transferred, int start = 0)
321     {
322       std::size_t max_size;
323       switch (start_ = start)
324       {
325         case 1:
326         max_size = this->check_for_completion(ec, buffers_.total_consumed());
327         do
328         {
329           stream_.async_write_some(buffers_.prepare(max_size),
330               BOOST_ASIO_MOVE_CAST(write_op)(*this));
331           return; default:
332           buffers_.consume(bytes_transferred);
333           if ((!ec && bytes_transferred == 0) || buffers_.empty())
334             break;
335           max_size = this->check_for_completion(ec, buffers_.total_consumed());
336         } while (max_size > 0);
337
338         handler_(ec, buffers_.total_consumed());
339       }
340     }
341
342   //private:
343     typedef boost::asio::detail::consuming_buffers<const_buffer,
344         ConstBufferSequence, ConstBufferIterator> buffers_type;
345
346     AsyncWriteStream& stream_;
347     buffers_type buffers_;
348     int start_;
349     WriteHandler handler_;
350   };
351
352   template <typename AsyncWriteStream, typename ConstBufferSequence,
353       typename ConstBufferIterator, typename CompletionCondition,
354       typename WriteHandler>
355   inline void* asio_handler_allocate(std::size_t size,
356       write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
357         CompletionCondition, WriteHandler>* this_handler)
358   {
359     return boost_asio_handler_alloc_helpers::allocate(
360         size, this_handler->handler_);
361   }
362
363   template <typename AsyncWriteStream, typename ConstBufferSequence,
364       typename ConstBufferIterator, typename CompletionCondition,
365       typename WriteHandler>
366   inline void asio_handler_deallocate(void* pointer, std::size_t size,
367       write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
368         CompletionCondition, WriteHandler>* this_handler)
369   {
370     boost_asio_handler_alloc_helpers::deallocate(
371         pointer, size, this_handler->handler_);
372   }
373
374   template <typename AsyncWriteStream, typename ConstBufferSequence,
375       typename ConstBufferIterator, typename CompletionCondition,
376       typename WriteHandler>
377   inline bool asio_handler_is_continuation(
378       write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
379         CompletionCondition, WriteHandler>* this_handler)
380   {
381     return this_handler->start_ == 0 ? true
382       : boost_asio_handler_cont_helpers::is_continuation(
383           this_handler->handler_);
384   }
385
386   template <typename Function, typename AsyncWriteStream,
387       typename ConstBufferSequence, typename ConstBufferIterator,
388       typename CompletionCondition, typename WriteHandler>
389   inline void asio_handler_invoke(Function& function,
390       write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
391         CompletionCondition, WriteHandler>* this_handler)
392   {
393     boost_asio_handler_invoke_helpers::invoke(
394         function, this_handler->handler_);
395   }
396
397   template <typename Function, typename AsyncWriteStream,
398       typename ConstBufferSequence, typename ConstBufferIterator,
399       typename CompletionCondition, typename WriteHandler>
400   inline void asio_handler_invoke(const Function& function,
401       write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
402         CompletionCondition, WriteHandler>* this_handler)
403   {
404     boost_asio_handler_invoke_helpers::invoke(
405         function, this_handler->handler_);
406   }
407
408   template <typename AsyncWriteStream, typename ConstBufferSequence,
409       typename ConstBufferIterator, typename CompletionCondition,
410       typename WriteHandler>
411   inline void start_write_buffer_sequence_op(AsyncWriteStream& stream,
412       const ConstBufferSequence& buffers, const ConstBufferIterator&,
413       CompletionCondition& completion_condition, WriteHandler& handler)
414   {
415     detail::write_op<AsyncWriteStream, ConstBufferSequence,
416       ConstBufferIterator, CompletionCondition, WriteHandler>(
417         stream, buffers, completion_condition, handler)(
418           boost::system::error_code(), 0, 1);
419   }
420
421   template <typename AsyncWriteStream>
422   class initiate_async_write_buffer_sequence
423   {
424   public:
425     typedef typename AsyncWriteStream::executor_type executor_type;
426
427     explicit initiate_async_write_buffer_sequence(AsyncWriteStream& stream)
428       : stream_(stream)
429     {
430     }
431
432     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
433     {
434       return stream_.get_executor();
435     }
436
437     template <typename WriteHandler, typename ConstBufferSequence,
438         typename CompletionCondition>
439     void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
440         const ConstBufferSequence& buffers,
441         BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
442     {
443       // If you get an error on the following line it means that your handler
444       // does not meet the documented type requirements for a WriteHandler.
445       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
446
447       non_const_lvalue<WriteHandler> handler2(handler);
448       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
449       start_write_buffer_sequence_op(stream_, buffers,
450           boost::asio::buffer_sequence_begin(buffers),
451           completion_cond2.value, handler2.value);
452     }
453
454   private:
455     AsyncWriteStream& stream_;
456   };
457 } // namespace detail
458
459 #if !defined(GENERATING_DOCUMENTATION)
460
461 template <typename AsyncWriteStream, typename ConstBufferSequence,
462     typename ConstBufferIterator, typename CompletionCondition,
463     typename WriteHandler, typename Allocator>
464 struct associated_allocator<
465     detail::write_op<AsyncWriteStream, ConstBufferSequence,
466       ConstBufferIterator, CompletionCondition, WriteHandler>,
467     Allocator>
468 {
469   typedef typename associated_allocator<WriteHandler, Allocator>::type type;
470
471   static type get(
472       const detail::write_op<AsyncWriteStream, ConstBufferSequence,
473         ConstBufferIterator, CompletionCondition, WriteHandler>& h,
474       const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
475   {
476     return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
477   }
478 };
479
480 template <typename AsyncWriteStream, typename ConstBufferSequence,
481     typename ConstBufferIterator, typename CompletionCondition,
482     typename WriteHandler, typename Executor>
483 struct associated_executor<
484     detail::write_op<AsyncWriteStream, ConstBufferSequence,
485       ConstBufferIterator, CompletionCondition, WriteHandler>,
486     Executor>
487 {
488   typedef typename associated_executor<WriteHandler, Executor>::type type;
489
490   static type get(
491       const detail::write_op<AsyncWriteStream, ConstBufferSequence,
492         ConstBufferIterator, CompletionCondition, WriteHandler>& h,
493       const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
494   {
495     return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
496   }
497 };
498
499 #endif // !defined(GENERATING_DOCUMENTATION)
500
501 template <typename AsyncWriteStream,
502     typename ConstBufferSequence, typename CompletionCondition,
503     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
504       std::size_t)) WriteHandler>
505 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
506     void (boost::system::error_code, std::size_t))
507 async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
508     CompletionCondition completion_condition,
509     BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
510     typename enable_if<
511       is_const_buffer_sequence<ConstBufferSequence>::value
512     >::type*)
513 {
514   return async_initiate<WriteHandler,
515     void (boost::system::error_code, std::size_t)>(
516       detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s),
517       handler, buffers,
518       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
519 }
520
521 template <typename AsyncWriteStream, typename ConstBufferSequence,
522     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
523       std::size_t)) WriteHandler>
524 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
525     void (boost::system::error_code, std::size_t))
526 async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
527     BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
528     typename enable_if<
529       is_const_buffer_sequence<ConstBufferSequence>::value
530     >::type*)
531 {
532   return async_initiate<WriteHandler,
533     void (boost::system::error_code, std::size_t)>(
534       detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s),
535       handler, buffers, transfer_all());
536 }
537
538 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
539
540 namespace detail
541 {
542   template <typename AsyncWriteStream, typename DynamicBuffer_v1,
543       typename CompletionCondition, typename WriteHandler>
544   class write_dynbuf_v1_op
545   {
546   public:
547     template <typename BufferSequence>
548     write_dynbuf_v1_op(AsyncWriteStream& stream,
549         BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
550         CompletionCondition& completion_condition, WriteHandler& handler)
551       : stream_(stream),
552         buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
553         completion_condition_(
554           BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
555         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
556     {
557     }
558
559 #if defined(BOOST_ASIO_HAS_MOVE)
560     write_dynbuf_v1_op(const write_dynbuf_v1_op& other)
561       : stream_(other.stream_),
562         buffers_(other.buffers_),
563         completion_condition_(other.completion_condition_),
564         handler_(other.handler_)
565     {
566     }
567
568     write_dynbuf_v1_op(write_dynbuf_v1_op&& other)
569       : stream_(other.stream_),
570         buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
571         completion_condition_(
572           BOOST_ASIO_MOVE_CAST(CompletionCondition)(
573             other.completion_condition_)),
574         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
575     {
576     }
577 #endif // defined(BOOST_ASIO_HAS_MOVE)
578
579     void operator()(const boost::system::error_code& ec,
580         std::size_t bytes_transferred, int start = 0)
581     {
582       switch (start)
583       {
584         case 1:
585         async_write(stream_, buffers_.data(),
586             BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition_),
587             BOOST_ASIO_MOVE_CAST(write_dynbuf_v1_op)(*this));
588         return; default:
589         buffers_.consume(bytes_transferred);
590         handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
591       }
592     }
593
594   //private:
595     AsyncWriteStream& stream_;
596     DynamicBuffer_v1 buffers_;
597     CompletionCondition completion_condition_;
598     WriteHandler handler_;
599   };
600
601   template <typename AsyncWriteStream, typename DynamicBuffer_v1,
602       typename CompletionCondition, typename WriteHandler>
603   inline void* asio_handler_allocate(std::size_t size,
604       write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
605         CompletionCondition, WriteHandler>* this_handler)
606   {
607     return boost_asio_handler_alloc_helpers::allocate(
608         size, this_handler->handler_);
609   }
610
611   template <typename AsyncWriteStream, typename DynamicBuffer_v1,
612       typename CompletionCondition, typename WriteHandler>
613   inline void asio_handler_deallocate(void* pointer, std::size_t size,
614       write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
615         CompletionCondition, WriteHandler>* this_handler)
616   {
617     boost_asio_handler_alloc_helpers::deallocate(
618         pointer, size, this_handler->handler_);
619   }
620
621   template <typename AsyncWriteStream, typename DynamicBuffer_v1,
622       typename CompletionCondition, typename WriteHandler>
623   inline bool asio_handler_is_continuation(
624       write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
625         CompletionCondition, WriteHandler>* this_handler)
626   {
627     return boost_asio_handler_cont_helpers::is_continuation(
628         this_handler->handler_);
629   }
630
631   template <typename Function, typename AsyncWriteStream,
632       typename DynamicBuffer_v1, typename CompletionCondition,
633       typename WriteHandler>
634   inline void asio_handler_invoke(Function& function,
635       write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
636         CompletionCondition, WriteHandler>* this_handler)
637   {
638     boost_asio_handler_invoke_helpers::invoke(
639         function, this_handler->handler_);
640   }
641
642   template <typename Function, typename AsyncWriteStream,
643       typename DynamicBuffer_v1, typename CompletionCondition,
644       typename WriteHandler>
645   inline void asio_handler_invoke(const Function& function,
646       write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
647         CompletionCondition, WriteHandler>* this_handler)
648   {
649     boost_asio_handler_invoke_helpers::invoke(
650         function, this_handler->handler_);
651   }
652
653   template <typename AsyncWriteStream>
654   class initiate_async_write_dynbuf_v1
655   {
656   public:
657     typedef typename AsyncWriteStream::executor_type executor_type;
658
659     explicit initiate_async_write_dynbuf_v1(AsyncWriteStream& stream)
660       : stream_(stream)
661     {
662     }
663
664     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
665     {
666       return stream_.get_executor();
667     }
668
669     template <typename WriteHandler, typename DynamicBuffer_v1,
670         typename CompletionCondition>
671     void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
672         BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
673         BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
674     {
675       // If you get an error on the following line it means that your handler
676       // does not meet the documented type requirements for a WriteHandler.
677       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
678
679       non_const_lvalue<WriteHandler> handler2(handler);
680       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
681       write_dynbuf_v1_op<AsyncWriteStream,
682         typename decay<DynamicBuffer_v1>::type,
683           CompletionCondition, typename decay<WriteHandler>::type>(
684             stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
685               completion_cond2.value, handler2.value)(
686                 boost::system::error_code(), 0, 1);
687     }
688
689   private:
690     AsyncWriteStream& stream_;
691   };
692 } // namespace detail
693
694 #if !defined(GENERATING_DOCUMENTATION)
695
696 template <typename AsyncWriteStream, typename DynamicBuffer_v1,
697     typename CompletionCondition, typename WriteHandler, typename Allocator>
698 struct associated_allocator<
699     detail::write_dynbuf_v1_op<AsyncWriteStream,
700       DynamicBuffer_v1, CompletionCondition, WriteHandler>,
701     Allocator>
702 {
703   typedef typename associated_allocator<WriteHandler, Allocator>::type type;
704
705   static type get(
706       const detail::write_dynbuf_v1_op<AsyncWriteStream,
707         DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
708       const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
709   {
710     return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
711   }
712 };
713
714 template <typename AsyncWriteStream, typename DynamicBuffer_v1,
715     typename CompletionCondition, typename WriteHandler, typename Executor>
716 struct associated_executor<
717     detail::write_dynbuf_v1_op<AsyncWriteStream,
718       DynamicBuffer_v1, CompletionCondition, WriteHandler>,
719     Executor>
720 {
721   typedef typename associated_executor<WriteHandler, Executor>::type type;
722
723   static type get(
724       const detail::write_dynbuf_v1_op<AsyncWriteStream,
725         DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
726       const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
727   {
728     return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
729   }
730 };
731
732 #endif // !defined(GENERATING_DOCUMENTATION)
733
734 template <typename AsyncWriteStream, typename DynamicBuffer_v1,
735     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
736       std::size_t)) WriteHandler>
737 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
738     void (boost::system::error_code, std::size_t))
739 async_write(AsyncWriteStream& s,
740     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
741     BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
742     typename enable_if<
743       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
744         && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
745     >::type*)
746 {
747   return async_write(s,
748       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
749       transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
750 }
751
752 template <typename AsyncWriteStream,
753     typename DynamicBuffer_v1, typename CompletionCondition,
754     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
755       std::size_t)) WriteHandler>
756 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
757     void (boost::system::error_code, std::size_t))
758 async_write(AsyncWriteStream& s,
759     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
760     CompletionCondition completion_condition,
761     BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
762     typename enable_if<
763       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
764         && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
765     >::type*)
766 {
767   return async_initiate<WriteHandler,
768     void (boost::system::error_code, std::size_t)>(
769       detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
770       handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
771       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
772 }
773
774 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
775 #if !defined(BOOST_ASIO_NO_IOSTREAM)
776
777 template <typename AsyncWriteStream, typename Allocator,
778     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
779       std::size_t)) WriteHandler>
780 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
781     void (boost::system::error_code, std::size_t))
782 async_write(AsyncWriteStream& s,
783     boost::asio::basic_streambuf<Allocator>& b,
784     BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
785 {
786   return async_write(s, basic_streambuf_ref<Allocator>(b),
787       BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
788 }
789
790 template <typename AsyncWriteStream,
791     typename Allocator, typename CompletionCondition,
792     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
793       std::size_t)) WriteHandler>
794 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
795     void (boost::system::error_code, std::size_t))
796 async_write(AsyncWriteStream& s,
797     boost::asio::basic_streambuf<Allocator>& b,
798     CompletionCondition completion_condition,
799     BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
800 {
801   return async_write(s, basic_streambuf_ref<Allocator>(b),
802       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
803       BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
804 }
805
806 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
807 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
808 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
809
810 namespace detail
811 {
812   template <typename AsyncWriteStream, typename DynamicBuffer_v2,
813       typename CompletionCondition, typename WriteHandler>
814   class write_dynbuf_v2_op
815   {
816   public:
817     template <typename BufferSequence>
818     write_dynbuf_v2_op(AsyncWriteStream& stream,
819         BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
820         CompletionCondition& completion_condition, WriteHandler& handler)
821       : stream_(stream),
822         buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
823         completion_condition_(
824           BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
825         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
826     {
827     }
828
829 #if defined(BOOST_ASIO_HAS_MOVE)
830     write_dynbuf_v2_op(const write_dynbuf_v2_op& other)
831       : stream_(other.stream_),
832         buffers_(other.buffers_),
833         completion_condition_(other.completion_condition_),
834         handler_(other.handler_)
835     {
836     }
837
838     write_dynbuf_v2_op(write_dynbuf_v2_op&& other)
839       : stream_(other.stream_),
840         buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
841         completion_condition_(
842           BOOST_ASIO_MOVE_CAST(CompletionCondition)(
843             other.completion_condition_)),
844         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
845     {
846     }
847 #endif // defined(BOOST_ASIO_HAS_MOVE)
848
849     void operator()(const boost::system::error_code& ec,
850         std::size_t bytes_transferred, int start = 0)
851     {
852       switch (start)
853       {
854         case 1:
855         async_write(stream_, buffers_.data(0, buffers_.size()),
856             BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition_),
857             BOOST_ASIO_MOVE_CAST(write_dynbuf_v2_op)(*this));
858         return; default:
859         buffers_.consume(bytes_transferred);
860         handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
861       }
862     }
863
864   //private:
865     AsyncWriteStream& stream_;
866     DynamicBuffer_v2 buffers_;
867     CompletionCondition completion_condition_;
868     WriteHandler handler_;
869   };
870
871   template <typename AsyncWriteStream, typename DynamicBuffer_v2,
872       typename CompletionCondition, typename WriteHandler>
873   inline void* asio_handler_allocate(std::size_t size,
874       write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
875         CompletionCondition, WriteHandler>* this_handler)
876   {
877     return boost_asio_handler_alloc_helpers::allocate(
878         size, this_handler->handler_);
879   }
880
881   template <typename AsyncWriteStream, typename DynamicBuffer_v2,
882       typename CompletionCondition, typename WriteHandler>
883   inline void asio_handler_deallocate(void* pointer, std::size_t size,
884       write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
885         CompletionCondition, WriteHandler>* this_handler)
886   {
887     boost_asio_handler_alloc_helpers::deallocate(
888         pointer, size, this_handler->handler_);
889   }
890
891   template <typename AsyncWriteStream, typename DynamicBuffer_v2,
892       typename CompletionCondition, typename WriteHandler>
893   inline bool asio_handler_is_continuation(
894       write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
895         CompletionCondition, WriteHandler>* this_handler)
896   {
897     return boost_asio_handler_cont_helpers::is_continuation(
898         this_handler->handler_);
899   }
900
901   template <typename Function, typename AsyncWriteStream,
902       typename DynamicBuffer_v2, typename CompletionCondition,
903       typename WriteHandler>
904   inline void asio_handler_invoke(Function& function,
905       write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
906         CompletionCondition, WriteHandler>* this_handler)
907   {
908     boost_asio_handler_invoke_helpers::invoke(
909         function, this_handler->handler_);
910   }
911
912   template <typename Function, typename AsyncWriteStream,
913       typename DynamicBuffer_v2, typename CompletionCondition,
914       typename WriteHandler>
915   inline void asio_handler_invoke(const Function& function,
916       write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
917         CompletionCondition, WriteHandler>* this_handler)
918   {
919     boost_asio_handler_invoke_helpers::invoke(
920         function, this_handler->handler_);
921   }
922
923   template <typename AsyncWriteStream>
924   class initiate_async_write_dynbuf_v2
925   {
926   public:
927     typedef typename AsyncWriteStream::executor_type executor_type;
928
929     explicit initiate_async_write_dynbuf_v2(AsyncWriteStream& stream)
930       : stream_(stream)
931     {
932     }
933
934     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
935     {
936       return stream_.get_executor();
937     }
938
939     template <typename WriteHandler, typename DynamicBuffer_v2,
940         typename CompletionCondition>
941     void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
942         BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
943         BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
944     {
945       // If you get an error on the following line it means that your handler
946       // does not meet the documented type requirements for a WriteHandler.
947       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
948
949       non_const_lvalue<WriteHandler> handler2(handler);
950       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
951       write_dynbuf_v2_op<AsyncWriteStream,
952         typename decay<DynamicBuffer_v2>::type,
953           CompletionCondition, typename decay<WriteHandler>::type>(
954             stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
955               completion_cond2.value, handler2.value)(
956                 boost::system::error_code(), 0, 1);
957     }
958
959   private:
960     AsyncWriteStream& stream_;
961   };
962 } // namespace detail
963
964 #if !defined(GENERATING_DOCUMENTATION)
965
966 template <typename AsyncWriteStream, typename DynamicBuffer_v2,
967     typename CompletionCondition, typename WriteHandler, typename Allocator>
968 struct associated_allocator<
969     detail::write_dynbuf_v2_op<AsyncWriteStream,
970       DynamicBuffer_v2, CompletionCondition, WriteHandler>,
971     Allocator>
972 {
973   typedef typename associated_allocator<WriteHandler, Allocator>::type type;
974
975   static type get(
976       const detail::write_dynbuf_v2_op<AsyncWriteStream,
977         DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
978       const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
979   {
980     return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
981   }
982 };
983
984 template <typename AsyncWriteStream, typename DynamicBuffer_v2,
985     typename CompletionCondition, typename WriteHandler, typename Executor>
986 struct associated_executor<
987     detail::write_dynbuf_v2_op<AsyncWriteStream,
988       DynamicBuffer_v2, CompletionCondition, WriteHandler>,
989     Executor>
990 {
991   typedef typename associated_executor<WriteHandler, Executor>::type type;
992
993   static type get(
994       const detail::write_dynbuf_v2_op<AsyncWriteStream,
995         DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
996       const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
997   {
998     return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
999   }
1000 };
1001
1002 #endif // !defined(GENERATING_DOCUMENTATION)
1003
1004 template <typename AsyncWriteStream, typename DynamicBuffer_v2,
1005     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1006       std::size_t)) WriteHandler>
1007 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
1008     void (boost::system::error_code, std::size_t))
1009 async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
1010     BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
1011     typename enable_if<
1012       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
1013     >::type*)
1014 {
1015   return async_write(s,
1016       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1017       transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
1018 }
1019
1020 template <typename AsyncWriteStream,
1021     typename DynamicBuffer_v2, typename CompletionCondition,
1022     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1023       std::size_t)) WriteHandler>
1024 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
1025     void (boost::system::error_code, std::size_t))
1026 async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
1027     CompletionCondition completion_condition,
1028     BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
1029     typename enable_if<
1030       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
1031     >::type*)
1032 {
1033   return async_initiate<WriteHandler,
1034     void (boost::system::error_code, std::size_t)>(
1035       detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),
1036       handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1037       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
1038 }
1039
1040 } // namespace asio
1041 } // namespace boost
1042
1043 #include <boost/asio/detail/pop_options.hpp>
1044
1045 #endif // BOOST_ASIO_IMPL_WRITE_HPP