read_at.hpp 23 KB

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