write_at.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. //
  2. // impl/write_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_WRITE_AT_HPP
  11. #define BOOST_ASIO_IMPL_WRITE_AT_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/associated_allocator.hpp>
  16. #include <boost/asio/associated_executor.hpp>
  17. #include <boost/asio/buffer.hpp>
  18. #include <boost/asio/completion_condition.hpp>
  19. #include <boost/asio/detail/array_fwd.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_alloc_helpers.hpp>
  25. #include <boost/asio/detail/handler_cont_helpers.hpp>
  26. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  27. #include <boost/asio/detail/handler_type_requirements.hpp>
  28. #include <boost/asio/detail/throw_error.hpp>
  29. #include <boost/asio/detail/push_options.hpp>
  30. namespace boost {
  31. namespace asio {
  32. namespace detail
  33. {
  34. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
  35. typename ConstBufferIterator, typename CompletionCondition>
  36. std::size_t write_at_buffer_sequence(SyncRandomAccessWriteDevice& d,
  37. uint64_t offset, const ConstBufferSequence& buffers,
  38. const ConstBufferIterator&, CompletionCondition completion_condition,
  39. boost::system::error_code& ec)
  40. {
  41. ec = boost::system::error_code();
  42. boost::asio::detail::consuming_buffers<const_buffer,
  43. ConstBufferSequence, ConstBufferIterator> tmp(buffers);
  44. while (!tmp.empty())
  45. {
  46. if (std::size_t max_size = detail::adapt_completion_condition_result(
  47. completion_condition(ec, tmp.total_consumed())))
  48. {
  49. tmp.consume(d.write_some_at(offset + tmp.total_consumed(),
  50. tmp.prepare(max_size), ec));
  51. }
  52. else
  53. break;
  54. }
  55. return tmp.total_consumed();;
  56. }
  57. } // namespace detail
  58. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
  59. typename CompletionCondition>
  60. std::size_t write_at(SyncRandomAccessWriteDevice& d,
  61. uint64_t offset, const ConstBufferSequence& buffers,
  62. CompletionCondition completion_condition, boost::system::error_code& ec)
  63. {
  64. return detail::write_at_buffer_sequence(d, offset, buffers,
  65. boost::asio::buffer_sequence_begin(buffers), completion_condition, ec);
  66. }
  67. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
  68. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  69. uint64_t offset, const ConstBufferSequence& buffers)
  70. {
  71. boost::system::error_code ec;
  72. std::size_t bytes_transferred = write_at(
  73. d, offset, buffers, transfer_all(), ec);
  74. boost::asio::detail::throw_error(ec, "write_at");
  75. return bytes_transferred;
  76. }
  77. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
  78. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  79. uint64_t offset, const ConstBufferSequence& buffers,
  80. boost::system::error_code& ec)
  81. {
  82. return write_at(d, offset, buffers, transfer_all(), ec);
  83. }
  84. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
  85. typename CompletionCondition>
  86. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  87. uint64_t offset, const ConstBufferSequence& buffers,
  88. CompletionCondition completion_condition)
  89. {
  90. boost::system::error_code ec;
  91. std::size_t bytes_transferred = write_at(
  92. d, offset, buffers, completion_condition, ec);
  93. boost::asio::detail::throw_error(ec, "write_at");
  94. return bytes_transferred;
  95. }
  96. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  97. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  98. template <typename SyncRandomAccessWriteDevice, typename Allocator,
  99. typename CompletionCondition>
  100. std::size_t write_at(SyncRandomAccessWriteDevice& d,
  101. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  102. CompletionCondition completion_condition, boost::system::error_code& ec)
  103. {
  104. std::size_t bytes_transferred = write_at(
  105. d, offset, b.data(), completion_condition, ec);
  106. b.consume(bytes_transferred);
  107. return bytes_transferred;
  108. }
  109. template <typename SyncRandomAccessWriteDevice, typename Allocator>
  110. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  111. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b)
  112. {
  113. boost::system::error_code ec;
  114. std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);
  115. boost::asio::detail::throw_error(ec, "write_at");
  116. return bytes_transferred;
  117. }
  118. template <typename SyncRandomAccessWriteDevice, typename Allocator>
  119. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  120. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  121. boost::system::error_code& ec)
  122. {
  123. return write_at(d, offset, b, transfer_all(), ec);
  124. }
  125. template <typename SyncRandomAccessWriteDevice, typename Allocator,
  126. typename CompletionCondition>
  127. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  128. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  129. CompletionCondition completion_condition)
  130. {
  131. boost::system::error_code ec;
  132. std::size_t bytes_transferred = write_at(
  133. d, offset, b, completion_condition, ec);
  134. boost::asio::detail::throw_error(ec, "write_at");
  135. return bytes_transferred;
  136. }
  137. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  138. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  139. namespace detail
  140. {
  141. template <typename AsyncRandomAccessWriteDevice,
  142. typename ConstBufferSequence, typename ConstBufferIterator,
  143. typename CompletionCondition, typename WriteHandler>
  144. class write_at_op
  145. : detail::base_from_completion_cond<CompletionCondition>
  146. {
  147. public:
  148. write_at_op(AsyncRandomAccessWriteDevice& device,
  149. uint64_t offset, const ConstBufferSequence& buffers,
  150. CompletionCondition completion_condition, WriteHandler& handler)
  151. : detail::base_from_completion_cond<
  152. CompletionCondition>(completion_condition),
  153. device_(device),
  154. offset_(offset),
  155. buffers_(buffers),
  156. start_(0),
  157. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  158. {
  159. }
  160. #if defined(BOOST_ASIO_HAS_MOVE)
  161. write_at_op(const write_at_op& other)
  162. : detail::base_from_completion_cond<CompletionCondition>(other),
  163. device_(other.device_),
  164. offset_(other.offset_),
  165. buffers_(other.buffers_),
  166. start_(other.start_),
  167. handler_(other.handler_)
  168. {
  169. }
  170. write_at_op(write_at_op&& other)
  171. : detail::base_from_completion_cond<CompletionCondition>(other),
  172. device_(other.device_),
  173. offset_(other.offset_),
  174. buffers_(other.buffers_),
  175. start_(other.start_),
  176. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  177. {
  178. }
  179. #endif // defined(BOOST_ASIO_HAS_MOVE)
  180. void operator()(const boost::system::error_code& ec,
  181. std::size_t bytes_transferred, int start = 0)
  182. {
  183. std::size_t max_size;
  184. switch (start_ = start)
  185. {
  186. case 1:
  187. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  188. do
  189. {
  190. device_.async_write_some_at(
  191. offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
  192. BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
  193. return; default:
  194. buffers_.consume(bytes_transferred);
  195. if ((!ec && bytes_transferred == 0) || buffers_.empty())
  196. break;
  197. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  198. } while (max_size > 0);
  199. handler_(ec, buffers_.total_consumed());
  200. }
  201. }
  202. //private:
  203. AsyncRandomAccessWriteDevice& device_;
  204. uint64_t offset_;
  205. boost::asio::detail::consuming_buffers<const_buffer,
  206. ConstBufferSequence, ConstBufferIterator> buffers_;
  207. int start_;
  208. WriteHandler handler_;
  209. };
  210. template <typename AsyncRandomAccessWriteDevice,
  211. typename ConstBufferSequence, typename ConstBufferIterator,
  212. typename CompletionCondition, typename WriteHandler>
  213. inline void* asio_handler_allocate(std::size_t size,
  214. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  215. ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
  216. {
  217. return boost_asio_handler_alloc_helpers::allocate(
  218. size, this_handler->handler_);
  219. }
  220. template <typename AsyncRandomAccessWriteDevice,
  221. typename ConstBufferSequence, typename ConstBufferIterator,
  222. typename CompletionCondition, typename WriteHandler>
  223. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  224. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  225. ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
  226. {
  227. boost_asio_handler_alloc_helpers::deallocate(
  228. pointer, size, this_handler->handler_);
  229. }
  230. template <typename AsyncRandomAccessWriteDevice,
  231. typename ConstBufferSequence, typename ConstBufferIterator,
  232. typename CompletionCondition, typename WriteHandler>
  233. inline bool asio_handler_is_continuation(
  234. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  235. ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
  236. {
  237. return this_handler->start_ == 0 ? true
  238. : boost_asio_handler_cont_helpers::is_continuation(
  239. this_handler->handler_);
  240. }
  241. template <typename Function, typename AsyncRandomAccessWriteDevice,
  242. typename ConstBufferSequence, typename ConstBufferIterator,
  243. typename CompletionCondition, typename WriteHandler>
  244. inline void asio_handler_invoke(Function& function,
  245. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  246. ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
  247. {
  248. boost_asio_handler_invoke_helpers::invoke(
  249. function, this_handler->handler_);
  250. }
  251. template <typename Function, typename AsyncRandomAccessWriteDevice,
  252. typename ConstBufferSequence, typename ConstBufferIterator,
  253. typename CompletionCondition, typename WriteHandler>
  254. inline void asio_handler_invoke(const Function& function,
  255. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  256. ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
  257. {
  258. boost_asio_handler_invoke_helpers::invoke(
  259. function, this_handler->handler_);
  260. }
  261. template <typename AsyncRandomAccessWriteDevice,
  262. typename ConstBufferSequence, typename ConstBufferIterator,
  263. typename CompletionCondition, typename WriteHandler>
  264. inline void start_write_at_buffer_sequence_op(AsyncRandomAccessWriteDevice& d,
  265. uint64_t offset, const ConstBufferSequence& buffers,
  266. const ConstBufferIterator&, CompletionCondition completion_condition,
  267. WriteHandler& handler)
  268. {
  269. detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  270. ConstBufferIterator, CompletionCondition, WriteHandler>(
  271. d, offset, buffers, completion_condition, handler)(
  272. boost::system::error_code(), 0, 1);
  273. }
  274. } // namespace detail
  275. #if !defined(GENERATING_DOCUMENTATION)
  276. template <typename AsyncRandomAccessWriteDevice,
  277. typename ConstBufferSequence, typename ConstBufferIterator,
  278. typename CompletionCondition, typename WriteHandler, typename Allocator>
  279. struct associated_allocator<
  280. detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  281. ConstBufferIterator, CompletionCondition, WriteHandler>,
  282. Allocator>
  283. {
  284. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  285. static type get(
  286. const detail::write_at_op<AsyncRandomAccessWriteDevice,
  287. ConstBufferSequence, ConstBufferIterator,
  288. CompletionCondition, WriteHandler>& h,
  289. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  290. {
  291. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  292. }
  293. };
  294. template <typename AsyncRandomAccessWriteDevice,
  295. typename ConstBufferSequence, typename ConstBufferIterator,
  296. typename CompletionCondition, typename WriteHandler, typename Executor>
  297. struct associated_executor<
  298. detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  299. ConstBufferIterator, CompletionCondition, WriteHandler>,
  300. Executor>
  301. {
  302. typedef typename associated_executor<WriteHandler, Executor>::type type;
  303. static type get(
  304. const detail::write_at_op<AsyncRandomAccessWriteDevice,
  305. ConstBufferSequence, ConstBufferIterator,
  306. CompletionCondition, WriteHandler>& h,
  307. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  308. {
  309. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  310. }
  311. };
  312. #endif // !defined(GENERATING_DOCUMENTATION)
  313. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  314. typename CompletionCondition, typename WriteHandler>
  315. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  316. void (boost::system::error_code, std::size_t))
  317. async_write_at(AsyncRandomAccessWriteDevice& d,
  318. uint64_t offset, const ConstBufferSequence& buffers,
  319. CompletionCondition completion_condition,
  320. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  321. {
  322. // If you get an error on the following line it means that your handler does
  323. // not meet the documented type requirements for a WriteHandler.
  324. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  325. async_completion<WriteHandler,
  326. void (boost::system::error_code, std::size_t)> init(handler);
  327. detail::start_write_at_buffer_sequence_op(d, offset, buffers,
  328. boost::asio::buffer_sequence_begin(buffers), completion_condition,
  329. init.completion_handler);
  330. return init.result.get();
  331. }
  332. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  333. typename WriteHandler>
  334. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  335. void (boost::system::error_code, std::size_t))
  336. async_write_at(AsyncRandomAccessWriteDevice& d,
  337. uint64_t offset, const ConstBufferSequence& buffers,
  338. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  339. {
  340. // If you get an error on the following line it means that your handler does
  341. // not meet the documented type requirements for a WriteHandler.
  342. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  343. async_completion<WriteHandler,
  344. void (boost::system::error_code, std::size_t)> init(handler);
  345. detail::start_write_at_buffer_sequence_op(d, offset, buffers,
  346. boost::asio::buffer_sequence_begin(buffers), transfer_all(),
  347. init.completion_handler);
  348. return init.result.get();
  349. }
  350. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  351. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  352. namespace detail
  353. {
  354. template <typename Allocator, typename WriteHandler>
  355. class write_at_streambuf_op
  356. {
  357. public:
  358. write_at_streambuf_op(
  359. boost::asio::basic_streambuf<Allocator>& streambuf,
  360. WriteHandler& handler)
  361. : streambuf_(streambuf),
  362. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  363. {
  364. }
  365. #if defined(BOOST_ASIO_HAS_MOVE)
  366. write_at_streambuf_op(const write_at_streambuf_op& other)
  367. : streambuf_(other.streambuf_),
  368. handler_(other.handler_)
  369. {
  370. }
  371. write_at_streambuf_op(write_at_streambuf_op&& other)
  372. : streambuf_(other.streambuf_),
  373. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  374. {
  375. }
  376. #endif // defined(BOOST_ASIO_HAS_MOVE)
  377. void operator()(const boost::system::error_code& ec,
  378. const std::size_t bytes_transferred)
  379. {
  380. streambuf_.consume(bytes_transferred);
  381. handler_(ec, bytes_transferred);
  382. }
  383. //private:
  384. boost::asio::basic_streambuf<Allocator>& streambuf_;
  385. WriteHandler handler_;
  386. };
  387. template <typename Allocator, typename WriteHandler>
  388. inline void* asio_handler_allocate(std::size_t size,
  389. write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
  390. {
  391. return boost_asio_handler_alloc_helpers::allocate(
  392. size, this_handler->handler_);
  393. }
  394. template <typename Allocator, typename WriteHandler>
  395. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  396. write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
  397. {
  398. boost_asio_handler_alloc_helpers::deallocate(
  399. pointer, size, this_handler->handler_);
  400. }
  401. template <typename Allocator, typename WriteHandler>
  402. inline bool asio_handler_is_continuation(
  403. write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
  404. {
  405. return boost_asio_handler_cont_helpers::is_continuation(
  406. this_handler->handler_);
  407. }
  408. template <typename Function, typename Allocator, typename WriteHandler>
  409. inline void asio_handler_invoke(Function& function,
  410. write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
  411. {
  412. boost_asio_handler_invoke_helpers::invoke(
  413. function, this_handler->handler_);
  414. }
  415. template <typename Function, typename Allocator, typename WriteHandler>
  416. inline void asio_handler_invoke(const Function& function,
  417. write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
  418. {
  419. boost_asio_handler_invoke_helpers::invoke(
  420. function, this_handler->handler_);
  421. }
  422. template <typename Allocator, typename WriteHandler>
  423. inline write_at_streambuf_op<Allocator, WriteHandler>
  424. make_write_at_streambuf_op(
  425. boost::asio::basic_streambuf<Allocator>& b, WriteHandler handler)
  426. {
  427. return write_at_streambuf_op<Allocator, WriteHandler>(b, handler);
  428. }
  429. } // namespace detail
  430. #if !defined(GENERATING_DOCUMENTATION)
  431. template <typename Allocator, typename WriteHandler, typename Allocator1>
  432. struct associated_allocator<
  433. detail::write_at_streambuf_op<Allocator, WriteHandler>,
  434. Allocator1>
  435. {
  436. typedef typename associated_allocator<WriteHandler, Allocator1>::type type;
  437. static type get(
  438. const detail::write_at_streambuf_op<Allocator, WriteHandler>& h,
  439. const Allocator1& a = Allocator1()) BOOST_ASIO_NOEXCEPT
  440. {
  441. return associated_allocator<WriteHandler, Allocator1>::get(h.handler_, a);
  442. }
  443. };
  444. template <typename Executor, typename WriteHandler, typename Executor1>
  445. struct associated_executor<
  446. detail::write_at_streambuf_op<Executor, WriteHandler>,
  447. Executor1>
  448. {
  449. typedef typename associated_executor<WriteHandler, Executor1>::type type;
  450. static type get(
  451. const detail::write_at_streambuf_op<Executor, WriteHandler>& h,
  452. const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
  453. {
  454. return associated_executor<WriteHandler, Executor1>::get(h.handler_, ex);
  455. }
  456. };
  457. #endif // !defined(GENERATING_DOCUMENTATION)
  458. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  459. typename CompletionCondition, typename WriteHandler>
  460. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  461. void (boost::system::error_code, std::size_t))
  462. async_write_at(AsyncRandomAccessWriteDevice& d,
  463. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  464. CompletionCondition completion_condition,
  465. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  466. {
  467. // If you get an error on the following line it means that your handler does
  468. // not meet the documented type requirements for a WriteHandler.
  469. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  470. async_completion<WriteHandler,
  471. void (boost::system::error_code, std::size_t)> init(handler);
  472. async_write_at(d, offset, b.data(), completion_condition,
  473. detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE(
  474. WriteHandler, void (boost::system::error_code, std::size_t))>(
  475. b, init.completion_handler));
  476. return init.result.get();
  477. }
  478. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  479. typename WriteHandler>
  480. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  481. void (boost::system::error_code, std::size_t))
  482. async_write_at(AsyncRandomAccessWriteDevice& d,
  483. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  484. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  485. {
  486. // If you get an error on the following line it means that your handler does
  487. // not meet the documented type requirements for a WriteHandler.
  488. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  489. async_completion<WriteHandler,
  490. void (boost::system::error_code, std::size_t)> init(handler);
  491. async_write_at(d, offset, b.data(), transfer_all(),
  492. detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE(
  493. WriteHandler, void (boost::system::error_code, std::size_t))>(
  494. b, init.completion_handler));
  495. return init.result.get();
  496. }
  497. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  498. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  499. } // namespace asio
  500. } // namespace boost
  501. #include <boost/asio/detail/pop_options.hpp>
  502. #endif // BOOST_ASIO_IMPL_WRITE_AT_HPP