write_at.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. //
  2. // impl/write_at.hpp
  3. // ~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef 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/buffer.hpp>
  16. #include <boost/asio/completion_condition.hpp>
  17. #include <boost/asio/detail/array_fwd.hpp>
  18. #include <boost/asio/detail/base_from_completion_cond.hpp>
  19. #include <boost/asio/detail/bind_handler.hpp>
  20. #include <boost/asio/detail/consuming_buffers.hpp>
  21. #include <boost/asio/detail/dependent_type.hpp>
  22. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  23. #include <boost/asio/detail/handler_cont_helpers.hpp>
  24. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  25. #include <boost/asio/detail/handler_type_requirements.hpp>
  26. #include <boost/asio/detail/throw_error.hpp>
  27. #include <boost/asio/detail/push_options.hpp>
  28. namespace boost {
  29. namespace asio {
  30. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
  31. typename CompletionCondition>
  32. std::size_t write_at(SyncRandomAccessWriteDevice& d,
  33. uint64_t offset, const ConstBufferSequence& buffers,
  34. CompletionCondition completion_condition, boost::system::error_code& ec)
  35. {
  36. ec = boost::system::error_code();
  37. boost::asio::detail::consuming_buffers<
  38. const_buffer, ConstBufferSequence> tmp(buffers);
  39. std::size_t total_transferred = 0;
  40. tmp.prepare(detail::adapt_completion_condition_result(
  41. completion_condition(ec, total_transferred)));
  42. while (tmp.begin() != tmp.end())
  43. {
  44. std::size_t bytes_transferred = d.write_some_at(
  45. offset + total_transferred, tmp, ec);
  46. tmp.consume(bytes_transferred);
  47. total_transferred += bytes_transferred;
  48. tmp.prepare(detail::adapt_completion_condition_result(
  49. completion_condition(ec, total_transferred)));
  50. }
  51. return total_transferred;
  52. }
  53. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
  54. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  55. uint64_t offset, const ConstBufferSequence& buffers)
  56. {
  57. boost::system::error_code ec;
  58. std::size_t bytes_transferred = write_at(
  59. d, offset, buffers, transfer_all(), ec);
  60. boost::asio::detail::throw_error(ec, "write_at");
  61. return bytes_transferred;
  62. }
  63. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
  64. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  65. uint64_t offset, const ConstBufferSequence& buffers,
  66. boost::system::error_code& ec)
  67. {
  68. return write_at(d, offset, buffers, transfer_all(), ec);
  69. }
  70. template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
  71. typename CompletionCondition>
  72. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  73. uint64_t offset, const ConstBufferSequence& buffers,
  74. CompletionCondition completion_condition)
  75. {
  76. boost::system::error_code ec;
  77. std::size_t bytes_transferred = write_at(
  78. d, offset, buffers, completion_condition, ec);
  79. boost::asio::detail::throw_error(ec, "write_at");
  80. return bytes_transferred;
  81. }
  82. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  83. template <typename SyncRandomAccessWriteDevice, typename Allocator,
  84. typename CompletionCondition>
  85. std::size_t write_at(SyncRandomAccessWriteDevice& d,
  86. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  87. CompletionCondition completion_condition, boost::system::error_code& ec)
  88. {
  89. std::size_t bytes_transferred = write_at(
  90. d, offset, b.data(), completion_condition, ec);
  91. b.consume(bytes_transferred);
  92. return bytes_transferred;
  93. }
  94. template <typename SyncRandomAccessWriteDevice, typename Allocator>
  95. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  96. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b)
  97. {
  98. boost::system::error_code ec;
  99. std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);
  100. boost::asio::detail::throw_error(ec, "write_at");
  101. return bytes_transferred;
  102. }
  103. template <typename SyncRandomAccessWriteDevice, typename Allocator>
  104. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  105. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  106. boost::system::error_code& ec)
  107. {
  108. return write_at(d, offset, b, transfer_all(), ec);
  109. }
  110. template <typename SyncRandomAccessWriteDevice, typename Allocator,
  111. typename CompletionCondition>
  112. inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
  113. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  114. CompletionCondition completion_condition)
  115. {
  116. boost::system::error_code ec;
  117. std::size_t bytes_transferred = write_at(
  118. d, offset, b, completion_condition, ec);
  119. boost::asio::detail::throw_error(ec, "write_at");
  120. return bytes_transferred;
  121. }
  122. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  123. namespace detail
  124. {
  125. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  126. typename CompletionCondition, typename WriteHandler>
  127. class write_at_op
  128. : detail::base_from_completion_cond<CompletionCondition>
  129. {
  130. public:
  131. write_at_op(AsyncRandomAccessWriteDevice& device,
  132. uint64_t offset, const ConstBufferSequence& buffers,
  133. CompletionCondition completion_condition, WriteHandler& handler)
  134. : detail::base_from_completion_cond<
  135. CompletionCondition>(completion_condition),
  136. device_(device),
  137. offset_(offset),
  138. buffers_(buffers),
  139. start_(0),
  140. total_transferred_(0),
  141. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  142. {
  143. }
  144. #if defined(BOOST_ASIO_HAS_MOVE)
  145. write_at_op(const write_at_op& other)
  146. : detail::base_from_completion_cond<CompletionCondition>(other),
  147. device_(other.device_),
  148. offset_(other.offset_),
  149. buffers_(other.buffers_),
  150. start_(other.start_),
  151. total_transferred_(other.total_transferred_),
  152. handler_(other.handler_)
  153. {
  154. }
  155. write_at_op(write_at_op&& other)
  156. : detail::base_from_completion_cond<CompletionCondition>(other),
  157. device_(other.device_),
  158. offset_(other.offset_),
  159. buffers_(other.buffers_),
  160. start_(other.start_),
  161. total_transferred_(other.total_transferred_),
  162. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  163. {
  164. }
  165. #endif // defined(BOOST_ASIO_HAS_MOVE)
  166. void operator()(const boost::system::error_code& ec,
  167. std::size_t bytes_transferred, int start = 0)
  168. {
  169. switch (start_ = start)
  170. {
  171. case 1:
  172. buffers_.prepare(this->check_for_completion(ec, total_transferred_));
  173. for (;;)
  174. {
  175. device_.async_write_some_at(
  176. offset_ + total_transferred_, buffers_,
  177. BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
  178. return; default:
  179. total_transferred_ += bytes_transferred;
  180. buffers_.consume(bytes_transferred);
  181. buffers_.prepare(this->check_for_completion(ec, total_transferred_));
  182. if ((!ec && bytes_transferred == 0)
  183. || buffers_.begin() == buffers_.end())
  184. break;
  185. }
  186. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  187. }
  188. }
  189. //private:
  190. AsyncRandomAccessWriteDevice& device_;
  191. uint64_t offset_;
  192. boost::asio::detail::consuming_buffers<
  193. const_buffer, ConstBufferSequence> buffers_;
  194. int start_;
  195. std::size_t total_transferred_;
  196. WriteHandler handler_;
  197. };
  198. template <typename AsyncRandomAccessWriteDevice,
  199. typename CompletionCondition, typename WriteHandler>
  200. class write_at_op<AsyncRandomAccessWriteDevice,
  201. boost::asio::mutable_buffers_1, CompletionCondition, WriteHandler>
  202. : detail::base_from_completion_cond<CompletionCondition>
  203. {
  204. public:
  205. write_at_op(AsyncRandomAccessWriteDevice& device,
  206. uint64_t offset, const boost::asio::mutable_buffers_1& buffers,
  207. CompletionCondition completion_condition,
  208. WriteHandler& handler)
  209. : detail::base_from_completion_cond<
  210. CompletionCondition>(completion_condition),
  211. device_(device),
  212. offset_(offset),
  213. buffer_(buffers),
  214. start_(0),
  215. total_transferred_(0),
  216. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  217. {
  218. }
  219. #if defined(BOOST_ASIO_HAS_MOVE)
  220. write_at_op(const write_at_op& other)
  221. : detail::base_from_completion_cond<CompletionCondition>(other),
  222. device_(other.device_),
  223. offset_(other.offset_),
  224. buffer_(other.buffer_),
  225. start_(other.start_),
  226. total_transferred_(other.total_transferred_),
  227. handler_(other.handler_)
  228. {
  229. }
  230. write_at_op(write_at_op&& other)
  231. : detail::base_from_completion_cond<CompletionCondition>(other),
  232. device_(other.device_),
  233. offset_(other.offset_),
  234. buffer_(other.buffer_),
  235. start_(other.start_),
  236. total_transferred_(other.total_transferred_),
  237. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  238. {
  239. }
  240. #endif // defined(BOOST_ASIO_HAS_MOVE)
  241. void operator()(const boost::system::error_code& ec,
  242. std::size_t bytes_transferred, int start = 0)
  243. {
  244. std::size_t n = 0;
  245. switch (start_ = start)
  246. {
  247. case 1:
  248. n = this->check_for_completion(ec, total_transferred_);
  249. for (;;)
  250. {
  251. device_.async_write_some_at(offset_ + total_transferred_,
  252. boost::asio::buffer(buffer_ + total_transferred_, n),
  253. BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
  254. return; default:
  255. total_transferred_ += bytes_transferred;
  256. if ((!ec && bytes_transferred == 0)
  257. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  258. || total_transferred_ == boost::asio::buffer_size(buffer_))
  259. break;
  260. }
  261. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  262. }
  263. }
  264. //private:
  265. AsyncRandomAccessWriteDevice& device_;
  266. uint64_t offset_;
  267. boost::asio::mutable_buffer buffer_;
  268. int start_;
  269. std::size_t total_transferred_;
  270. WriteHandler handler_;
  271. };
  272. template <typename AsyncRandomAccessWriteDevice,
  273. typename CompletionCondition, typename WriteHandler>
  274. class write_at_op<AsyncRandomAccessWriteDevice, boost::asio::const_buffers_1,
  275. CompletionCondition, WriteHandler>
  276. : detail::base_from_completion_cond<CompletionCondition>
  277. {
  278. public:
  279. write_at_op(AsyncRandomAccessWriteDevice& device,
  280. uint64_t offset, const boost::asio::const_buffers_1& buffers,
  281. CompletionCondition completion_condition,
  282. WriteHandler& handler)
  283. : detail::base_from_completion_cond<
  284. CompletionCondition>(completion_condition),
  285. device_(device),
  286. offset_(offset),
  287. buffer_(buffers),
  288. start_(0),
  289. total_transferred_(0),
  290. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  291. {
  292. }
  293. #if defined(BOOST_ASIO_HAS_MOVE)
  294. write_at_op(const write_at_op& other)
  295. : detail::base_from_completion_cond<CompletionCondition>(other),
  296. device_(other.device_),
  297. offset_(other.offset_),
  298. buffer_(other.buffer_),
  299. start_(other.start_),
  300. total_transferred_(other.total_transferred_),
  301. handler_(other.handler_)
  302. {
  303. }
  304. write_at_op(write_at_op&& other)
  305. : detail::base_from_completion_cond<CompletionCondition>(other),
  306. device_(other.device_),
  307. offset_(other.offset_),
  308. buffer_(other.buffer_),
  309. start_(other.start_),
  310. total_transferred_(other.total_transferred_),
  311. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  312. {
  313. }
  314. #endif // defined(BOOST_ASIO_HAS_MOVE)
  315. void operator()(const boost::system::error_code& ec,
  316. std::size_t bytes_transferred, int start = 0)
  317. {
  318. std::size_t n = 0;
  319. switch (start_ = start)
  320. {
  321. case 1:
  322. n = this->check_for_completion(ec, total_transferred_);
  323. for (;;)
  324. {
  325. device_.async_write_some_at(offset_ + total_transferred_,
  326. boost::asio::buffer(buffer_ + total_transferred_, n),
  327. BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
  328. return; default:
  329. total_transferred_ += bytes_transferred;
  330. if ((!ec && bytes_transferred == 0)
  331. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  332. || total_transferred_ == boost::asio::buffer_size(buffer_))
  333. break;
  334. }
  335. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  336. }
  337. }
  338. //private:
  339. AsyncRandomAccessWriteDevice& device_;
  340. uint64_t offset_;
  341. boost::asio::const_buffer buffer_;
  342. int start_;
  343. std::size_t total_transferred_;
  344. WriteHandler handler_;
  345. };
  346. template <typename AsyncRandomAccessWriteDevice, typename Elem,
  347. typename CompletionCondition, typename WriteHandler>
  348. class write_at_op<AsyncRandomAccessWriteDevice, boost::array<Elem, 2>,
  349. CompletionCondition, WriteHandler>
  350. : detail::base_from_completion_cond<CompletionCondition>
  351. {
  352. public:
  353. write_at_op(AsyncRandomAccessWriteDevice& device,
  354. uint64_t offset, const boost::array<Elem, 2>& buffers,
  355. CompletionCondition completion_condition, WriteHandler& handler)
  356. : detail::base_from_completion_cond<
  357. CompletionCondition>(completion_condition),
  358. device_(device),
  359. offset_(offset),
  360. buffers_(buffers),
  361. start_(0),
  362. total_transferred_(0),
  363. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  364. {
  365. }
  366. #if defined(BOOST_ASIO_HAS_MOVE)
  367. write_at_op(const write_at_op& other)
  368. : detail::base_from_completion_cond<CompletionCondition>(other),
  369. device_(other.device_),
  370. offset_(other.offset_),
  371. buffers_(other.buffers_),
  372. start_(other.start_),
  373. total_transferred_(other.total_transferred_),
  374. handler_(other.handler_)
  375. {
  376. }
  377. write_at_op(write_at_op&& other)
  378. : detail::base_from_completion_cond<CompletionCondition>(other),
  379. device_(other.device_),
  380. offset_(other.offset_),
  381. buffers_(other.buffers_),
  382. start_(other.start_),
  383. total_transferred_(other.total_transferred_),
  384. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  385. {
  386. }
  387. #endif // defined(BOOST_ASIO_HAS_MOVE)
  388. void operator()(const boost::system::error_code& ec,
  389. std::size_t bytes_transferred, int start = 0)
  390. {
  391. typename boost::asio::detail::dependent_type<Elem,
  392. boost::array<boost::asio::const_buffer, 2> >::type bufs = {{
  393. boost::asio::const_buffer(buffers_[0]),
  394. boost::asio::const_buffer(buffers_[1]) }};
  395. std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
  396. std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
  397. std::size_t n = 0;
  398. switch (start_ = start)
  399. {
  400. case 1:
  401. n = this->check_for_completion(ec, total_transferred_);
  402. for (;;)
  403. {
  404. bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
  405. bufs[1] = boost::asio::buffer(
  406. bufs[1] + (total_transferred_ < buffer_size0
  407. ? 0 : total_transferred_ - buffer_size0),
  408. n - boost::asio::buffer_size(bufs[0]));
  409. device_.async_write_some_at(offset_ + total_transferred_,
  410. bufs, BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
  411. return; default:
  412. total_transferred_ += bytes_transferred;
  413. if ((!ec && bytes_transferred == 0)
  414. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  415. || total_transferred_ == buffer_size0 + buffer_size1)
  416. break;
  417. }
  418. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  419. }
  420. }
  421. //private:
  422. AsyncRandomAccessWriteDevice& device_;
  423. uint64_t offset_;
  424. boost::array<Elem, 2> buffers_;
  425. int start_;
  426. std::size_t total_transferred_;
  427. WriteHandler handler_;
  428. };
  429. #if defined(BOOST_ASIO_HAS_STD_ARRAY)
  430. template <typename AsyncRandomAccessWriteDevice, typename Elem,
  431. typename CompletionCondition, typename WriteHandler>
  432. class write_at_op<AsyncRandomAccessWriteDevice, std::array<Elem, 2>,
  433. CompletionCondition, WriteHandler>
  434. : detail::base_from_completion_cond<CompletionCondition>
  435. {
  436. public:
  437. write_at_op(AsyncRandomAccessWriteDevice& device,
  438. uint64_t offset, const std::array<Elem, 2>& buffers,
  439. CompletionCondition completion_condition, WriteHandler& handler)
  440. : detail::base_from_completion_cond<
  441. CompletionCondition>(completion_condition),
  442. device_(device),
  443. offset_(offset),
  444. buffers_(buffers),
  445. start_(0),
  446. total_transferred_(0),
  447. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  448. {
  449. }
  450. #if defined(BOOST_ASIO_HAS_MOVE)
  451. write_at_op(const write_at_op& other)
  452. : detail::base_from_completion_cond<CompletionCondition>(other),
  453. device_(other.device_),
  454. offset_(other.offset_),
  455. buffers_(other.buffers_),
  456. start_(other.start_),
  457. total_transferred_(other.total_transferred_),
  458. handler_(other.handler_)
  459. {
  460. }
  461. write_at_op(write_at_op&& other)
  462. : detail::base_from_completion_cond<CompletionCondition>(other),
  463. device_(other.device_),
  464. offset_(other.offset_),
  465. buffers_(other.buffers_),
  466. start_(other.start_),
  467. total_transferred_(other.total_transferred_),
  468. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  469. {
  470. }
  471. #endif // defined(BOOST_ASIO_HAS_MOVE)
  472. void operator()(const boost::system::error_code& ec,
  473. std::size_t bytes_transferred, int start = 0)
  474. {
  475. typename boost::asio::detail::dependent_type<Elem,
  476. std::array<boost::asio::const_buffer, 2> >::type bufs = {{
  477. boost::asio::const_buffer(buffers_[0]),
  478. boost::asio::const_buffer(buffers_[1]) }};
  479. std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
  480. std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
  481. std::size_t n = 0;
  482. switch (start_ = start)
  483. {
  484. case 1:
  485. n = this->check_for_completion(ec, total_transferred_);
  486. for (;;)
  487. {
  488. bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
  489. bufs[1] = boost::asio::buffer(
  490. bufs[1] + (total_transferred_ < buffer_size0
  491. ? 0 : total_transferred_ - buffer_size0),
  492. n - boost::asio::buffer_size(bufs[0]));
  493. device_.async_write_some_at(offset_ + total_transferred_,
  494. bufs, BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
  495. return; default:
  496. total_transferred_ += bytes_transferred;
  497. if ((!ec && bytes_transferred == 0)
  498. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  499. || total_transferred_ == buffer_size0 + buffer_size1)
  500. break;
  501. }
  502. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  503. }
  504. }
  505. //private:
  506. AsyncRandomAccessWriteDevice& device_;
  507. uint64_t offset_;
  508. std::array<Elem, 2> buffers_;
  509. int start_;
  510. std::size_t total_transferred_;
  511. WriteHandler handler_;
  512. };
  513. #endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
  514. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  515. typename CompletionCondition, typename WriteHandler>
  516. inline void* asio_handler_allocate(std::size_t size,
  517. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  518. CompletionCondition, WriteHandler>* this_handler)
  519. {
  520. return boost_asio_handler_alloc_helpers::allocate(
  521. size, this_handler->handler_);
  522. }
  523. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  524. typename CompletionCondition, typename WriteHandler>
  525. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  526. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  527. CompletionCondition, WriteHandler>* this_handler)
  528. {
  529. boost_asio_handler_alloc_helpers::deallocate(
  530. pointer, size, this_handler->handler_);
  531. }
  532. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  533. typename CompletionCondition, typename WriteHandler>
  534. inline bool asio_handler_is_continuation(
  535. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  536. CompletionCondition, WriteHandler>* this_handler)
  537. {
  538. return this_handler->start_ == 0 ? true
  539. : boost_asio_handler_cont_helpers::is_continuation(
  540. this_handler->handler_);
  541. }
  542. template <typename Function, typename AsyncRandomAccessWriteDevice,
  543. typename ConstBufferSequence, typename CompletionCondition,
  544. typename WriteHandler>
  545. inline void asio_handler_invoke(Function& function,
  546. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  547. CompletionCondition, WriteHandler>* this_handler)
  548. {
  549. boost_asio_handler_invoke_helpers::invoke(
  550. function, this_handler->handler_);
  551. }
  552. template <typename Function, typename AsyncRandomAccessWriteDevice,
  553. typename ConstBufferSequence, typename CompletionCondition,
  554. typename WriteHandler>
  555. inline void asio_handler_invoke(const Function& function,
  556. write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  557. CompletionCondition, WriteHandler>* this_handler)
  558. {
  559. boost_asio_handler_invoke_helpers::invoke(
  560. function, this_handler->handler_);
  561. }
  562. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  563. typename CompletionCondition, typename WriteHandler>
  564. inline write_at_op<AsyncRandomAccessWriteDevice,
  565. ConstBufferSequence, CompletionCondition, WriteHandler>
  566. make_write_at_op(AsyncRandomAccessWriteDevice& d,
  567. uint64_t offset, const ConstBufferSequence& buffers,
  568. CompletionCondition completion_condition, WriteHandler handler)
  569. {
  570. return write_at_op<AsyncRandomAccessWriteDevice,
  571. ConstBufferSequence, CompletionCondition, WriteHandler>(
  572. d, offset, buffers, completion_condition, handler);
  573. }
  574. } // namespace detail
  575. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  576. typename CompletionCondition, typename WriteHandler>
  577. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  578. void (boost::system::error_code, std::size_t))
  579. async_write_at(AsyncRandomAccessWriteDevice& d,
  580. uint64_t offset, const ConstBufferSequence& buffers,
  581. CompletionCondition completion_condition,
  582. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  583. {
  584. // If you get an error on the following line it means that your handler does
  585. // not meet the documented type requirements for a WriteHandler.
  586. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  587. detail::async_result_init<
  588. WriteHandler, void (boost::system::error_code, std::size_t)> init(
  589. BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  590. detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  591. CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
  592. WriteHandler, void (boost::system::error_code, std::size_t))>(
  593. d, offset, buffers, completion_condition, init.handler)(
  594. boost::system::error_code(), 0, 1);
  595. return init.result.get();
  596. }
  597. template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
  598. typename WriteHandler>
  599. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  600. void (boost::system::error_code, std::size_t))
  601. async_write_at(AsyncRandomAccessWriteDevice& d,
  602. uint64_t offset, const ConstBufferSequence& buffers,
  603. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  604. {
  605. // If you get an error on the following line it means that your handler does
  606. // not meet the documented type requirements for a WriteHandler.
  607. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  608. detail::async_result_init<
  609. WriteHandler, void (boost::system::error_code, std::size_t)> init(
  610. BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  611. detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
  612. detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(
  613. WriteHandler, void (boost::system::error_code, std::size_t))>(
  614. d, offset, buffers, transfer_all(), init.handler)(
  615. boost::system::error_code(), 0, 1);
  616. return init.result.get();
  617. }
  618. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  619. namespace detail
  620. {
  621. template <typename Allocator, typename WriteHandler>
  622. class write_at_streambuf_op
  623. {
  624. public:
  625. write_at_streambuf_op(
  626. boost::asio::basic_streambuf<Allocator>& streambuf,
  627. WriteHandler& handler)
  628. : streambuf_(streambuf),
  629. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  630. {
  631. }
  632. #if defined(BOOST_ASIO_HAS_MOVE)
  633. write_at_streambuf_op(const write_at_streambuf_op& other)
  634. : streambuf_(other.streambuf_),
  635. handler_(other.handler_)
  636. {
  637. }
  638. write_at_streambuf_op(write_at_streambuf_op&& other)
  639. : streambuf_(other.streambuf_),
  640. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  641. {
  642. }
  643. #endif // defined(BOOST_ASIO_HAS_MOVE)
  644. void operator()(const boost::system::error_code& ec,
  645. const std::size_t bytes_transferred)
  646. {
  647. streambuf_.consume(bytes_transferred);
  648. handler_(ec, bytes_transferred);
  649. }
  650. //private:
  651. boost::asio::basic_streambuf<Allocator>& streambuf_;
  652. WriteHandler handler_;
  653. };
  654. template <typename Allocator, typename WriteHandler>
  655. inline void* asio_handler_allocate(std::size_t size,
  656. write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
  657. {
  658. return boost_asio_handler_alloc_helpers::allocate(
  659. size, this_handler->handler_);
  660. }
  661. template <typename Allocator, typename WriteHandler>
  662. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  663. write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
  664. {
  665. boost_asio_handler_alloc_helpers::deallocate(
  666. pointer, size, this_handler->handler_);
  667. }
  668. template <typename Allocator, typename WriteHandler>
  669. inline bool asio_handler_is_continuation(
  670. write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
  671. {
  672. return boost_asio_handler_cont_helpers::is_continuation(
  673. this_handler->handler_);
  674. }
  675. template <typename Function, typename Allocator, typename WriteHandler>
  676. inline void asio_handler_invoke(Function& function,
  677. write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
  678. {
  679. boost_asio_handler_invoke_helpers::invoke(
  680. function, this_handler->handler_);
  681. }
  682. template <typename Function, typename Allocator, typename WriteHandler>
  683. inline void asio_handler_invoke(const Function& function,
  684. write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
  685. {
  686. boost_asio_handler_invoke_helpers::invoke(
  687. function, this_handler->handler_);
  688. }
  689. template <typename Allocator, typename WriteHandler>
  690. inline write_at_streambuf_op<Allocator, WriteHandler>
  691. make_write_at_streambuf_op(
  692. boost::asio::basic_streambuf<Allocator>& b, WriteHandler handler)
  693. {
  694. return write_at_streambuf_op<Allocator, WriteHandler>(b, handler);
  695. }
  696. } // namespace detail
  697. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  698. typename CompletionCondition, typename WriteHandler>
  699. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  700. void (boost::system::error_code, std::size_t))
  701. async_write_at(AsyncRandomAccessWriteDevice& d,
  702. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  703. CompletionCondition completion_condition,
  704. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  705. {
  706. // If you get an error on the following line it means that your handler does
  707. // not meet the documented type requirements for a WriteHandler.
  708. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  709. detail::async_result_init<
  710. WriteHandler, void (boost::system::error_code, std::size_t)> init(
  711. BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  712. async_write_at(d, offset, b.data(), completion_condition,
  713. detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE(
  714. WriteHandler, void (boost::system::error_code, std::size_t))>(
  715. b, init.handler));
  716. return init.result.get();
  717. }
  718. template <typename AsyncRandomAccessWriteDevice, typename Allocator,
  719. typename WriteHandler>
  720. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  721. void (boost::system::error_code, std::size_t))
  722. async_write_at(AsyncRandomAccessWriteDevice& d,
  723. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  724. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  725. {
  726. // If you get an error on the following line it means that your handler does
  727. // not meet the documented type requirements for a WriteHandler.
  728. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  729. detail::async_result_init<
  730. WriteHandler, void (boost::system::error_code, std::size_t)> init(
  731. BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  732. async_write_at(d, offset, b.data(), transfer_all(),
  733. detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE(
  734. WriteHandler, void (boost::system::error_code, std::size_t))>(
  735. b, init.handler));
  736. return init.result.get();
  737. }
  738. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  739. } // namespace asio
  740. } // namespace boost
  741. #include <boost/asio/detail/pop_options.hpp>
  742. #endif // BOOST_ASIO_IMPL_WRITE_AT_HPP