write.hpp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. //
  2. // impl/write.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 BOOST_ASIO_IMPL_WRITE_HPP
  11. #define BOOST_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 <boost/asio/associated_allocator.hpp>
  16. #include <boost/asio/associated_executor.hpp>
  17. #include <boost/asio/buffer.hpp>
  18. #include <boost/asio/completion_condition.hpp>
  19. #include <boost/asio/detail/array_fwd.hpp>
  20. #include <boost/asio/detail/base_from_completion_cond.hpp>
  21. #include <boost/asio/detail/bind_handler.hpp>
  22. #include <boost/asio/detail/consuming_buffers.hpp>
  23. #include <boost/asio/detail/dependent_type.hpp>
  24. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  25. #include <boost/asio/detail/handler_cont_helpers.hpp>
  26. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  27. #include <boost/asio/detail/handler_type_requirements.hpp>
  28. #include <boost/asio/detail/non_const_lvalue.hpp>
  29. #include <boost/asio/detail/throw_error.hpp>
  30. #include <boost/asio/detail/push_options.hpp>
  31. namespace boost {
  32. namespace asio {
  33. namespace detail
  34. {
  35. template <typename SyncWriteStream, typename ConstBufferSequence,
  36. typename ConstBufferIterator, typename CompletionCondition>
  37. std::size_t write_buffer_sequence(SyncWriteStream& s,
  38. const ConstBufferSequence& buffers, const ConstBufferIterator&,
  39. CompletionCondition completion_condition, boost::system::error_code& ec)
  40. {
  41. ec = boost::system::error_code();
  42. boost::asio::detail::consuming_buffers<const_buffer,
  43. ConstBufferSequence, ConstBufferIterator> tmp(buffers);
  44. while (!tmp.empty())
  45. {
  46. if (std::size_t max_size = detail::adapt_completion_condition_result(
  47. completion_condition(ec, tmp.total_consumed())))
  48. tmp.consume(s.write_some(tmp.prepare(max_size), ec));
  49. else
  50. break;
  51. }
  52. return tmp.total_consumed();;
  53. }
  54. } // namespace detail
  55. template <typename SyncWriteStream, typename ConstBufferSequence,
  56. typename CompletionCondition>
  57. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  58. CompletionCondition completion_condition, boost::system::error_code& ec,
  59. typename enable_if<
  60. is_const_buffer_sequence<ConstBufferSequence>::value
  61. >::type*)
  62. {
  63. return detail::write_buffer_sequence(s, buffers,
  64. boost::asio::buffer_sequence_begin(buffers),
  65. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  66. }
  67. template <typename SyncWriteStream, typename ConstBufferSequence>
  68. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  69. typename enable_if<
  70. is_const_buffer_sequence<ConstBufferSequence>::value
  71. >::type*)
  72. {
  73. boost::system::error_code ec;
  74. std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
  75. boost::asio::detail::throw_error(ec, "write");
  76. return bytes_transferred;
  77. }
  78. template <typename SyncWriteStream, typename ConstBufferSequence>
  79. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  80. boost::system::error_code& ec,
  81. typename enable_if<
  82. is_const_buffer_sequence<ConstBufferSequence>::value
  83. >::type*)
  84. {
  85. return write(s, buffers, transfer_all(), ec);
  86. }
  87. template <typename SyncWriteStream, typename ConstBufferSequence,
  88. typename CompletionCondition>
  89. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  90. CompletionCondition completion_condition,
  91. typename enable_if<
  92. is_const_buffer_sequence<ConstBufferSequence>::value
  93. >::type*)
  94. {
  95. boost::system::error_code ec;
  96. std::size_t bytes_transferred = write(s, buffers,
  97. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  98. boost::asio::detail::throw_error(ec, "write");
  99. return bytes_transferred;
  100. }
  101. #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  102. template <typename SyncWriteStream, typename DynamicBuffer_v1,
  103. typename CompletionCondition>
  104. std::size_t write(SyncWriteStream& s,
  105. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  106. CompletionCondition completion_condition, boost::system::error_code& ec,
  107. typename enable_if<
  108. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  109. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  110. >::type*)
  111. {
  112. typename decay<DynamicBuffer_v1>::type b(
  113. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
  114. std::size_t bytes_transferred = write(s, b.data(),
  115. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  116. b.consume(bytes_transferred);
  117. return bytes_transferred;
  118. }
  119. template <typename SyncWriteStream, typename DynamicBuffer_v1>
  120. inline std::size_t write(SyncWriteStream& s,
  121. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  122. typename enable_if<
  123. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  124. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  125. >::type*)
  126. {
  127. boost::system::error_code ec;
  128. std::size_t bytes_transferred = write(s,
  129. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  130. transfer_all(), ec);
  131. boost::asio::detail::throw_error(ec, "write");
  132. return bytes_transferred;
  133. }
  134. template <typename SyncWriteStream, typename DynamicBuffer_v1>
  135. inline std::size_t write(SyncWriteStream& s,
  136. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  137. boost::system::error_code& ec,
  138. typename enable_if<
  139. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  140. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  141. >::type*)
  142. {
  143. return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  144. transfer_all(), ec);
  145. }
  146. template <typename SyncWriteStream, typename DynamicBuffer_v1,
  147. typename CompletionCondition>
  148. inline std::size_t write(SyncWriteStream& s,
  149. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  150. CompletionCondition completion_condition,
  151. typename enable_if<
  152. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  153. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  154. >::type*)
  155. {
  156. boost::system::error_code ec;
  157. std::size_t bytes_transferred = write(s,
  158. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  159. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  160. boost::asio::detail::throw_error(ec, "write");
  161. return bytes_transferred;
  162. }
  163. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  164. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  165. template <typename SyncWriteStream, typename Allocator,
  166. typename CompletionCondition>
  167. inline std::size_t write(SyncWriteStream& s,
  168. boost::asio::basic_streambuf<Allocator>& b,
  169. CompletionCondition completion_condition, boost::system::error_code& ec)
  170. {
  171. return write(s, basic_streambuf_ref<Allocator>(b),
  172. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  173. }
  174. template <typename SyncWriteStream, typename Allocator>
  175. inline std::size_t write(SyncWriteStream& s,
  176. boost::asio::basic_streambuf<Allocator>& b)
  177. {
  178. return write(s, basic_streambuf_ref<Allocator>(b));
  179. }
  180. template <typename SyncWriteStream, typename Allocator>
  181. inline std::size_t write(SyncWriteStream& s,
  182. boost::asio::basic_streambuf<Allocator>& b,
  183. boost::system::error_code& ec)
  184. {
  185. return write(s, basic_streambuf_ref<Allocator>(b), ec);
  186. }
  187. template <typename SyncWriteStream, typename Allocator,
  188. typename CompletionCondition>
  189. inline std::size_t write(SyncWriteStream& s,
  190. boost::asio::basic_streambuf<Allocator>& b,
  191. CompletionCondition completion_condition)
  192. {
  193. return write(s, basic_streambuf_ref<Allocator>(b),
  194. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  195. }
  196. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  197. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  198. #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  199. template <typename SyncWriteStream, typename DynamicBuffer_v2,
  200. typename CompletionCondition>
  201. std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  202. CompletionCondition completion_condition, boost::system::error_code& ec,
  203. typename enable_if<
  204. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  205. >::type*)
  206. {
  207. std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()),
  208. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  209. buffers.consume(bytes_transferred);
  210. return bytes_transferred;
  211. }
  212. template <typename SyncWriteStream, typename DynamicBuffer_v2>
  213. inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  214. typename enable_if<
  215. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  216. >::type*)
  217. {
  218. boost::system::error_code ec;
  219. std::size_t bytes_transferred = write(s,
  220. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  221. transfer_all(), ec);
  222. boost::asio::detail::throw_error(ec, "write");
  223. return bytes_transferred;
  224. }
  225. template <typename SyncWriteStream, typename DynamicBuffer_v2>
  226. inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  227. boost::system::error_code& ec,
  228. typename enable_if<
  229. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  230. >::type*)
  231. {
  232. return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  233. transfer_all(), ec);
  234. }
  235. template <typename SyncWriteStream, typename DynamicBuffer_v2,
  236. typename CompletionCondition>
  237. inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  238. CompletionCondition completion_condition,
  239. typename enable_if<
  240. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  241. >::type*)
  242. {
  243. boost::system::error_code ec;
  244. std::size_t bytes_transferred = write(s,
  245. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  246. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  247. boost::asio::detail::throw_error(ec, "write");
  248. return bytes_transferred;
  249. }
  250. namespace detail
  251. {
  252. template <typename AsyncWriteStream, typename ConstBufferSequence,
  253. typename ConstBufferIterator, typename CompletionCondition,
  254. typename WriteHandler>
  255. class write_op
  256. : detail::base_from_completion_cond<CompletionCondition>
  257. {
  258. public:
  259. write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
  260. CompletionCondition& completion_condition, WriteHandler& handler)
  261. : detail::base_from_completion_cond<
  262. CompletionCondition>(completion_condition),
  263. stream_(stream),
  264. buffers_(buffers),
  265. start_(0),
  266. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  267. {
  268. }
  269. #if defined(BOOST_ASIO_HAS_MOVE)
  270. write_op(const write_op& other)
  271. : detail::base_from_completion_cond<CompletionCondition>(other),
  272. stream_(other.stream_),
  273. buffers_(other.buffers_),
  274. start_(other.start_),
  275. handler_(other.handler_)
  276. {
  277. }
  278. write_op(write_op&& other)
  279. : detail::base_from_completion_cond<CompletionCondition>(
  280. BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
  281. CompletionCondition>)(other)),
  282. stream_(other.stream_),
  283. buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
  284. start_(other.start_),
  285. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  286. {
  287. }
  288. #endif // defined(BOOST_ASIO_HAS_MOVE)
  289. void operator()(const boost::system::error_code& ec,
  290. std::size_t bytes_transferred, int start = 0)
  291. {
  292. std::size_t max_size;
  293. switch (start_ = start)
  294. {
  295. case 1:
  296. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  297. do
  298. {
  299. stream_.async_write_some(buffers_.prepare(max_size),
  300. BOOST_ASIO_MOVE_CAST(write_op)(*this));
  301. return; default:
  302. buffers_.consume(bytes_transferred);
  303. if ((!ec && bytes_transferred == 0) || buffers_.empty())
  304. break;
  305. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  306. } while (max_size > 0);
  307. handler_(ec, buffers_.total_consumed());
  308. }
  309. }
  310. //private:
  311. typedef boost::asio::detail::consuming_buffers<const_buffer,
  312. ConstBufferSequence, ConstBufferIterator> buffers_type;
  313. AsyncWriteStream& stream_;
  314. buffers_type buffers_;
  315. int start_;
  316. WriteHandler handler_;
  317. };
  318. template <typename AsyncWriteStream, typename ConstBufferSequence,
  319. typename ConstBufferIterator, typename CompletionCondition,
  320. typename WriteHandler>
  321. inline void* asio_handler_allocate(std::size_t size,
  322. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  323. CompletionCondition, WriteHandler>* this_handler)
  324. {
  325. return boost_asio_handler_alloc_helpers::allocate(
  326. size, this_handler->handler_);
  327. }
  328. template <typename AsyncWriteStream, typename ConstBufferSequence,
  329. typename ConstBufferIterator, typename CompletionCondition,
  330. typename WriteHandler>
  331. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  332. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  333. CompletionCondition, WriteHandler>* this_handler)
  334. {
  335. boost_asio_handler_alloc_helpers::deallocate(
  336. pointer, size, this_handler->handler_);
  337. }
  338. template <typename AsyncWriteStream, typename ConstBufferSequence,
  339. typename ConstBufferIterator, typename CompletionCondition,
  340. typename WriteHandler>
  341. inline bool asio_handler_is_continuation(
  342. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  343. CompletionCondition, WriteHandler>* this_handler)
  344. {
  345. return this_handler->start_ == 0 ? true
  346. : boost_asio_handler_cont_helpers::is_continuation(
  347. this_handler->handler_);
  348. }
  349. template <typename Function, typename AsyncWriteStream,
  350. typename ConstBufferSequence, typename ConstBufferIterator,
  351. typename CompletionCondition, typename WriteHandler>
  352. inline void asio_handler_invoke(Function& function,
  353. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  354. CompletionCondition, WriteHandler>* this_handler)
  355. {
  356. boost_asio_handler_invoke_helpers::invoke(
  357. function, this_handler->handler_);
  358. }
  359. template <typename Function, typename AsyncWriteStream,
  360. typename ConstBufferSequence, typename ConstBufferIterator,
  361. typename CompletionCondition, typename WriteHandler>
  362. inline void asio_handler_invoke(const Function& function,
  363. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  364. CompletionCondition, WriteHandler>* this_handler)
  365. {
  366. boost_asio_handler_invoke_helpers::invoke(
  367. function, this_handler->handler_);
  368. }
  369. template <typename AsyncWriteStream, typename ConstBufferSequence,
  370. typename ConstBufferIterator, typename CompletionCondition,
  371. typename WriteHandler>
  372. inline void start_write_buffer_sequence_op(AsyncWriteStream& stream,
  373. const ConstBufferSequence& buffers, const ConstBufferIterator&,
  374. CompletionCondition& completion_condition, WriteHandler& handler)
  375. {
  376. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  377. ConstBufferIterator, CompletionCondition, WriteHandler>(
  378. stream, buffers, completion_condition, handler)(
  379. boost::system::error_code(), 0, 1);
  380. }
  381. template <typename AsyncWriteStream>
  382. class initiate_async_write_buffer_sequence
  383. {
  384. public:
  385. typedef typename AsyncWriteStream::executor_type executor_type;
  386. explicit initiate_async_write_buffer_sequence(AsyncWriteStream& stream)
  387. : stream_(stream)
  388. {
  389. }
  390. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  391. {
  392. return stream_.get_executor();
  393. }
  394. template <typename WriteHandler, typename ConstBufferSequence,
  395. typename CompletionCondition>
  396. void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  397. const ConstBufferSequence& buffers,
  398. BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  399. {
  400. // If you get an error on the following line it means that your handler
  401. // does not meet the documented type requirements for a WriteHandler.
  402. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  403. non_const_lvalue<WriteHandler> handler2(handler);
  404. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  405. start_write_buffer_sequence_op(stream_, buffers,
  406. boost::asio::buffer_sequence_begin(buffers),
  407. completion_cond2.value, handler2.value);
  408. }
  409. private:
  410. AsyncWriteStream& stream_;
  411. };
  412. } // namespace detail
  413. #if !defined(GENERATING_DOCUMENTATION)
  414. template <typename AsyncWriteStream, typename ConstBufferSequence,
  415. typename ConstBufferIterator, typename CompletionCondition,
  416. typename WriteHandler, typename Allocator>
  417. struct associated_allocator<
  418. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  419. ConstBufferIterator, CompletionCondition, WriteHandler>,
  420. Allocator>
  421. {
  422. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  423. static type get(
  424. const detail::write_op<AsyncWriteStream, ConstBufferSequence,
  425. ConstBufferIterator, CompletionCondition, WriteHandler>& h,
  426. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  427. {
  428. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  429. }
  430. };
  431. template <typename AsyncWriteStream, typename ConstBufferSequence,
  432. typename ConstBufferIterator, typename CompletionCondition,
  433. typename WriteHandler, typename Executor>
  434. struct associated_executor<
  435. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  436. ConstBufferIterator, CompletionCondition, WriteHandler>,
  437. Executor>
  438. {
  439. typedef typename associated_executor<WriteHandler, Executor>::type type;
  440. static type get(
  441. const detail::write_op<AsyncWriteStream, ConstBufferSequence,
  442. ConstBufferIterator, CompletionCondition, WriteHandler>& h,
  443. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  444. {
  445. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  446. }
  447. };
  448. #endif // !defined(GENERATING_DOCUMENTATION)
  449. template <typename AsyncWriteStream,
  450. typename ConstBufferSequence, typename CompletionCondition,
  451. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  452. std::size_t)) WriteHandler>
  453. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
  454. void (boost::system::error_code, std::size_t))
  455. async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  456. CompletionCondition completion_condition,
  457. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  458. typename enable_if<
  459. is_const_buffer_sequence<ConstBufferSequence>::value
  460. >::type*)
  461. {
  462. return async_initiate<WriteHandler,
  463. void (boost::system::error_code, std::size_t)>(
  464. detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s),
  465. handler, buffers,
  466. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  467. }
  468. template <typename AsyncWriteStream, typename ConstBufferSequence,
  469. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  470. std::size_t)) WriteHandler>
  471. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
  472. void (boost::system::error_code, std::size_t))
  473. async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  474. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  475. typename enable_if<
  476. is_const_buffer_sequence<ConstBufferSequence>::value
  477. >::type*)
  478. {
  479. return async_initiate<WriteHandler,
  480. void (boost::system::error_code, std::size_t)>(
  481. detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s),
  482. handler, buffers, transfer_all());
  483. }
  484. #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  485. namespace detail
  486. {
  487. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  488. typename CompletionCondition, typename WriteHandler>
  489. class write_dynbuf_v1_op
  490. {
  491. public:
  492. template <typename BufferSequence>
  493. write_dynbuf_v1_op(AsyncWriteStream& stream,
  494. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  495. CompletionCondition& completion_condition, WriteHandler& handler)
  496. : stream_(stream),
  497. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  498. completion_condition_(
  499. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
  500. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  501. {
  502. }
  503. #if defined(BOOST_ASIO_HAS_MOVE)
  504. write_dynbuf_v1_op(const write_dynbuf_v1_op& other)
  505. : stream_(other.stream_),
  506. buffers_(other.buffers_),
  507. completion_condition_(other.completion_condition_),
  508. handler_(other.handler_)
  509. {
  510. }
  511. write_dynbuf_v1_op(write_dynbuf_v1_op&& other)
  512. : stream_(other.stream_),
  513. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
  514. completion_condition_(
  515. BOOST_ASIO_MOVE_CAST(CompletionCondition)(
  516. other.completion_condition_)),
  517. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  518. {
  519. }
  520. #endif // defined(BOOST_ASIO_HAS_MOVE)
  521. void operator()(const boost::system::error_code& ec,
  522. std::size_t bytes_transferred, int start = 0)
  523. {
  524. switch (start)
  525. {
  526. case 1:
  527. async_write(stream_, buffers_.data(),
  528. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition_),
  529. BOOST_ASIO_MOVE_CAST(write_dynbuf_v1_op)(*this));
  530. return; default:
  531. buffers_.consume(bytes_transferred);
  532. handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
  533. }
  534. }
  535. //private:
  536. AsyncWriteStream& stream_;
  537. DynamicBuffer_v1 buffers_;
  538. CompletionCondition completion_condition_;
  539. WriteHandler handler_;
  540. };
  541. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  542. typename CompletionCondition, typename WriteHandler>
  543. inline void* asio_handler_allocate(std::size_t size,
  544. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  545. CompletionCondition, WriteHandler>* this_handler)
  546. {
  547. return boost_asio_handler_alloc_helpers::allocate(
  548. size, this_handler->handler_);
  549. }
  550. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  551. typename CompletionCondition, typename WriteHandler>
  552. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  553. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  554. CompletionCondition, WriteHandler>* this_handler)
  555. {
  556. boost_asio_handler_alloc_helpers::deallocate(
  557. pointer, size, this_handler->handler_);
  558. }
  559. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  560. typename CompletionCondition, typename WriteHandler>
  561. inline bool asio_handler_is_continuation(
  562. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  563. CompletionCondition, WriteHandler>* this_handler)
  564. {
  565. return boost_asio_handler_cont_helpers::is_continuation(
  566. this_handler->handler_);
  567. }
  568. template <typename Function, typename AsyncWriteStream,
  569. typename DynamicBuffer_v1, typename CompletionCondition,
  570. typename WriteHandler>
  571. inline void asio_handler_invoke(Function& function,
  572. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  573. CompletionCondition, WriteHandler>* this_handler)
  574. {
  575. boost_asio_handler_invoke_helpers::invoke(
  576. function, this_handler->handler_);
  577. }
  578. template <typename Function, typename AsyncWriteStream,
  579. typename DynamicBuffer_v1, typename CompletionCondition,
  580. typename WriteHandler>
  581. inline void asio_handler_invoke(const Function& function,
  582. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  583. CompletionCondition, WriteHandler>* this_handler)
  584. {
  585. boost_asio_handler_invoke_helpers::invoke(
  586. function, this_handler->handler_);
  587. }
  588. template <typename AsyncWriteStream>
  589. class initiate_async_write_dynbuf_v1
  590. {
  591. public:
  592. typedef typename AsyncWriteStream::executor_type executor_type;
  593. explicit initiate_async_write_dynbuf_v1(AsyncWriteStream& stream)
  594. : stream_(stream)
  595. {
  596. }
  597. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  598. {
  599. return stream_.get_executor();
  600. }
  601. template <typename WriteHandler, typename DynamicBuffer_v1,
  602. typename CompletionCondition>
  603. void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  604. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  605. BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  606. {
  607. // If you get an error on the following line it means that your handler
  608. // does not meet the documented type requirements for a WriteHandler.
  609. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  610. non_const_lvalue<WriteHandler> handler2(handler);
  611. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  612. write_dynbuf_v1_op<AsyncWriteStream,
  613. typename decay<DynamicBuffer_v1>::type,
  614. CompletionCondition, typename decay<WriteHandler>::type>(
  615. stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  616. completion_cond2.value, handler2.value)(
  617. boost::system::error_code(), 0, 1);
  618. }
  619. private:
  620. AsyncWriteStream& stream_;
  621. };
  622. } // namespace detail
  623. #if !defined(GENERATING_DOCUMENTATION)
  624. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  625. typename CompletionCondition, typename WriteHandler, typename Allocator>
  626. struct associated_allocator<
  627. detail::write_dynbuf_v1_op<AsyncWriteStream,
  628. DynamicBuffer_v1, CompletionCondition, WriteHandler>,
  629. Allocator>
  630. {
  631. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  632. static type get(
  633. const detail::write_dynbuf_v1_op<AsyncWriteStream,
  634. DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
  635. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  636. {
  637. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  638. }
  639. };
  640. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  641. typename CompletionCondition, typename WriteHandler, typename Executor>
  642. struct associated_executor<
  643. detail::write_dynbuf_v1_op<AsyncWriteStream,
  644. DynamicBuffer_v1, CompletionCondition, WriteHandler>,
  645. Executor>
  646. {
  647. typedef typename associated_executor<WriteHandler, Executor>::type type;
  648. static type get(
  649. const detail::write_dynbuf_v1_op<AsyncWriteStream,
  650. DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
  651. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  652. {
  653. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  654. }
  655. };
  656. #endif // !defined(GENERATING_DOCUMENTATION)
  657. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  658. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  659. std::size_t)) WriteHandler>
  660. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
  661. void (boost::system::error_code, std::size_t))
  662. async_write(AsyncWriteStream& s,
  663. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  664. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  665. typename enable_if<
  666. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  667. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  668. >::type*)
  669. {
  670. return async_write(s,
  671. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  672. transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  673. }
  674. template <typename AsyncWriteStream,
  675. typename DynamicBuffer_v1, typename CompletionCondition,
  676. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  677. std::size_t)) WriteHandler>
  678. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
  679. void (boost::system::error_code, std::size_t))
  680. async_write(AsyncWriteStream& s,
  681. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  682. CompletionCondition completion_condition,
  683. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  684. typename enable_if<
  685. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  686. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  687. >::type*)
  688. {
  689. return async_initiate<WriteHandler,
  690. void (boost::system::error_code, std::size_t)>(
  691. detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
  692. handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  693. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  694. }
  695. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  696. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  697. template <typename AsyncWriteStream, typename Allocator,
  698. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  699. std::size_t)) WriteHandler>
  700. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
  701. void (boost::system::error_code, std::size_t))
  702. async_write(AsyncWriteStream& s,
  703. boost::asio::basic_streambuf<Allocator>& b,
  704. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  705. {
  706. return async_write(s, basic_streambuf_ref<Allocator>(b),
  707. BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  708. }
  709. template <typename AsyncWriteStream,
  710. typename Allocator, typename CompletionCondition,
  711. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  712. std::size_t)) WriteHandler>
  713. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
  714. void (boost::system::error_code, std::size_t))
  715. async_write(AsyncWriteStream& s,
  716. boost::asio::basic_streambuf<Allocator>& b,
  717. CompletionCondition completion_condition,
  718. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  719. {
  720. return async_write(s, basic_streambuf_ref<Allocator>(b),
  721. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
  722. BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  723. }
  724. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  725. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  726. #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  727. namespace detail
  728. {
  729. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  730. typename CompletionCondition, typename WriteHandler>
  731. class write_dynbuf_v2_op
  732. {
  733. public:
  734. template <typename BufferSequence>
  735. write_dynbuf_v2_op(AsyncWriteStream& stream,
  736. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  737. CompletionCondition& completion_condition, WriteHandler& handler)
  738. : stream_(stream),
  739. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  740. completion_condition_(
  741. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
  742. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  743. {
  744. }
  745. #if defined(BOOST_ASIO_HAS_MOVE)
  746. write_dynbuf_v2_op(const write_dynbuf_v2_op& other)
  747. : stream_(other.stream_),
  748. buffers_(other.buffers_),
  749. completion_condition_(other.completion_condition_),
  750. handler_(other.handler_)
  751. {
  752. }
  753. write_dynbuf_v2_op(write_dynbuf_v2_op&& other)
  754. : stream_(other.stream_),
  755. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
  756. completion_condition_(
  757. BOOST_ASIO_MOVE_CAST(CompletionCondition)(
  758. other.completion_condition_)),
  759. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  760. {
  761. }
  762. #endif // defined(BOOST_ASIO_HAS_MOVE)
  763. void operator()(const boost::system::error_code& ec,
  764. std::size_t bytes_transferred, int start = 0)
  765. {
  766. switch (start)
  767. {
  768. case 1:
  769. async_write(stream_, buffers_.data(0, buffers_.size()),
  770. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition_),
  771. BOOST_ASIO_MOVE_CAST(write_dynbuf_v2_op)(*this));
  772. return; default:
  773. buffers_.consume(bytes_transferred);
  774. handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
  775. }
  776. }
  777. //private:
  778. AsyncWriteStream& stream_;
  779. DynamicBuffer_v2 buffers_;
  780. CompletionCondition completion_condition_;
  781. WriteHandler handler_;
  782. };
  783. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  784. typename CompletionCondition, typename WriteHandler>
  785. inline void* asio_handler_allocate(std::size_t size,
  786. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  787. CompletionCondition, WriteHandler>* this_handler)
  788. {
  789. return boost_asio_handler_alloc_helpers::allocate(
  790. size, this_handler->handler_);
  791. }
  792. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  793. typename CompletionCondition, typename WriteHandler>
  794. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  795. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  796. CompletionCondition, WriteHandler>* this_handler)
  797. {
  798. boost_asio_handler_alloc_helpers::deallocate(
  799. pointer, size, this_handler->handler_);
  800. }
  801. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  802. typename CompletionCondition, typename WriteHandler>
  803. inline bool asio_handler_is_continuation(
  804. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  805. CompletionCondition, WriteHandler>* this_handler)
  806. {
  807. return boost_asio_handler_cont_helpers::is_continuation(
  808. this_handler->handler_);
  809. }
  810. template <typename Function, typename AsyncWriteStream,
  811. typename DynamicBuffer_v2, typename CompletionCondition,
  812. typename WriteHandler>
  813. inline void asio_handler_invoke(Function& function,
  814. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  815. CompletionCondition, WriteHandler>* this_handler)
  816. {
  817. boost_asio_handler_invoke_helpers::invoke(
  818. function, this_handler->handler_);
  819. }
  820. template <typename Function, typename AsyncWriteStream,
  821. typename DynamicBuffer_v2, typename CompletionCondition,
  822. typename WriteHandler>
  823. inline void asio_handler_invoke(const Function& function,
  824. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  825. CompletionCondition, WriteHandler>* this_handler)
  826. {
  827. boost_asio_handler_invoke_helpers::invoke(
  828. function, this_handler->handler_);
  829. }
  830. template <typename AsyncWriteStream>
  831. class initiate_async_write_dynbuf_v2
  832. {
  833. public:
  834. typedef typename AsyncWriteStream::executor_type executor_type;
  835. explicit initiate_async_write_dynbuf_v2(AsyncWriteStream& stream)
  836. : stream_(stream)
  837. {
  838. }
  839. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  840. {
  841. return stream_.get_executor();
  842. }
  843. template <typename WriteHandler, typename DynamicBuffer_v2,
  844. typename CompletionCondition>
  845. void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  846. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
  847. BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  848. {
  849. // If you get an error on the following line it means that your handler
  850. // does not meet the documented type requirements for a WriteHandler.
  851. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  852. non_const_lvalue<WriteHandler> handler2(handler);
  853. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  854. write_dynbuf_v2_op<AsyncWriteStream,
  855. typename decay<DynamicBuffer_v2>::type,
  856. CompletionCondition, typename decay<WriteHandler>::type>(
  857. stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  858. completion_cond2.value, handler2.value)(
  859. boost::system::error_code(), 0, 1);
  860. }
  861. private:
  862. AsyncWriteStream& stream_;
  863. };
  864. } // namespace detail
  865. #if !defined(GENERATING_DOCUMENTATION)
  866. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  867. typename CompletionCondition, typename WriteHandler, typename Allocator>
  868. struct associated_allocator<
  869. detail::write_dynbuf_v2_op<AsyncWriteStream,
  870. DynamicBuffer_v2, CompletionCondition, WriteHandler>,
  871. Allocator>
  872. {
  873. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  874. static type get(
  875. const detail::write_dynbuf_v2_op<AsyncWriteStream,
  876. DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
  877. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  878. {
  879. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  880. }
  881. };
  882. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  883. typename CompletionCondition, typename WriteHandler, typename Executor>
  884. struct associated_executor<
  885. detail::write_dynbuf_v2_op<AsyncWriteStream,
  886. DynamicBuffer_v2, CompletionCondition, WriteHandler>,
  887. Executor>
  888. {
  889. typedef typename associated_executor<WriteHandler, Executor>::type type;
  890. static type get(
  891. const detail::write_dynbuf_v2_op<AsyncWriteStream,
  892. DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
  893. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  894. {
  895. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  896. }
  897. };
  898. #endif // !defined(GENERATING_DOCUMENTATION)
  899. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  900. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  901. std::size_t)) WriteHandler>
  902. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
  903. void (boost::system::error_code, std::size_t))
  904. async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
  905. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  906. typename enable_if<
  907. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  908. >::type*)
  909. {
  910. return async_write(s,
  911. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  912. transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  913. }
  914. template <typename AsyncWriteStream,
  915. typename DynamicBuffer_v2, typename CompletionCondition,
  916. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  917. std::size_t)) WriteHandler>
  918. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
  919. void (boost::system::error_code, std::size_t))
  920. async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
  921. CompletionCondition completion_condition,
  922. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  923. typename enable_if<
  924. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  925. >::type*)
  926. {
  927. return async_initiate<WriteHandler,
  928. void (boost::system::error_code, std::size_t)>(
  929. detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),
  930. handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  931. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  932. }
  933. } // namespace asio
  934. } // namespace boost
  935. #include <boost/asio/detail/pop_options.hpp>
  936. #endif // BOOST_ASIO_IMPL_WRITE_HPP