write.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. //
  2. // impl/write.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 ASIO_IMPL_WRITE_HPP
  11. #define ASIO_IMPL_WRITE_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. namespace detail
  32. {
  33. template <typename SyncWriteStream, typename ConstBufferSequence,
  34. typename ConstBufferIterator, typename CompletionCondition>
  35. std::size_t write_buffer_sequence(SyncWriteStream& s,
  36. const ConstBufferSequence& buffers, const ConstBufferIterator&,
  37. CompletionCondition completion_condition, asio::error_code& ec)
  38. {
  39. ec = asio::error_code();
  40. asio::detail::consuming_buffers<const_buffer,
  41. ConstBufferSequence, ConstBufferIterator> tmp(buffers);
  42. while (!tmp.empty())
  43. {
  44. if (std::size_t max_size = detail::adapt_completion_condition_result(
  45. completion_condition(ec, tmp.total_consumed())))
  46. tmp.consume(s.write_some(tmp.prepare(max_size), ec));
  47. else
  48. break;
  49. }
  50. return tmp.total_consumed();;
  51. }
  52. } // namespace detail
  53. template <typename SyncWriteStream, typename ConstBufferSequence,
  54. typename CompletionCondition>
  55. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  56. CompletionCondition completion_condition, asio::error_code& ec,
  57. typename enable_if<
  58. is_const_buffer_sequence<ConstBufferSequence>::value
  59. >::type*)
  60. {
  61. return detail::write_buffer_sequence(s, buffers,
  62. asio::buffer_sequence_begin(buffers), completion_condition, ec);
  63. }
  64. template <typename SyncWriteStream, typename ConstBufferSequence>
  65. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  66. typename enable_if<
  67. is_const_buffer_sequence<ConstBufferSequence>::value
  68. >::type*)
  69. {
  70. asio::error_code ec;
  71. std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
  72. asio::detail::throw_error(ec, "write");
  73. return bytes_transferred;
  74. }
  75. template <typename SyncWriteStream, typename ConstBufferSequence>
  76. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  77. asio::error_code& ec,
  78. typename enable_if<
  79. is_const_buffer_sequence<ConstBufferSequence>::value
  80. >::type*)
  81. {
  82. return write(s, buffers, transfer_all(), ec);
  83. }
  84. template <typename SyncWriteStream, typename ConstBufferSequence,
  85. typename CompletionCondition>
  86. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  87. CompletionCondition completion_condition,
  88. typename enable_if<
  89. is_const_buffer_sequence<ConstBufferSequence>::value
  90. >::type*)
  91. {
  92. asio::error_code ec;
  93. std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
  94. asio::detail::throw_error(ec, "write");
  95. return bytes_transferred;
  96. }
  97. template <typename SyncWriteStream, typename DynamicBuffer,
  98. typename CompletionCondition>
  99. std::size_t write(SyncWriteStream& s,
  100. ASIO_MOVE_ARG(DynamicBuffer) buffers,
  101. CompletionCondition completion_condition, asio::error_code& ec,
  102. typename enable_if<
  103. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  104. >::type*)
  105. {
  106. typename decay<DynamicBuffer>::type b(
  107. ASIO_MOVE_CAST(DynamicBuffer)(buffers));
  108. std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
  109. b.consume(bytes_transferred);
  110. return bytes_transferred;
  111. }
  112. template <typename SyncWriteStream, typename DynamicBuffer>
  113. inline std::size_t write(SyncWriteStream& s,
  114. ASIO_MOVE_ARG(DynamicBuffer) buffers,
  115. typename enable_if<
  116. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  117. >::type*)
  118. {
  119. asio::error_code ec;
  120. std::size_t bytes_transferred = write(s,
  121. ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  122. transfer_all(), ec);
  123. asio::detail::throw_error(ec, "write");
  124. return bytes_transferred;
  125. }
  126. template <typename SyncWriteStream, typename DynamicBuffer>
  127. inline std::size_t write(SyncWriteStream& s,
  128. ASIO_MOVE_ARG(DynamicBuffer) buffers,
  129. asio::error_code& ec,
  130. typename enable_if<
  131. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  132. >::type*)
  133. {
  134. return write(s, ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  135. transfer_all(), ec);
  136. }
  137. template <typename SyncWriteStream, typename DynamicBuffer,
  138. typename CompletionCondition>
  139. inline std::size_t write(SyncWriteStream& s,
  140. ASIO_MOVE_ARG(DynamicBuffer) buffers,
  141. CompletionCondition completion_condition,
  142. typename enable_if<
  143. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  144. >::type*)
  145. {
  146. asio::error_code ec;
  147. std::size_t bytes_transferred = write(s,
  148. ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  149. completion_condition, ec);
  150. asio::detail::throw_error(ec, "write");
  151. return bytes_transferred;
  152. }
  153. #if !defined(ASIO_NO_EXTENSIONS)
  154. #if !defined(ASIO_NO_IOSTREAM)
  155. template <typename SyncWriteStream, typename Allocator,
  156. typename CompletionCondition>
  157. inline std::size_t write(SyncWriteStream& s,
  158. asio::basic_streambuf<Allocator>& b,
  159. CompletionCondition completion_condition, asio::error_code& ec)
  160. {
  161. return write(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec);
  162. }
  163. template <typename SyncWriteStream, typename Allocator>
  164. inline std::size_t write(SyncWriteStream& s,
  165. asio::basic_streambuf<Allocator>& b)
  166. {
  167. return write(s, basic_streambuf_ref<Allocator>(b));
  168. }
  169. template <typename SyncWriteStream, typename Allocator>
  170. inline std::size_t write(SyncWriteStream& s,
  171. asio::basic_streambuf<Allocator>& b,
  172. asio::error_code& ec)
  173. {
  174. return write(s, basic_streambuf_ref<Allocator>(b), ec);
  175. }
  176. template <typename SyncWriteStream, typename Allocator,
  177. typename CompletionCondition>
  178. inline std::size_t write(SyncWriteStream& s,
  179. asio::basic_streambuf<Allocator>& b,
  180. CompletionCondition completion_condition)
  181. {
  182. return write(s, basic_streambuf_ref<Allocator>(b), completion_condition);
  183. }
  184. #endif // !defined(ASIO_NO_IOSTREAM)
  185. #endif // !defined(ASIO_NO_EXTENSIONS)
  186. namespace detail
  187. {
  188. template <typename AsyncWriteStream, typename ConstBufferSequence,
  189. typename ConstBufferIterator, typename CompletionCondition,
  190. typename WriteHandler>
  191. class write_op
  192. : detail::base_from_completion_cond<CompletionCondition>
  193. {
  194. public:
  195. write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
  196. CompletionCondition completion_condition, WriteHandler& handler)
  197. : detail::base_from_completion_cond<
  198. CompletionCondition>(completion_condition),
  199. stream_(stream),
  200. buffers_(buffers),
  201. start_(0),
  202. handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
  203. {
  204. }
  205. #if defined(ASIO_HAS_MOVE)
  206. write_op(const write_op& other)
  207. : detail::base_from_completion_cond<CompletionCondition>(other),
  208. stream_(other.stream_),
  209. buffers_(other.buffers_),
  210. start_(other.start_),
  211. handler_(other.handler_)
  212. {
  213. }
  214. write_op(write_op&& other)
  215. : detail::base_from_completion_cond<CompletionCondition>(other),
  216. stream_(other.stream_),
  217. buffers_(other.buffers_),
  218. start_(other.start_),
  219. handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  220. {
  221. }
  222. #endif // defined(ASIO_HAS_MOVE)
  223. void operator()(const asio::error_code& ec,
  224. std::size_t bytes_transferred, int start = 0)
  225. {
  226. std::size_t max_size;
  227. switch (start_ = start)
  228. {
  229. case 1:
  230. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  231. do
  232. {
  233. stream_.async_write_some(buffers_.prepare(max_size),
  234. ASIO_MOVE_CAST(write_op)(*this));
  235. return; default:
  236. buffers_.consume(bytes_transferred);
  237. if ((!ec && bytes_transferred == 0) || buffers_.empty())
  238. break;
  239. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  240. } while (max_size > 0);
  241. handler_(ec, buffers_.total_consumed());
  242. }
  243. }
  244. //private:
  245. AsyncWriteStream& stream_;
  246. asio::detail::consuming_buffers<const_buffer,
  247. ConstBufferSequence, ConstBufferIterator> buffers_;
  248. int start_;
  249. WriteHandler handler_;
  250. };
  251. template <typename AsyncWriteStream, typename ConstBufferSequence,
  252. typename ConstBufferIterator, typename CompletionCondition,
  253. typename WriteHandler>
  254. inline void* asio_handler_allocate(std::size_t size,
  255. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  256. CompletionCondition, WriteHandler>* this_handler)
  257. {
  258. return asio_handler_alloc_helpers::allocate(
  259. size, this_handler->handler_);
  260. }
  261. template <typename AsyncWriteStream, typename ConstBufferSequence,
  262. typename ConstBufferIterator, typename CompletionCondition,
  263. typename WriteHandler>
  264. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  265. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  266. CompletionCondition, WriteHandler>* this_handler)
  267. {
  268. asio_handler_alloc_helpers::deallocate(
  269. pointer, size, this_handler->handler_);
  270. }
  271. template <typename AsyncWriteStream, typename ConstBufferSequence,
  272. typename ConstBufferIterator, typename CompletionCondition,
  273. typename WriteHandler>
  274. inline bool asio_handler_is_continuation(
  275. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  276. CompletionCondition, WriteHandler>* this_handler)
  277. {
  278. return this_handler->start_ == 0 ? true
  279. : asio_handler_cont_helpers::is_continuation(
  280. this_handler->handler_);
  281. }
  282. template <typename Function, typename AsyncWriteStream,
  283. typename ConstBufferSequence, typename ConstBufferIterator,
  284. typename CompletionCondition, typename WriteHandler>
  285. inline void asio_handler_invoke(Function& function,
  286. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  287. CompletionCondition, WriteHandler>* this_handler)
  288. {
  289. asio_handler_invoke_helpers::invoke(
  290. function, this_handler->handler_);
  291. }
  292. template <typename Function, typename AsyncWriteStream,
  293. typename ConstBufferSequence, typename ConstBufferIterator,
  294. typename CompletionCondition, typename WriteHandler>
  295. inline void asio_handler_invoke(const Function& function,
  296. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  297. CompletionCondition, WriteHandler>* this_handler)
  298. {
  299. asio_handler_invoke_helpers::invoke(
  300. function, this_handler->handler_);
  301. }
  302. template <typename AsyncWriteStream, typename ConstBufferSequence,
  303. typename ConstBufferIterator, typename CompletionCondition,
  304. typename WriteHandler>
  305. inline void start_write_buffer_sequence_op(AsyncWriteStream& stream,
  306. const ConstBufferSequence& buffers, const ConstBufferIterator&,
  307. CompletionCondition completion_condition, WriteHandler& handler)
  308. {
  309. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  310. ConstBufferIterator, CompletionCondition, WriteHandler>(
  311. stream, buffers, completion_condition, handler)(
  312. asio::error_code(), 0, 1);
  313. }
  314. } // namespace detail
  315. #if !defined(GENERATING_DOCUMENTATION)
  316. template <typename AsyncWriteStream, typename ConstBufferSequence,
  317. typename ConstBufferIterator, typename CompletionCondition,
  318. typename WriteHandler, typename Allocator>
  319. struct associated_allocator<
  320. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  321. ConstBufferIterator, CompletionCondition, WriteHandler>,
  322. Allocator>
  323. {
  324. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  325. static type get(
  326. const detail::write_op<AsyncWriteStream, ConstBufferSequence,
  327. ConstBufferIterator, CompletionCondition, WriteHandler>& h,
  328. const Allocator& a = Allocator()) ASIO_NOEXCEPT
  329. {
  330. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  331. }
  332. };
  333. template <typename AsyncWriteStream, typename ConstBufferSequence,
  334. typename ConstBufferIterator, typename CompletionCondition,
  335. typename WriteHandler, typename Executor>
  336. struct associated_executor<
  337. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  338. ConstBufferIterator, CompletionCondition, WriteHandler>,
  339. Executor>
  340. {
  341. typedef typename associated_executor<WriteHandler, Executor>::type type;
  342. static type get(
  343. const detail::write_op<AsyncWriteStream, ConstBufferSequence,
  344. ConstBufferIterator, CompletionCondition, WriteHandler>& h,
  345. const Executor& ex = Executor()) ASIO_NOEXCEPT
  346. {
  347. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  348. }
  349. };
  350. #endif // !defined(GENERATING_DOCUMENTATION)
  351. template <typename AsyncWriteStream, typename ConstBufferSequence,
  352. typename CompletionCondition, typename WriteHandler>
  353. inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
  354. void (asio::error_code, std::size_t))
  355. async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  356. CompletionCondition completion_condition,
  357. ASIO_MOVE_ARG(WriteHandler) handler,
  358. typename enable_if<
  359. is_const_buffer_sequence<ConstBufferSequence>::value
  360. >::type*)
  361. {
  362. // If you get an error on the following line it means that your handler does
  363. // not meet the documented type requirements for a WriteHandler.
  364. ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  365. async_completion<WriteHandler,
  366. void (asio::error_code, std::size_t)> init(handler);
  367. detail::start_write_buffer_sequence_op(s, buffers,
  368. asio::buffer_sequence_begin(buffers), completion_condition,
  369. init.completion_handler);
  370. return init.result.get();
  371. }
  372. template <typename AsyncWriteStream, typename ConstBufferSequence,
  373. typename WriteHandler>
  374. inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
  375. void (asio::error_code, std::size_t))
  376. async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  377. ASIO_MOVE_ARG(WriteHandler) handler,
  378. typename enable_if<
  379. is_const_buffer_sequence<ConstBufferSequence>::value
  380. >::type*)
  381. {
  382. // If you get an error on the following line it means that your handler does
  383. // not meet the documented type requirements for a WriteHandler.
  384. ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  385. async_completion<WriteHandler,
  386. void (asio::error_code, std::size_t)> init(handler);
  387. detail::start_write_buffer_sequence_op(s, buffers,
  388. asio::buffer_sequence_begin(buffers), transfer_all(),
  389. init.completion_handler);
  390. return init.result.get();
  391. }
  392. namespace detail
  393. {
  394. template <typename AsyncWriteStream, typename DynamicBuffer,
  395. typename CompletionCondition, typename WriteHandler>
  396. class write_dynbuf_op
  397. {
  398. public:
  399. template <typename BufferSequence>
  400. write_dynbuf_op(AsyncWriteStream& stream,
  401. ASIO_MOVE_ARG(BufferSequence) buffers,
  402. CompletionCondition completion_condition, WriteHandler& handler)
  403. : stream_(stream),
  404. buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
  405. completion_condition_(
  406. ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
  407. handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
  408. {
  409. }
  410. #if defined(ASIO_HAS_MOVE)
  411. write_dynbuf_op(const write_dynbuf_op& other)
  412. : stream_(other.stream_),
  413. buffers_(other.buffers_),
  414. completion_condition_(other.completion_condition_),
  415. handler_(other.handler_)
  416. {
  417. }
  418. write_dynbuf_op(write_dynbuf_op&& other)
  419. : stream_(other.stream_),
  420. buffers_(ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
  421. completion_condition_(
  422. ASIO_MOVE_CAST(CompletionCondition)(
  423. other.completion_condition_)),
  424. handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  425. {
  426. }
  427. #endif // defined(ASIO_HAS_MOVE)
  428. void operator()(const asio::error_code& ec,
  429. std::size_t bytes_transferred, int start = 0)
  430. {
  431. switch (start)
  432. {
  433. case 1:
  434. async_write(stream_, buffers_.data(), completion_condition_,
  435. ASIO_MOVE_CAST(write_dynbuf_op)(*this));
  436. return; default:
  437. buffers_.consume(bytes_transferred);
  438. handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
  439. }
  440. }
  441. //private:
  442. AsyncWriteStream& stream_;
  443. DynamicBuffer buffers_;
  444. CompletionCondition completion_condition_;
  445. WriteHandler handler_;
  446. };
  447. template <typename AsyncWriteStream, typename DynamicBuffer,
  448. typename CompletionCondition, typename WriteHandler>
  449. inline void* asio_handler_allocate(std::size_t size,
  450. write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
  451. CompletionCondition, WriteHandler>* this_handler)
  452. {
  453. return asio_handler_alloc_helpers::allocate(
  454. size, this_handler->handler_);
  455. }
  456. template <typename AsyncWriteStream, typename DynamicBuffer,
  457. typename CompletionCondition, typename WriteHandler>
  458. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  459. write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
  460. CompletionCondition, WriteHandler>* this_handler)
  461. {
  462. asio_handler_alloc_helpers::deallocate(
  463. pointer, size, this_handler->handler_);
  464. }
  465. template <typename AsyncWriteStream, typename DynamicBuffer,
  466. typename CompletionCondition, typename WriteHandler>
  467. inline bool asio_handler_is_continuation(
  468. write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
  469. CompletionCondition, WriteHandler>* this_handler)
  470. {
  471. return asio_handler_cont_helpers::is_continuation(
  472. this_handler->handler_);
  473. }
  474. template <typename Function, typename AsyncWriteStream,
  475. typename DynamicBuffer, typename CompletionCondition,
  476. typename WriteHandler>
  477. inline void asio_handler_invoke(Function& function,
  478. write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
  479. CompletionCondition, WriteHandler>* this_handler)
  480. {
  481. asio_handler_invoke_helpers::invoke(
  482. function, this_handler->handler_);
  483. }
  484. template <typename Function, typename AsyncWriteStream,
  485. typename DynamicBuffer, typename CompletionCondition,
  486. typename WriteHandler>
  487. inline void asio_handler_invoke(const Function& function,
  488. write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
  489. CompletionCondition, WriteHandler>* this_handler)
  490. {
  491. asio_handler_invoke_helpers::invoke(
  492. function, this_handler->handler_);
  493. }
  494. } // namespace detail
  495. #if !defined(GENERATING_DOCUMENTATION)
  496. template <typename AsyncWriteStream, typename DynamicBuffer,
  497. typename CompletionCondition, typename WriteHandler, typename Allocator>
  498. struct associated_allocator<
  499. detail::write_dynbuf_op<AsyncWriteStream,
  500. DynamicBuffer, CompletionCondition, WriteHandler>,
  501. Allocator>
  502. {
  503. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  504. static type get(
  505. const detail::write_dynbuf_op<AsyncWriteStream,
  506. DynamicBuffer, CompletionCondition, WriteHandler>& h,
  507. const Allocator& a = Allocator()) ASIO_NOEXCEPT
  508. {
  509. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  510. }
  511. };
  512. template <typename AsyncWriteStream, typename DynamicBuffer,
  513. typename CompletionCondition, typename WriteHandler, typename Executor>
  514. struct associated_executor<
  515. detail::write_dynbuf_op<AsyncWriteStream,
  516. DynamicBuffer, CompletionCondition, WriteHandler>,
  517. Executor>
  518. {
  519. typedef typename associated_executor<WriteHandler, Executor>::type type;
  520. static type get(
  521. const detail::write_dynbuf_op<AsyncWriteStream,
  522. DynamicBuffer, CompletionCondition, WriteHandler>& h,
  523. const Executor& ex = Executor()) ASIO_NOEXCEPT
  524. {
  525. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  526. }
  527. };
  528. #endif // !defined(GENERATING_DOCUMENTATION)
  529. template <typename AsyncWriteStream,
  530. typename DynamicBuffer, typename WriteHandler>
  531. inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
  532. void (asio::error_code, std::size_t))
  533. async_write(AsyncWriteStream& s,
  534. ASIO_MOVE_ARG(DynamicBuffer) buffers,
  535. ASIO_MOVE_ARG(WriteHandler) handler,
  536. typename enable_if<
  537. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  538. >::type*)
  539. {
  540. return async_write(s,
  541. ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  542. transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler));
  543. }
  544. template <typename AsyncWriteStream, typename DynamicBuffer,
  545. typename CompletionCondition, typename WriteHandler>
  546. inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
  547. void (asio::error_code, std::size_t))
  548. async_write(AsyncWriteStream& s,
  549. ASIO_MOVE_ARG(DynamicBuffer) buffers,
  550. CompletionCondition completion_condition,
  551. ASIO_MOVE_ARG(WriteHandler) handler,
  552. typename enable_if<
  553. is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
  554. >::type*)
  555. {
  556. // If you get an error on the following line it means that your handler does
  557. // not meet the documented type requirements for a WriteHandler.
  558. ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  559. async_completion<WriteHandler,
  560. void (asio::error_code, std::size_t)> init(handler);
  561. detail::write_dynbuf_op<AsyncWriteStream,
  562. typename decay<DynamicBuffer>::type,
  563. CompletionCondition, ASIO_HANDLER_TYPE(
  564. WriteHandler, void (asio::error_code, std::size_t))>(
  565. s, ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  566. completion_condition, init.completion_handler)(
  567. asio::error_code(), 0, 1);
  568. return init.result.get();
  569. }
  570. #if !defined(ASIO_NO_EXTENSIONS)
  571. #if !defined(ASIO_NO_IOSTREAM)
  572. template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
  573. inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
  574. void (asio::error_code, std::size_t))
  575. async_write(AsyncWriteStream& s,
  576. asio::basic_streambuf<Allocator>& b,
  577. ASIO_MOVE_ARG(WriteHandler) handler)
  578. {
  579. return async_write(s, basic_streambuf_ref<Allocator>(b),
  580. ASIO_MOVE_CAST(WriteHandler)(handler));
  581. }
  582. template <typename AsyncWriteStream, typename Allocator,
  583. typename CompletionCondition, typename WriteHandler>
  584. inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
  585. void (asio::error_code, std::size_t))
  586. async_write(AsyncWriteStream& s,
  587. asio::basic_streambuf<Allocator>& b,
  588. CompletionCondition completion_condition,
  589. ASIO_MOVE_ARG(WriteHandler) handler)
  590. {
  591. return async_write(s, basic_streambuf_ref<Allocator>(b),
  592. completion_condition, ASIO_MOVE_CAST(WriteHandler)(handler));
  593. }
  594. #endif // !defined(ASIO_NO_IOSTREAM)
  595. #endif // !defined(ASIO_NO_EXTENSIONS)
  596. } // namespace asio
  597. #include "asio/detail/pop_options.hpp"
  598. #endif // ASIO_IMPL_WRITE_HPP