read.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. //
  2. // impl/read.hpp
  3. // ~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 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/throw_error.hpp>
  30. #include <boost/asio/error.hpp>
  31. #include <boost/asio/detail/push_options.hpp>
  32. namespace boost {
  33. namespace asio {
  34. namespace detail
  35. {
  36. template <typename SyncReadStream, typename MutableBufferSequence,
  37. typename MutableBufferIterator, typename CompletionCondition>
  38. std::size_t read_buffer_sequence(SyncReadStream& s,
  39. const MutableBufferSequence& buffers, const MutableBufferIterator&,
  40. CompletionCondition completion_condition, boost::system::error_code& ec)
  41. {
  42. ec = boost::system::error_code();
  43. boost::asio::detail::consuming_buffers<mutable_buffer,
  44. MutableBufferSequence, MutableBufferIterator> tmp(buffers);
  45. while (!tmp.empty())
  46. {
  47. if (std::size_t max_size = detail::adapt_completion_condition_result(
  48. completion_condition(ec, tmp.total_consumed())))
  49. tmp.consume(s.read_some(tmp.prepare(max_size), ec));
  50. else
  51. break;
  52. }
  53. return tmp.total_consumed();;
  54. }
  55. } // namespace detail
  56. template <typename SyncReadStream, typename MutableBufferSequence,
  57. typename CompletionCondition>
  58. std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  59. CompletionCondition completion_condition, boost::system::error_code& ec,
  60. typename enable_if<
  61. is_mutable_buffer_sequence<MutableBufferSequence>::value
  62. >::type*)
  63. {
  64. return detail::read_buffer_sequence(s, buffers,
  65. boost::asio::buffer_sequence_begin(buffers), completion_condition, ec);
  66. }
  67. template <typename SyncReadStream, typename MutableBufferSequence>
  68. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  69. typename enable_if<
  70. is_mutable_buffer_sequence<MutableBufferSequence>::value
  71. >::type*)
  72. {
  73. boost::system::error_code ec;
  74. std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
  75. boost::asio::detail::throw_error(ec, "read");
  76. return bytes_transferred;
  77. }
  78. template <typename SyncReadStream, typename MutableBufferSequence>
  79. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  80. boost::system::error_code& ec,
  81. typename enable_if<
  82. is_mutable_buffer_sequence<MutableBufferSequence>::value
  83. >::type*)
  84. {
  85. return read(s, buffers, transfer_all(), ec);
  86. }
  87. template <typename SyncReadStream, typename MutableBufferSequence,
  88. typename CompletionCondition>
  89. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  90. CompletionCondition completion_condition,
  91. typename enable_if<
  92. is_mutable_buffer_sequence<MutableBufferSequence>::value
  93. >::type*)
  94. {
  95. boost::system::error_code ec;
  96. std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
  97. boost::asio::detail::throw_error(ec, "read");
  98. return bytes_transferred;
  99. }
  100. template <typename SyncReadStream, typename DynamicBuffer,
  101. typename CompletionCondition>
  102. std::size_t read(SyncReadStream& s,
  103. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  104. CompletionCondition completion_condition, boost::system::error_code& ec,
  105. typename enable_if<
  106. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  107. >::type*)
  108. {
  109. typename decay<DynamicBuffer>::type b(
  110. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
  111. ec = boost::system::error_code();
  112. std::size_t total_transferred = 0;
  113. std::size_t max_size = detail::adapt_completion_condition_result(
  114. completion_condition(ec, total_transferred));
  115. std::size_t bytes_available = std::min<std::size_t>(
  116. std::max<std::size_t>(512, b.capacity() - b.size()),
  117. std::min<std::size_t>(max_size, b.max_size() - b.size()));
  118. while (bytes_available > 0)
  119. {
  120. std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
  121. b.commit(bytes_transferred);
  122. total_transferred += bytes_transferred;
  123. max_size = detail::adapt_completion_condition_result(
  124. completion_condition(ec, total_transferred));
  125. bytes_available = std::min<std::size_t>(
  126. std::max<std::size_t>(512, b.capacity() - b.size()),
  127. std::min<std::size_t>(max_size, b.max_size() - b.size()));
  128. }
  129. return total_transferred;
  130. }
  131. template <typename SyncReadStream, typename DynamicBuffer>
  132. inline std::size_t read(SyncReadStream& s,
  133. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  134. typename enable_if<
  135. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  136. >::type*)
  137. {
  138. boost::system::error_code ec;
  139. std::size_t bytes_transferred = read(s,
  140. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), transfer_all(), ec);
  141. boost::asio::detail::throw_error(ec, "read");
  142. return bytes_transferred;
  143. }
  144. template <typename SyncReadStream, typename DynamicBuffer>
  145. inline std::size_t read(SyncReadStream& s,
  146. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  147. boost::system::error_code& ec,
  148. typename enable_if<
  149. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  150. >::type*)
  151. {
  152. return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  153. transfer_all(), ec);
  154. }
  155. template <typename SyncReadStream, typename DynamicBuffer,
  156. typename CompletionCondition>
  157. inline std::size_t read(SyncReadStream& s,
  158. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  159. CompletionCondition completion_condition,
  160. typename enable_if<
  161. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  162. >::type*)
  163. {
  164. boost::system::error_code ec;
  165. std::size_t bytes_transferred = read(s,
  166. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  167. completion_condition, ec);
  168. boost::asio::detail::throw_error(ec, "read");
  169. return bytes_transferred;
  170. }
  171. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  172. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  173. template <typename SyncReadStream, typename Allocator,
  174. typename CompletionCondition>
  175. inline std::size_t read(SyncReadStream& s,
  176. boost::asio::basic_streambuf<Allocator>& b,
  177. CompletionCondition completion_condition, boost::system::error_code& ec)
  178. {
  179. return read(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec);
  180. }
  181. template <typename SyncReadStream, typename Allocator>
  182. inline std::size_t read(SyncReadStream& s,
  183. boost::asio::basic_streambuf<Allocator>& b)
  184. {
  185. return read(s, basic_streambuf_ref<Allocator>(b));
  186. }
  187. template <typename SyncReadStream, typename Allocator>
  188. inline std::size_t read(SyncReadStream& s,
  189. boost::asio::basic_streambuf<Allocator>& b,
  190. boost::system::error_code& ec)
  191. {
  192. return read(s, basic_streambuf_ref<Allocator>(b), ec);
  193. }
  194. template <typename SyncReadStream, typename Allocator,
  195. typename CompletionCondition>
  196. inline std::size_t read(SyncReadStream& s,
  197. boost::asio::basic_streambuf<Allocator>& b,
  198. CompletionCondition completion_condition)
  199. {
  200. return read(s, basic_streambuf_ref<Allocator>(b), completion_condition);
  201. }
  202. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  203. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  204. namespace detail
  205. {
  206. template <typename AsyncReadStream, typename MutableBufferSequence,
  207. typename MutableBufferIterator, typename CompletionCondition,
  208. typename ReadHandler>
  209. class read_op
  210. : detail::base_from_completion_cond<CompletionCondition>
  211. {
  212. public:
  213. read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
  214. CompletionCondition completion_condition, ReadHandler& handler)
  215. : detail::base_from_completion_cond<
  216. CompletionCondition>(completion_condition),
  217. stream_(stream),
  218. buffers_(buffers),
  219. start_(0),
  220. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  221. {
  222. }
  223. #if defined(BOOST_ASIO_HAS_MOVE)
  224. read_op(const read_op& other)
  225. : detail::base_from_completion_cond<CompletionCondition>(other),
  226. stream_(other.stream_),
  227. buffers_(other.buffers_),
  228. start_(other.start_),
  229. handler_(other.handler_)
  230. {
  231. }
  232. read_op(read_op&& other)
  233. : detail::base_from_completion_cond<CompletionCondition>(other),
  234. stream_(other.stream_),
  235. buffers_(other.buffers_),
  236. start_(other.start_),
  237. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  238. {
  239. }
  240. #endif // defined(BOOST_ASIO_HAS_MOVE)
  241. void operator()(const boost::system::error_code& ec,
  242. std::size_t bytes_transferred, int start = 0)
  243. {
  244. std::size_t max_size;
  245. switch (start_ = start)
  246. {
  247. case 1:
  248. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  249. do
  250. {
  251. stream_.async_read_some(buffers_.prepare(max_size),
  252. BOOST_ASIO_MOVE_CAST(read_op)(*this));
  253. return; default:
  254. buffers_.consume(bytes_transferred);
  255. if ((!ec && bytes_transferred == 0) || buffers_.empty())
  256. break;
  257. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  258. } while (max_size > 0);
  259. handler_(ec, buffers_.total_consumed());
  260. }
  261. }
  262. //private:
  263. AsyncReadStream& stream_;
  264. boost::asio::detail::consuming_buffers<mutable_buffer,
  265. MutableBufferSequence, MutableBufferIterator> buffers_;
  266. int start_;
  267. ReadHandler handler_;
  268. };
  269. template <typename AsyncReadStream, typename MutableBufferSequence,
  270. typename MutableBufferIterator, typename CompletionCondition,
  271. typename ReadHandler>
  272. inline void* asio_handler_allocate(std::size_t size,
  273. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  274. CompletionCondition, ReadHandler>* this_handler)
  275. {
  276. return boost_asio_handler_alloc_helpers::allocate(
  277. size, this_handler->handler_);
  278. }
  279. template <typename AsyncReadStream, typename MutableBufferSequence,
  280. typename MutableBufferIterator, typename CompletionCondition,
  281. typename ReadHandler>
  282. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  283. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  284. CompletionCondition, ReadHandler>* this_handler)
  285. {
  286. boost_asio_handler_alloc_helpers::deallocate(
  287. pointer, size, this_handler->handler_);
  288. }
  289. template <typename AsyncReadStream, typename MutableBufferSequence,
  290. typename MutableBufferIterator, typename CompletionCondition,
  291. typename ReadHandler>
  292. inline bool asio_handler_is_continuation(
  293. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  294. CompletionCondition, ReadHandler>* this_handler)
  295. {
  296. return this_handler->start_ == 0 ? true
  297. : boost_asio_handler_cont_helpers::is_continuation(
  298. this_handler->handler_);
  299. }
  300. template <typename Function, typename AsyncReadStream,
  301. typename MutableBufferSequence, typename MutableBufferIterator,
  302. typename CompletionCondition, typename ReadHandler>
  303. inline void asio_handler_invoke(Function& function,
  304. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  305. CompletionCondition, ReadHandler>* this_handler)
  306. {
  307. boost_asio_handler_invoke_helpers::invoke(
  308. function, this_handler->handler_);
  309. }
  310. template <typename Function, typename AsyncReadStream,
  311. typename MutableBufferSequence, typename MutableBufferIterator,
  312. typename CompletionCondition, typename ReadHandler>
  313. inline void asio_handler_invoke(const Function& function,
  314. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  315. CompletionCondition, ReadHandler>* this_handler)
  316. {
  317. boost_asio_handler_invoke_helpers::invoke(
  318. function, this_handler->handler_);
  319. }
  320. template <typename AsyncReadStream, typename MutableBufferSequence,
  321. typename MutableBufferIterator, typename CompletionCondition,
  322. typename ReadHandler>
  323. inline void start_read_buffer_sequence_op(AsyncReadStream& stream,
  324. const MutableBufferSequence& buffers, const MutableBufferIterator&,
  325. CompletionCondition completion_condition, ReadHandler& handler)
  326. {
  327. detail::read_op<AsyncReadStream, MutableBufferSequence,
  328. MutableBufferIterator, CompletionCondition, ReadHandler>(
  329. stream, buffers, completion_condition, handler)(
  330. boost::system::error_code(), 0, 1);
  331. }
  332. } // namespace detail
  333. #if !defined(GENERATING_DOCUMENTATION)
  334. template <typename AsyncReadStream, typename MutableBufferSequence,
  335. typename MutableBufferIterator, typename CompletionCondition,
  336. typename ReadHandler, typename Allocator>
  337. struct associated_allocator<
  338. detail::read_op<AsyncReadStream, MutableBufferSequence,
  339. MutableBufferIterator, CompletionCondition, ReadHandler>,
  340. Allocator>
  341. {
  342. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  343. static type get(
  344. const detail::read_op<AsyncReadStream, MutableBufferSequence,
  345. MutableBufferIterator, CompletionCondition, ReadHandler>& h,
  346. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  347. {
  348. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  349. }
  350. };
  351. template <typename AsyncReadStream, typename MutableBufferSequence,
  352. typename MutableBufferIterator, typename CompletionCondition,
  353. typename ReadHandler, typename Executor>
  354. struct associated_executor<
  355. detail::read_op<AsyncReadStream, MutableBufferSequence,
  356. MutableBufferIterator, CompletionCondition, ReadHandler>,
  357. Executor>
  358. {
  359. typedef typename associated_executor<ReadHandler, Executor>::type type;
  360. static type get(
  361. const detail::read_op<AsyncReadStream, MutableBufferSequence,
  362. MutableBufferIterator, CompletionCondition, ReadHandler>& h,
  363. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  364. {
  365. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  366. }
  367. };
  368. #endif // !defined(GENERATING_DOCUMENTATION)
  369. template <typename AsyncReadStream, typename MutableBufferSequence,
  370. typename CompletionCondition, typename ReadHandler>
  371. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  372. void (boost::system::error_code, std::size_t))
  373. async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
  374. CompletionCondition completion_condition,
  375. BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  376. typename enable_if<
  377. is_mutable_buffer_sequence<MutableBufferSequence>::value
  378. >::type*)
  379. {
  380. // If you get an error on the following line it means that your handler does
  381. // not meet the documented type requirements for a ReadHandler.
  382. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  383. async_completion<ReadHandler,
  384. void (boost::system::error_code, std::size_t)> init(handler);
  385. detail::start_read_buffer_sequence_op(s, buffers,
  386. boost::asio::buffer_sequence_begin(buffers), completion_condition,
  387. init.completion_handler);
  388. return init.result.get();
  389. }
  390. template <typename AsyncReadStream, typename MutableBufferSequence,
  391. typename ReadHandler>
  392. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  393. void (boost::system::error_code, std::size_t))
  394. async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
  395. BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  396. typename enable_if<
  397. is_mutable_buffer_sequence<MutableBufferSequence>::value
  398. >::type*)
  399. {
  400. // If you get an error on the following line it means that your handler does
  401. // not meet the documented type requirements for a ReadHandler.
  402. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  403. async_completion<ReadHandler,
  404. void (boost::system::error_code, std::size_t)> init(handler);
  405. detail::start_read_buffer_sequence_op(s, buffers,
  406. boost::asio::buffer_sequence_begin(buffers), transfer_all(),
  407. init.completion_handler);
  408. return init.result.get();
  409. }
  410. namespace detail
  411. {
  412. template <typename AsyncReadStream, typename DynamicBuffer,
  413. typename CompletionCondition, typename ReadHandler>
  414. class read_dynbuf_op
  415. : detail::base_from_completion_cond<CompletionCondition>
  416. {
  417. public:
  418. template <typename BufferSequence>
  419. read_dynbuf_op(AsyncReadStream& stream,
  420. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  421. CompletionCondition completion_condition, ReadHandler& handler)
  422. : detail::base_from_completion_cond<
  423. CompletionCondition>(completion_condition),
  424. stream_(stream),
  425. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  426. start_(0),
  427. total_transferred_(0),
  428. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  429. {
  430. }
  431. #if defined(BOOST_ASIO_HAS_MOVE)
  432. read_dynbuf_op(const read_dynbuf_op& other)
  433. : detail::base_from_completion_cond<CompletionCondition>(other),
  434. stream_(other.stream_),
  435. buffers_(other.buffers_),
  436. start_(other.start_),
  437. total_transferred_(other.total_transferred_),
  438. handler_(other.handler_)
  439. {
  440. }
  441. read_dynbuf_op(read_dynbuf_op&& other)
  442. : detail::base_from_completion_cond<CompletionCondition>(other),
  443. stream_(other.stream_),
  444. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
  445. start_(other.start_),
  446. total_transferred_(other.total_transferred_),
  447. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  448. {
  449. }
  450. #endif // defined(BOOST_ASIO_HAS_MOVE)
  451. void operator()(const boost::system::error_code& ec,
  452. std::size_t bytes_transferred, int start = 0)
  453. {
  454. std::size_t max_size, bytes_available;
  455. switch (start_ = start)
  456. {
  457. case 1:
  458. max_size = this->check_for_completion(ec, total_transferred_);
  459. bytes_available = std::min<std::size_t>(
  460. std::max<std::size_t>(512,
  461. buffers_.capacity() - buffers_.size()),
  462. std::min<std::size_t>(max_size,
  463. buffers_.max_size() - buffers_.size()));
  464. for (;;)
  465. {
  466. stream_.async_read_some(buffers_.prepare(bytes_available),
  467. BOOST_ASIO_MOVE_CAST(read_dynbuf_op)(*this));
  468. return; default:
  469. total_transferred_ += bytes_transferred;
  470. buffers_.commit(bytes_transferred);
  471. max_size = this->check_for_completion(ec, total_transferred_);
  472. bytes_available = std::min<std::size_t>(
  473. std::max<std::size_t>(512,
  474. buffers_.capacity() - buffers_.size()),
  475. std::min<std::size_t>(max_size,
  476. buffers_.max_size() - buffers_.size()));
  477. if ((!ec && bytes_transferred == 0) || bytes_available == 0)
  478. break;
  479. }
  480. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  481. }
  482. }
  483. //private:
  484. AsyncReadStream& stream_;
  485. DynamicBuffer buffers_;
  486. int start_;
  487. std::size_t total_transferred_;
  488. ReadHandler handler_;
  489. };
  490. template <typename AsyncReadStream, typename DynamicBuffer,
  491. typename CompletionCondition, typename ReadHandler>
  492. inline void* asio_handler_allocate(std::size_t size,
  493. read_dynbuf_op<AsyncReadStream, DynamicBuffer,
  494. CompletionCondition, ReadHandler>* this_handler)
  495. {
  496. return boost_asio_handler_alloc_helpers::allocate(
  497. size, this_handler->handler_);
  498. }
  499. template <typename AsyncReadStream, typename DynamicBuffer,
  500. typename CompletionCondition, typename ReadHandler>
  501. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  502. read_dynbuf_op<AsyncReadStream, DynamicBuffer,
  503. CompletionCondition, ReadHandler>* this_handler)
  504. {
  505. boost_asio_handler_alloc_helpers::deallocate(
  506. pointer, size, this_handler->handler_);
  507. }
  508. template <typename AsyncReadStream, typename DynamicBuffer,
  509. typename CompletionCondition, typename ReadHandler>
  510. inline bool asio_handler_is_continuation(
  511. read_dynbuf_op<AsyncReadStream, DynamicBuffer,
  512. CompletionCondition, ReadHandler>* this_handler)
  513. {
  514. return this_handler->start_ == 0 ? true
  515. : boost_asio_handler_cont_helpers::is_continuation(
  516. this_handler->handler_);
  517. }
  518. template <typename Function, typename AsyncReadStream,
  519. typename DynamicBuffer, typename CompletionCondition,
  520. typename ReadHandler>
  521. inline void asio_handler_invoke(Function& function,
  522. read_dynbuf_op<AsyncReadStream, DynamicBuffer,
  523. CompletionCondition, ReadHandler>* this_handler)
  524. {
  525. boost_asio_handler_invoke_helpers::invoke(
  526. function, this_handler->handler_);
  527. }
  528. template <typename Function, typename AsyncReadStream,
  529. typename DynamicBuffer, typename CompletionCondition,
  530. typename ReadHandler>
  531. inline void asio_handler_invoke(const Function& function,
  532. read_dynbuf_op<AsyncReadStream, DynamicBuffer,
  533. CompletionCondition, ReadHandler>* this_handler)
  534. {
  535. boost_asio_handler_invoke_helpers::invoke(
  536. function, this_handler->handler_);
  537. }
  538. } // namespace detail
  539. #if !defined(GENERATING_DOCUMENTATION)
  540. template <typename AsyncReadStream, typename DynamicBuffer,
  541. typename CompletionCondition, typename ReadHandler, typename Allocator>
  542. struct associated_allocator<
  543. detail::read_dynbuf_op<AsyncReadStream,
  544. DynamicBuffer, CompletionCondition, ReadHandler>,
  545. Allocator>
  546. {
  547. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  548. static type get(
  549. const detail::read_dynbuf_op<AsyncReadStream,
  550. DynamicBuffer, CompletionCondition, ReadHandler>& h,
  551. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  552. {
  553. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  554. }
  555. };
  556. template <typename AsyncReadStream, typename DynamicBuffer,
  557. typename CompletionCondition, typename ReadHandler, typename Executor>
  558. struct associated_executor<
  559. detail::read_dynbuf_op<AsyncReadStream,
  560. DynamicBuffer, CompletionCondition, ReadHandler>,
  561. Executor>
  562. {
  563. typedef typename associated_executor<ReadHandler, Executor>::type type;
  564. static type get(
  565. const detail::read_dynbuf_op<AsyncReadStream,
  566. DynamicBuffer, CompletionCondition, ReadHandler>& h,
  567. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  568. {
  569. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  570. }
  571. };
  572. #endif // !defined(GENERATING_DOCUMENTATION)
  573. template <typename AsyncReadStream,
  574. typename DynamicBuffer, typename ReadHandler>
  575. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  576. void (boost::system::error_code, std::size_t))
  577. async_read(AsyncReadStream& s,
  578. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  579. BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  580. typename enable_if<
  581. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  582. >::type*)
  583. {
  584. return async_read(s,
  585. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  586. transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
  587. }
  588. template <typename AsyncReadStream, typename DynamicBuffer,
  589. typename CompletionCondition, typename ReadHandler>
  590. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  591. void (boost::system::error_code, std::size_t))
  592. async_read(AsyncReadStream& s,
  593. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  594. CompletionCondition completion_condition,
  595. BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  596. typename enable_if<
  597. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  598. >::type*)
  599. {
  600. // If you get an error on the following line it means that your handler does
  601. // not meet the documented type requirements for a ReadHandler.
  602. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  603. async_completion<ReadHandler,
  604. void (boost::system::error_code, std::size_t)> init(handler);
  605. detail::read_dynbuf_op<AsyncReadStream,
  606. typename decay<DynamicBuffer>::type,
  607. CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
  608. ReadHandler, void (boost::system::error_code, std::size_t))>(
  609. s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  610. completion_condition, init.completion_handler)(
  611. boost::system::error_code(), 0, 1);
  612. return init.result.get();
  613. }
  614. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  615. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  616. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  617. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  618. void (boost::system::error_code, std::size_t))
  619. async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
  620. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  621. {
  622. return async_read(s, basic_streambuf_ref<Allocator>(b),
  623. BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
  624. }
  625. template <typename AsyncReadStream, typename Allocator,
  626. typename CompletionCondition, typename ReadHandler>
  627. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  628. void (boost::system::error_code, std::size_t))
  629. async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
  630. CompletionCondition completion_condition,
  631. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  632. {
  633. return async_read(s, basic_streambuf_ref<Allocator>(b),
  634. completion_condition, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
  635. }
  636. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  637. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  638. } // namespace asio
  639. } // namespace boost
  640. #include <boost/asio/detail/pop_options.hpp>
  641. #endif // BOOST_ASIO_IMPL_READ_HPP