read.hpp 31 KB

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