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.

579 lines
20KB

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