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