read_at.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  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 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/associated_allocator.hpp>
  17. #include <boost/asio/associated_executor.hpp>
  18. #include <boost/asio/buffer.hpp>
  19. #include <boost/asio/completion_condition.hpp>
  20. #include <boost/asio/detail/array_fwd.hpp>
  21. #include <boost/asio/detail/base_from_completion_cond.hpp>
  22. #include <boost/asio/detail/bind_handler.hpp>
  23. #include <boost/asio/detail/consuming_buffers.hpp>
  24. #include <boost/asio/detail/dependent_type.hpp>
  25. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  26. #include <boost/asio/detail/handler_cont_helpers.hpp>
  27. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  28. #include <boost/asio/detail/handler_type_requirements.hpp>
  29. #include <boost/asio/detail/throw_error.hpp>
  30. #include <boost/asio/error.hpp>
  31. #include <boost/asio/detail/push_options.hpp>
  32. namespace boost {
  33. namespace asio {
  34. namespace detail
  35. {
  36. template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
  37. typename MutableBufferIterator, typename CompletionCondition>
  38. std::size_t read_at_buffer_sequence(SyncRandomAccessReadDevice& d,
  39. uint64_t offset, const MutableBufferSequence& buffers,
  40. const MutableBufferIterator&, CompletionCondition completion_condition,
  41. boost::system::error_code& ec)
  42. {
  43. ec = boost::system::error_code();
  44. boost::asio::detail::consuming_buffers<mutable_buffer,
  45. MutableBufferSequence, MutableBufferIterator> tmp(buffers);
  46. while (!tmp.empty())
  47. {
  48. if (std::size_t max_size = detail::adapt_completion_condition_result(
  49. completion_condition(ec, tmp.total_consumed())))
  50. {
  51. tmp.consume(d.read_some_at(offset + tmp.total_consumed(),
  52. tmp.prepare(max_size), ec));
  53. }
  54. else
  55. break;
  56. }
  57. return tmp.total_consumed();;
  58. }
  59. } // namespace detail
  60. template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
  61. typename CompletionCondition>
  62. std::size_t read_at(SyncRandomAccessReadDevice& d,
  63. uint64_t offset, const MutableBufferSequence& buffers,
  64. CompletionCondition completion_condition, boost::system::error_code& ec)
  65. {
  66. return detail::read_at_buffer_sequence(d, offset, buffers,
  67. boost::asio::buffer_sequence_begin(buffers), 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(
  94. d, offset, buffers, 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(
  148. d, offset, b, 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. : detail::base_from_completion_cond<CompletionCondition>
  161. {
  162. public:
  163. read_at_op(AsyncRandomAccessReadDevice& device,
  164. uint64_t offset, const MutableBufferSequence& buffers,
  165. CompletionCondition completion_condition, ReadHandler& handler)
  166. : detail::base_from_completion_cond<
  167. CompletionCondition>(completion_condition),
  168. device_(device),
  169. offset_(offset),
  170. buffers_(buffers),
  171. start_(0),
  172. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  173. {
  174. }
  175. #if defined(BOOST_ASIO_HAS_MOVE)
  176. read_at_op(const read_at_op& other)
  177. : detail::base_from_completion_cond<CompletionCondition>(other),
  178. device_(other.device_),
  179. offset_(other.offset_),
  180. buffers_(other.buffers_),
  181. start_(other.start_),
  182. handler_(other.handler_)
  183. {
  184. }
  185. read_at_op(read_at_op&& other)
  186. : detail::base_from_completion_cond<CompletionCondition>(other),
  187. device_(other.device_),
  188. offset_(other.offset_),
  189. buffers_(other.buffers_),
  190. start_(other.start_),
  191. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  192. {
  193. }
  194. #endif // defined(BOOST_ASIO_HAS_MOVE)
  195. void operator()(const boost::system::error_code& ec,
  196. std::size_t bytes_transferred, int start = 0)
  197. {
  198. std::size_t max_size;
  199. switch (start_ = start)
  200. {
  201. case 1:
  202. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  203. do
  204. {
  205. device_.async_read_some_at(
  206. offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
  207. BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
  208. return; default:
  209. buffers_.consume(bytes_transferred);
  210. if ((!ec && bytes_transferred == 0) || buffers_.empty())
  211. break;
  212. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  213. } while (max_size > 0);
  214. handler_(ec, buffers_.total_consumed());
  215. }
  216. }
  217. //private:
  218. AsyncRandomAccessReadDevice& device_;
  219. uint64_t offset_;
  220. boost::asio::detail::consuming_buffers<mutable_buffer,
  221. MutableBufferSequence, MutableBufferIterator> buffers_;
  222. int start_;
  223. ReadHandler handler_;
  224. };
  225. template <typename AsyncRandomAccessReadDevice,
  226. typename MutableBufferSequence, typename MutableBufferIterator,
  227. typename CompletionCondition, typename ReadHandler>
  228. inline void* asio_handler_allocate(std::size_t size,
  229. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  230. MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
  231. {
  232. return boost_asio_handler_alloc_helpers::allocate(
  233. size, this_handler->handler_);
  234. }
  235. template <typename AsyncRandomAccessReadDevice,
  236. typename MutableBufferSequence, typename MutableBufferIterator,
  237. typename CompletionCondition, typename ReadHandler>
  238. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  239. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  240. MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
  241. {
  242. boost_asio_handler_alloc_helpers::deallocate(
  243. pointer, size, this_handler->handler_);
  244. }
  245. template <typename AsyncRandomAccessReadDevice,
  246. typename MutableBufferSequence, typename MutableBufferIterator,
  247. typename CompletionCondition, typename ReadHandler>
  248. inline bool asio_handler_is_continuation(
  249. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  250. MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
  251. {
  252. return this_handler->start_ == 0 ? true
  253. : boost_asio_handler_cont_helpers::is_continuation(
  254. this_handler->handler_);
  255. }
  256. template <typename Function, typename AsyncRandomAccessReadDevice,
  257. typename MutableBufferSequence, typename MutableBufferIterator,
  258. typename CompletionCondition, typename ReadHandler>
  259. inline void asio_handler_invoke(Function& function,
  260. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  261. MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
  262. {
  263. boost_asio_handler_invoke_helpers::invoke(
  264. function, this_handler->handler_);
  265. }
  266. template <typename Function, typename AsyncRandomAccessReadDevice,
  267. typename MutableBufferSequence, typename MutableBufferIterator,
  268. typename CompletionCondition, typename ReadHandler>
  269. inline void asio_handler_invoke(const Function& function,
  270. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  271. MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
  272. {
  273. boost_asio_handler_invoke_helpers::invoke(
  274. function, this_handler->handler_);
  275. }
  276. template <typename AsyncRandomAccessReadDevice,
  277. typename MutableBufferSequence, typename MutableBufferIterator,
  278. typename CompletionCondition, typename ReadHandler>
  279. inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d,
  280. uint64_t offset, const MutableBufferSequence& buffers,
  281. const MutableBufferIterator&, CompletionCondition completion_condition,
  282. ReadHandler& handler)
  283. {
  284. detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  285. MutableBufferIterator, CompletionCondition, ReadHandler>(
  286. d, offset, buffers, completion_condition, handler)(
  287. boost::system::error_code(), 0, 1);
  288. }
  289. } // namespace detail
  290. #if !defined(GENERATING_DOCUMENTATION)
  291. template <typename AsyncRandomAccessReadDevice,
  292. typename MutableBufferSequence, typename MutableBufferIterator,
  293. typename CompletionCondition, typename ReadHandler, typename Allocator>
  294. struct associated_allocator<
  295. detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  296. MutableBufferIterator, CompletionCondition, ReadHandler>,
  297. Allocator>
  298. {
  299. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  300. static type get(
  301. const detail::read_at_op<AsyncRandomAccessReadDevice,
  302. MutableBufferSequence, MutableBufferIterator,
  303. CompletionCondition, ReadHandler>& h,
  304. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  305. {
  306. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  307. }
  308. };
  309. template <typename AsyncRandomAccessReadDevice,
  310. typename MutableBufferSequence, typename MutableBufferIterator,
  311. typename CompletionCondition, typename ReadHandler, typename Executor>
  312. struct associated_executor<
  313. detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  314. MutableBufferIterator, CompletionCondition, ReadHandler>,
  315. Executor>
  316. {
  317. typedef typename associated_executor<ReadHandler, Executor>::type type;
  318. static type get(
  319. const detail::read_at_op<AsyncRandomAccessReadDevice,
  320. MutableBufferSequence, MutableBufferIterator,
  321. CompletionCondition, ReadHandler>& h,
  322. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  323. {
  324. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  325. }
  326. };
  327. #endif // !defined(GENERATING_DOCUMENTATION)
  328. template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
  329. typename CompletionCondition, typename ReadHandler>
  330. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  331. void (boost::system::error_code, std::size_t))
  332. async_read_at(AsyncRandomAccessReadDevice& d,
  333. uint64_t offset, const MutableBufferSequence& buffers,
  334. CompletionCondition completion_condition,
  335. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  336. {
  337. // If you get an error on the following line it means that your handler does
  338. // not meet the documented type requirements for a ReadHandler.
  339. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  340. async_completion<ReadHandler,
  341. void (boost::system::error_code, std::size_t)> init(handler);
  342. detail::start_read_at_buffer_sequence_op(d, offset, buffers,
  343. boost::asio::buffer_sequence_begin(buffers), completion_condition,
  344. init.completion_handler);
  345. return init.result.get();
  346. }
  347. template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
  348. typename ReadHandler>
  349. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  350. void (boost::system::error_code, std::size_t))
  351. async_read_at(AsyncRandomAccessReadDevice& d,
  352. uint64_t offset, const MutableBufferSequence& buffers,
  353. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  354. {
  355. // If you get an error on the following line it means that your handler does
  356. // not meet the documented type requirements for a ReadHandler.
  357. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  358. async_completion<ReadHandler,
  359. void (boost::system::error_code, std::size_t)> init(handler);
  360. detail::start_read_at_buffer_sequence_op(d, offset, buffers,
  361. boost::asio::buffer_sequence_begin(buffers), transfer_all(),
  362. init.completion_handler);
  363. return init.result.get();
  364. }
  365. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  366. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  367. namespace detail
  368. {
  369. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  370. typename CompletionCondition, typename ReadHandler>
  371. class read_at_streambuf_op
  372. : detail::base_from_completion_cond<CompletionCondition>
  373. {
  374. public:
  375. read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
  376. uint64_t offset, basic_streambuf<Allocator>& streambuf,
  377. CompletionCondition completion_condition, ReadHandler& handler)
  378. : detail::base_from_completion_cond<
  379. CompletionCondition>(completion_condition),
  380. device_(device),
  381. offset_(offset),
  382. streambuf_(streambuf),
  383. start_(0),
  384. total_transferred_(0),
  385. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  386. {
  387. }
  388. #if defined(BOOST_ASIO_HAS_MOVE)
  389. read_at_streambuf_op(const read_at_streambuf_op& other)
  390. : detail::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. : detail::base_from_completion_cond<CompletionCondition>(other),
  401. device_(other.device_),
  402. offset_(other.offset_),
  403. streambuf_(other.streambuf_),
  404. start_(other.start_),
  405. total_transferred_(other.total_transferred_),
  406. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  407. {
  408. }
  409. #endif // defined(BOOST_ASIO_HAS_MOVE)
  410. void operator()(const boost::system::error_code& ec,
  411. std::size_t bytes_transferred, int start = 0)
  412. {
  413. std::size_t max_size, bytes_available;
  414. switch (start_ = start)
  415. {
  416. case 1:
  417. max_size = this->check_for_completion(ec, total_transferred_);
  418. bytes_available = read_size_helper(streambuf_, max_size);
  419. for (;;)
  420. {
  421. device_.async_read_some_at(offset_ + total_transferred_,
  422. streambuf_.prepare(bytes_available),
  423. BOOST_ASIO_MOVE_CAST(read_at_streambuf_op)(*this));
  424. return; default:
  425. total_transferred_ += bytes_transferred;
  426. streambuf_.commit(bytes_transferred);
  427. max_size = this->check_for_completion(ec, total_transferred_);
  428. bytes_available = read_size_helper(streambuf_, max_size);
  429. if ((!ec && bytes_transferred == 0) || bytes_available == 0)
  430. break;
  431. }
  432. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  433. }
  434. }
  435. //private:
  436. AsyncRandomAccessReadDevice& device_;
  437. uint64_t offset_;
  438. boost::asio::basic_streambuf<Allocator>& streambuf_;
  439. int start_;
  440. std::size_t total_transferred_;
  441. ReadHandler handler_;
  442. };
  443. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  444. typename CompletionCondition, typename ReadHandler>
  445. inline void* asio_handler_allocate(std::size_t size,
  446. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  447. CompletionCondition, ReadHandler>* this_handler)
  448. {
  449. return boost_asio_handler_alloc_helpers::allocate(
  450. size, this_handler->handler_);
  451. }
  452. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  453. typename CompletionCondition, typename ReadHandler>
  454. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  455. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  456. CompletionCondition, ReadHandler>* this_handler)
  457. {
  458. boost_asio_handler_alloc_helpers::deallocate(
  459. pointer, size, this_handler->handler_);
  460. }
  461. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  462. typename CompletionCondition, typename ReadHandler>
  463. inline bool asio_handler_is_continuation(
  464. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  465. CompletionCondition, ReadHandler>* this_handler)
  466. {
  467. return this_handler->start_ == 0 ? true
  468. : boost_asio_handler_cont_helpers::is_continuation(
  469. this_handler->handler_);
  470. }
  471. template <typename Function, typename AsyncRandomAccessReadDevice,
  472. typename Allocator, typename CompletionCondition, typename ReadHandler>
  473. inline void asio_handler_invoke(Function& function,
  474. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  475. CompletionCondition, ReadHandler>* this_handler)
  476. {
  477. boost_asio_handler_invoke_helpers::invoke(
  478. function, this_handler->handler_);
  479. }
  480. template <typename Function, typename AsyncRandomAccessReadDevice,
  481. typename Allocator, typename CompletionCondition, typename ReadHandler>
  482. inline void asio_handler_invoke(const Function& function,
  483. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  484. CompletionCondition, ReadHandler>* this_handler)
  485. {
  486. boost_asio_handler_invoke_helpers::invoke(
  487. function, this_handler->handler_);
  488. }
  489. } // namespace detail
  490. #if !defined(GENERATING_DOCUMENTATION)
  491. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  492. typename CompletionCondition, typename ReadHandler, typename Allocator1>
  493. struct associated_allocator<
  494. detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  495. Allocator, CompletionCondition, ReadHandler>,
  496. Allocator1>
  497. {
  498. typedef typename associated_allocator<ReadHandler, Allocator1>::type type;
  499. static type get(
  500. const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  501. Allocator, CompletionCondition, ReadHandler>& h,
  502. const Allocator1& a = Allocator1()) BOOST_ASIO_NOEXCEPT
  503. {
  504. return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);
  505. }
  506. };
  507. template <typename AsyncRandomAccessReadDevice, typename Executor,
  508. typename CompletionCondition, typename ReadHandler, typename Executor1>
  509. struct associated_executor<
  510. detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  511. Executor, CompletionCondition, ReadHandler>,
  512. Executor1>
  513. {
  514. typedef typename associated_executor<ReadHandler, Executor1>::type type;
  515. static type get(
  516. const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  517. Executor, CompletionCondition, ReadHandler>& h,
  518. const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
  519. {
  520. return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);
  521. }
  522. };
  523. #endif // !defined(GENERATING_DOCUMENTATION)
  524. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  525. typename CompletionCondition, typename ReadHandler>
  526. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  527. void (boost::system::error_code, std::size_t))
  528. async_read_at(AsyncRandomAccessReadDevice& d,
  529. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  530. CompletionCondition completion_condition,
  531. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  532. {
  533. // If you get an error on the following line it means that your handler does
  534. // not meet the documented type requirements for a ReadHandler.
  535. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  536. async_completion<ReadHandler,
  537. void (boost::system::error_code, std::size_t)> init(handler);
  538. detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  539. CompletionCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
  540. void (boost::system::error_code, std::size_t))>(
  541. d, offset, b, completion_condition, init.completion_handler)(
  542. boost::system::error_code(), 0, 1);
  543. return init.result.get();
  544. }
  545. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  546. typename ReadHandler>
  547. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  548. void (boost::system::error_code, std::size_t))
  549. async_read_at(AsyncRandomAccessReadDevice& d,
  550. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  551. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  552. {
  553. // If you get an error on the following line it means that your handler does
  554. // not meet the documented type requirements for a ReadHandler.
  555. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  556. async_completion<ReadHandler,
  557. void (boost::system::error_code, std::size_t)> init(handler);
  558. detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  559. detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
  560. void (boost::system::error_code, std::size_t))>(
  561. d, offset, b, transfer_all(), init.completion_handler)(
  562. boost::system::error_code(), 0, 1);
  563. return init.result.get();
  564. }
  565. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  566. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  567. } // namespace asio
  568. } // namespace boost
  569. #include <boost/asio/detail/pop_options.hpp>
  570. #endif // BOOST_ASIO_IMPL_READ_AT_HPP