Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

898 lines
30KB

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