Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

937 lines
32KB

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