read.hpp 37 KB

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