read_at.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. //
  2. // impl/read_at.hpp
  3. // ~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 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_AT_HPP
  11. #define BOOST_ASIO_IMPL_READ_AT_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 SyncRandomAccessReadDevice, typename MutableBufferSequence,
  36. typename MutableBufferIterator, typename CompletionCondition>
  37. std::size_t read_at_buffer_sequence(SyncRandomAccessReadDevice& d,
  38. uint64_t offset, const MutableBufferSequence& buffers,
  39. const MutableBufferIterator&, CompletionCondition completion_condition,
  40. boost::system::error_code& ec)
  41. {
  42. ec = boost::system::error_code();
  43. boost::asio::detail::consuming_buffers<mutable_buffer,
  44. MutableBufferSequence, MutableBufferIterator> tmp(buffers);
  45. while (!tmp.empty())
  46. {
  47. if (std::size_t max_size = detail::adapt_completion_condition_result(
  48. completion_condition(ec, tmp.total_consumed())))
  49. {
  50. tmp.consume(d.read_some_at(offset + tmp.total_consumed(),
  51. tmp.prepare(max_size), ec));
  52. }
  53. else
  54. break;
  55. }
  56. return tmp.total_consumed();
  57. }
  58. } // namespace detail
  59. template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
  60. typename CompletionCondition>
  61. std::size_t read_at(SyncRandomAccessReadDevice& d,
  62. uint64_t offset, const MutableBufferSequence& buffers,
  63. CompletionCondition completion_condition, boost::system::error_code& ec)
  64. {
  65. return detail::read_at_buffer_sequence(d, offset, buffers,
  66. boost::asio::buffer_sequence_begin(buffers),
  67. static_cast<CompletionCondition&&>(completion_condition), ec);
  68. }
  69. template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
  70. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  71. uint64_t offset, const MutableBufferSequence& buffers)
  72. {
  73. boost::system::error_code ec;
  74. std::size_t bytes_transferred = read_at(
  75. d, offset, buffers, transfer_all(), ec);
  76. boost::asio::detail::throw_error(ec, "read_at");
  77. return bytes_transferred;
  78. }
  79. template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
  80. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  81. uint64_t offset, const MutableBufferSequence& buffers,
  82. boost::system::error_code& ec)
  83. {
  84. return read_at(d, offset, buffers, transfer_all(), ec);
  85. }
  86. template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
  87. typename CompletionCondition>
  88. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  89. uint64_t offset, const MutableBufferSequence& buffers,
  90. CompletionCondition completion_condition)
  91. {
  92. boost::system::error_code ec;
  93. std::size_t bytes_transferred = read_at(d, offset, buffers,
  94. static_cast<CompletionCondition&&>(completion_condition), ec);
  95. boost::asio::detail::throw_error(ec, "read_at");
  96. return bytes_transferred;
  97. }
  98. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  99. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  100. template <typename SyncRandomAccessReadDevice, typename Allocator,
  101. typename CompletionCondition>
  102. std::size_t read_at(SyncRandomAccessReadDevice& d,
  103. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  104. CompletionCondition completion_condition, boost::system::error_code& ec)
  105. {
  106. ec = boost::system::error_code();
  107. std::size_t total_transferred = 0;
  108. std::size_t max_size = detail::adapt_completion_condition_result(
  109. completion_condition(ec, total_transferred));
  110. std::size_t bytes_available = read_size_helper(b, max_size);
  111. while (bytes_available > 0)
  112. {
  113. std::size_t bytes_transferred = d.read_some_at(
  114. offset + total_transferred, b.prepare(bytes_available), ec);
  115. b.commit(bytes_transferred);
  116. total_transferred += bytes_transferred;
  117. max_size = detail::adapt_completion_condition_result(
  118. completion_condition(ec, total_transferred));
  119. bytes_available = read_size_helper(b, max_size);
  120. }
  121. return total_transferred;
  122. }
  123. template <typename SyncRandomAccessReadDevice, typename Allocator>
  124. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  125. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b)
  126. {
  127. boost::system::error_code ec;
  128. std::size_t bytes_transferred = read_at(
  129. d, offset, b, transfer_all(), ec);
  130. boost::asio::detail::throw_error(ec, "read_at");
  131. return bytes_transferred;
  132. }
  133. template <typename SyncRandomAccessReadDevice, typename Allocator>
  134. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  135. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  136. boost::system::error_code& ec)
  137. {
  138. return read_at(d, offset, b, transfer_all(), ec);
  139. }
  140. template <typename SyncRandomAccessReadDevice, typename Allocator,
  141. typename CompletionCondition>
  142. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  143. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  144. CompletionCondition completion_condition)
  145. {
  146. boost::system::error_code ec;
  147. std::size_t bytes_transferred = read_at(d, offset, b,
  148. static_cast<CompletionCondition&&>(completion_condition), ec);
  149. boost::asio::detail::throw_error(ec, "read_at");
  150. return bytes_transferred;
  151. }
  152. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  153. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  154. namespace detail
  155. {
  156. template <typename AsyncRandomAccessReadDevice,
  157. typename MutableBufferSequence, typename MutableBufferIterator,
  158. typename CompletionCondition, typename ReadHandler>
  159. class read_at_op
  160. : public base_from_cancellation_state<ReadHandler>,
  161. base_from_completion_cond<CompletionCondition>
  162. {
  163. public:
  164. read_at_op(AsyncRandomAccessReadDevice& device,
  165. uint64_t offset, const MutableBufferSequence& buffers,
  166. CompletionCondition& completion_condition, ReadHandler& handler)
  167. : base_from_cancellation_state<ReadHandler>(
  168. handler, enable_partial_cancellation()),
  169. base_from_completion_cond<CompletionCondition>(completion_condition),
  170. device_(device),
  171. offset_(offset),
  172. buffers_(buffers),
  173. start_(0),
  174. handler_(static_cast<ReadHandler&&>(handler))
  175. {
  176. }
  177. read_at_op(const read_at_op& other)
  178. : base_from_cancellation_state<ReadHandler>(other),
  179. base_from_completion_cond<CompletionCondition>(other),
  180. device_(other.device_),
  181. offset_(other.offset_),
  182. buffers_(other.buffers_),
  183. start_(other.start_),
  184. handler_(other.handler_)
  185. {
  186. }
  187. read_at_op(read_at_op&& other)
  188. : base_from_cancellation_state<ReadHandler>(
  189. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  190. base_from_completion_cond<CompletionCondition>(
  191. static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
  192. device_(other.device_),
  193. offset_(other.offset_),
  194. buffers_(static_cast<buffers_type&&>(other.buffers_)),
  195. start_(other.start_),
  196. handler_(static_cast<ReadHandler&&>(other.handler_))
  197. {
  198. }
  199. void operator()(boost::system::error_code ec,
  200. std::size_t bytes_transferred, int start = 0)
  201. {
  202. std::size_t max_size;
  203. switch (start_ = start)
  204. {
  205. case 1:
  206. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  207. for (;;)
  208. {
  209. {
  210. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
  211. device_.async_read_some_at(
  212. offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
  213. static_cast<read_at_op&&>(*this));
  214. }
  215. return; default:
  216. buffers_.consume(bytes_transferred);
  217. if ((!ec && bytes_transferred == 0) || buffers_.empty())
  218. break;
  219. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  220. if (max_size == 0)
  221. break;
  222. if (this->cancelled() != cancellation_type::none)
  223. {
  224. ec = boost::asio::error::operation_aborted;
  225. break;
  226. }
  227. }
  228. static_cast<ReadHandler&&>(handler_)(
  229. static_cast<const boost::system::error_code&>(ec),
  230. static_cast<const std::size_t&>(buffers_.total_consumed()));
  231. }
  232. }
  233. //private:
  234. typedef boost::asio::detail::consuming_buffers<mutable_buffer,
  235. MutableBufferSequence, MutableBufferIterator> buffers_type;
  236. AsyncRandomAccessReadDevice& device_;
  237. uint64_t offset_;
  238. buffers_type buffers_;
  239. int start_;
  240. ReadHandler handler_;
  241. };
  242. template <typename AsyncRandomAccessReadDevice,
  243. typename MutableBufferSequence, typename MutableBufferIterator,
  244. typename CompletionCondition, typename ReadHandler>
  245. inline bool asio_handler_is_continuation(
  246. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  247. MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
  248. {
  249. return this_handler->start_ == 0 ? true
  250. : boost_asio_handler_cont_helpers::is_continuation(
  251. this_handler->handler_);
  252. }
  253. template <typename AsyncRandomAccessReadDevice,
  254. typename MutableBufferSequence, typename MutableBufferIterator,
  255. typename CompletionCondition, typename ReadHandler>
  256. inline void start_read_at_op(AsyncRandomAccessReadDevice& d,
  257. uint64_t offset, const MutableBufferSequence& buffers,
  258. const MutableBufferIterator&, CompletionCondition& completion_condition,
  259. ReadHandler& handler)
  260. {
  261. detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  262. MutableBufferIterator, CompletionCondition, ReadHandler>(
  263. d, offset, buffers, completion_condition, handler)(
  264. boost::system::error_code(), 0, 1);
  265. }
  266. template <typename AsyncRandomAccessReadDevice>
  267. class initiate_async_read_at
  268. {
  269. public:
  270. typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
  271. explicit initiate_async_read_at(AsyncRandomAccessReadDevice& device)
  272. : device_(device)
  273. {
  274. }
  275. executor_type get_executor() const noexcept
  276. {
  277. return device_.get_executor();
  278. }
  279. template <typename ReadHandler, typename MutableBufferSequence,
  280. typename CompletionCondition>
  281. void operator()(ReadHandler&& handler,
  282. uint64_t offset, const MutableBufferSequence& buffers,
  283. CompletionCondition&& completion_cond) const
  284. {
  285. // If you get an error on the following line it means that your handler
  286. // does not meet the documented type requirements for a ReadHandler.
  287. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  288. non_const_lvalue<ReadHandler> handler2(handler);
  289. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  290. start_read_at_op(device_, offset, buffers,
  291. boost::asio::buffer_sequence_begin(buffers),
  292. completion_cond2.value, handler2.value);
  293. }
  294. private:
  295. AsyncRandomAccessReadDevice& device_;
  296. };
  297. } // namespace detail
  298. #if !defined(GENERATING_DOCUMENTATION)
  299. template <template <typename, typename> class Associator,
  300. typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
  301. typename MutableBufferIterator, typename CompletionCondition,
  302. typename ReadHandler, typename DefaultCandidate>
  303. struct associator<Associator,
  304. detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  305. MutableBufferIterator, CompletionCondition, ReadHandler>,
  306. DefaultCandidate>
  307. : Associator<ReadHandler, DefaultCandidate>
  308. {
  309. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  310. const detail::read_at_op<AsyncRandomAccessReadDevice,
  311. MutableBufferSequence, MutableBufferIterator,
  312. CompletionCondition, ReadHandler>& h) noexcept
  313. {
  314. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  315. }
  316. static auto get(
  317. const detail::read_at_op<AsyncRandomAccessReadDevice,
  318. MutableBufferSequence, MutableBufferIterator,
  319. CompletionCondition, ReadHandler>& h,
  320. const DefaultCandidate& c) noexcept
  321. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  322. {
  323. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  324. }
  325. };
  326. #endif // !defined(GENERATING_DOCUMENTATION)
  327. template <typename AsyncRandomAccessReadDevice,
  328. typename MutableBufferSequence, typename CompletionCondition,
  329. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  330. std::size_t)) ReadToken>
  331. inline auto async_read_at(AsyncRandomAccessReadDevice& d,
  332. uint64_t offset, const MutableBufferSequence& buffers,
  333. CompletionCondition completion_condition, ReadToken&& token)
  334. -> decltype(
  335. async_initiate<ReadToken,
  336. void (boost::system::error_code, std::size_t)>(
  337. declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice>>(),
  338. token, offset, buffers,
  339. static_cast<CompletionCondition&&>(completion_condition)))
  340. {
  341. return async_initiate<ReadToken,
  342. void (boost::system::error_code, std::size_t)>(
  343. detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),
  344. token, offset, buffers,
  345. static_cast<CompletionCondition&&>(completion_condition));
  346. }
  347. template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
  348. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  349. std::size_t)) ReadToken>
  350. inline auto async_read_at(AsyncRandomAccessReadDevice& d,
  351. uint64_t offset, const MutableBufferSequence& buffers, ReadToken&& token)
  352. -> decltype(
  353. async_initiate<ReadToken,
  354. void (boost::system::error_code, std::size_t)>(
  355. declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice>>(),
  356. token, offset, buffers, transfer_all()))
  357. {
  358. return async_initiate<ReadToken,
  359. void (boost::system::error_code, std::size_t)>(
  360. detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),
  361. token, offset, buffers, transfer_all());
  362. }
  363. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  364. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  365. namespace detail
  366. {
  367. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  368. typename CompletionCondition, typename ReadHandler>
  369. class read_at_streambuf_op
  370. : public base_from_cancellation_state<ReadHandler>,
  371. base_from_completion_cond<CompletionCondition>
  372. {
  373. public:
  374. read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
  375. uint64_t offset, basic_streambuf<Allocator>& streambuf,
  376. CompletionCondition& completion_condition, ReadHandler& handler)
  377. : base_from_cancellation_state<ReadHandler>(
  378. handler, enable_partial_cancellation()),
  379. base_from_completion_cond<CompletionCondition>(completion_condition),
  380. device_(device),
  381. offset_(offset),
  382. streambuf_(streambuf),
  383. start_(0),
  384. total_transferred_(0),
  385. handler_(static_cast<ReadHandler&&>(handler))
  386. {
  387. }
  388. read_at_streambuf_op(const read_at_streambuf_op& other)
  389. : base_from_cancellation_state<ReadHandler>(other),
  390. base_from_completion_cond<CompletionCondition>(other),
  391. device_(other.device_),
  392. offset_(other.offset_),
  393. streambuf_(other.streambuf_),
  394. start_(other.start_),
  395. total_transferred_(other.total_transferred_),
  396. handler_(other.handler_)
  397. {
  398. }
  399. read_at_streambuf_op(read_at_streambuf_op&& other)
  400. : base_from_cancellation_state<ReadHandler>(
  401. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  402. base_from_completion_cond<CompletionCondition>(
  403. static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
  404. device_(other.device_),
  405. offset_(other.offset_),
  406. streambuf_(other.streambuf_),
  407. start_(other.start_),
  408. total_transferred_(other.total_transferred_),
  409. handler_(static_cast<ReadHandler&&>(other.handler_))
  410. {
  411. }
  412. void operator()(boost::system::error_code ec,
  413. std::size_t bytes_transferred, int start = 0)
  414. {
  415. std::size_t max_size, bytes_available;
  416. switch (start_ = start)
  417. {
  418. case 1:
  419. max_size = this->check_for_completion(ec, total_transferred_);
  420. bytes_available = read_size_helper(streambuf_, max_size);
  421. for (;;)
  422. {
  423. {
  424. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
  425. device_.async_read_some_at(offset_ + total_transferred_,
  426. streambuf_.prepare(bytes_available),
  427. static_cast<read_at_streambuf_op&&>(*this));
  428. }
  429. return; default:
  430. total_transferred_ += bytes_transferred;
  431. streambuf_.commit(bytes_transferred);
  432. max_size = this->check_for_completion(ec, total_transferred_);
  433. bytes_available = read_size_helper(streambuf_, max_size);
  434. if ((!ec && bytes_transferred == 0) || bytes_available == 0)
  435. break;
  436. if (this->cancelled() != cancellation_type::none)
  437. {
  438. ec = boost::asio::error::operation_aborted;
  439. break;
  440. }
  441. }
  442. static_cast<ReadHandler&&>(handler_)(
  443. static_cast<const boost::system::error_code&>(ec),
  444. static_cast<const std::size_t&>(total_transferred_));
  445. }
  446. }
  447. //private:
  448. AsyncRandomAccessReadDevice& device_;
  449. uint64_t offset_;
  450. boost::asio::basic_streambuf<Allocator>& streambuf_;
  451. int start_;
  452. std::size_t total_transferred_;
  453. ReadHandler handler_;
  454. };
  455. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  456. typename CompletionCondition, typename ReadHandler>
  457. inline bool asio_handler_is_continuation(
  458. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  459. CompletionCondition, ReadHandler>* this_handler)
  460. {
  461. return this_handler->start_ == 0 ? true
  462. : boost_asio_handler_cont_helpers::is_continuation(
  463. this_handler->handler_);
  464. }
  465. template <typename AsyncRandomAccessReadDevice>
  466. class initiate_async_read_at_streambuf
  467. {
  468. public:
  469. typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
  470. explicit initiate_async_read_at_streambuf(
  471. AsyncRandomAccessReadDevice& device)
  472. : device_(device)
  473. {
  474. }
  475. executor_type get_executor() const noexcept
  476. {
  477. return device_.get_executor();
  478. }
  479. template <typename ReadHandler,
  480. typename Allocator, typename CompletionCondition>
  481. void operator()(ReadHandler&& handler,
  482. uint64_t offset, basic_streambuf<Allocator>* b,
  483. CompletionCondition&& completion_cond) const
  484. {
  485. // If you get an error on the following line it means that your handler
  486. // does not meet the documented type requirements for a ReadHandler.
  487. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  488. non_const_lvalue<ReadHandler> handler2(handler);
  489. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  490. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  491. CompletionCondition, decay_t<ReadHandler>>(
  492. device_, offset, *b, completion_cond2.value, handler2.value)(
  493. boost::system::error_code(), 0, 1);
  494. }
  495. private:
  496. AsyncRandomAccessReadDevice& device_;
  497. };
  498. } // namespace detail
  499. #if !defined(GENERATING_DOCUMENTATION)
  500. template <template <typename, typename> class Associator,
  501. typename AsyncRandomAccessReadDevice, typename Executor,
  502. typename CompletionCondition, typename ReadHandler,
  503. typename DefaultCandidate>
  504. struct associator<Associator,
  505. detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  506. Executor, CompletionCondition, ReadHandler>,
  507. DefaultCandidate>
  508. : Associator<ReadHandler, DefaultCandidate>
  509. {
  510. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  511. const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  512. Executor, CompletionCondition, ReadHandler>& h) noexcept
  513. {
  514. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  515. }
  516. static auto get(
  517. const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  518. Executor, CompletionCondition, ReadHandler>& h,
  519. const DefaultCandidate& c) noexcept
  520. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  521. {
  522. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  523. }
  524. };
  525. #endif // !defined(GENERATING_DOCUMENTATION)
  526. template <typename AsyncRandomAccessReadDevice,
  527. typename Allocator, typename CompletionCondition,
  528. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  529. std::size_t)) ReadToken>
  530. inline auto async_read_at(AsyncRandomAccessReadDevice& d,
  531. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  532. CompletionCondition completion_condition, ReadToken&& token)
  533. -> decltype(
  534. async_initiate<ReadToken,
  535. void (boost::system::error_code, std::size_t)>(
  536. declval<detail::initiate_async_read_at_streambuf<
  537. AsyncRandomAccessReadDevice>>(),
  538. token, offset, &b,
  539. static_cast<CompletionCondition&&>(completion_condition)))
  540. {
  541. return async_initiate<ReadToken,
  542. void (boost::system::error_code, std::size_t)>(
  543. detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),
  544. token, offset, &b,
  545. static_cast<CompletionCondition&&>(completion_condition));
  546. }
  547. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  548. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  549. std::size_t)) ReadToken>
  550. inline auto async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset,
  551. boost::asio::basic_streambuf<Allocator>& b, ReadToken&& token)
  552. -> decltype(
  553. async_initiate<ReadToken,
  554. void (boost::system::error_code, std::size_t)>(
  555. declval<detail::initiate_async_read_at_streambuf<
  556. AsyncRandomAccessReadDevice>>(),
  557. token, offset, &b, transfer_all()))
  558. {
  559. return async_initiate<ReadToken,
  560. void (boost::system::error_code, std::size_t)>(
  561. detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),
  562. token, offset, &b, transfer_all());
  563. }
  564. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  565. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  566. } // namespace asio
  567. } // namespace boost
  568. #include <boost/asio/detail/pop_options.hpp>
  569. #endif // BOOST_ASIO_IMPL_READ_AT_HPP