read.hpp 41 KB

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