write.hpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  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. struct initiate_async_write_buffer_sequence
  382. {
  383. template <typename WriteHandler, typename AsyncWriteStream,
  384. typename ConstBufferSequence, typename CompletionCondition>
  385. void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  386. AsyncWriteStream* s, const ConstBufferSequence& buffers,
  387. BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  388. {
  389. // If you get an error on the following line it means that your handler
  390. // does not meet the documented type requirements for a WriteHandler.
  391. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  392. non_const_lvalue<WriteHandler> handler2(handler);
  393. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  394. start_write_buffer_sequence_op(*s, buffers,
  395. boost::asio::buffer_sequence_begin(buffers),
  396. completion_cond2.value, handler2.value);
  397. }
  398. };
  399. } // namespace detail
  400. #if !defined(GENERATING_DOCUMENTATION)
  401. template <typename AsyncWriteStream, typename ConstBufferSequence,
  402. typename ConstBufferIterator, typename CompletionCondition,
  403. typename WriteHandler, typename Allocator>
  404. struct associated_allocator<
  405. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  406. ConstBufferIterator, CompletionCondition, WriteHandler>,
  407. Allocator>
  408. {
  409. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  410. static type get(
  411. const detail::write_op<AsyncWriteStream, ConstBufferSequence,
  412. ConstBufferIterator, CompletionCondition, WriteHandler>& h,
  413. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  414. {
  415. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  416. }
  417. };
  418. template <typename AsyncWriteStream, typename ConstBufferSequence,
  419. typename ConstBufferIterator, typename CompletionCondition,
  420. typename WriteHandler, typename Executor>
  421. struct associated_executor<
  422. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  423. ConstBufferIterator, CompletionCondition, WriteHandler>,
  424. Executor>
  425. {
  426. typedef typename associated_executor<WriteHandler, Executor>::type type;
  427. static type get(
  428. const detail::write_op<AsyncWriteStream, ConstBufferSequence,
  429. ConstBufferIterator, CompletionCondition, WriteHandler>& h,
  430. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  431. {
  432. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  433. }
  434. };
  435. #endif // !defined(GENERATING_DOCUMENTATION)
  436. template <typename AsyncWriteStream, typename ConstBufferSequence,
  437. typename CompletionCondition, typename WriteHandler>
  438. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  439. void (boost::system::error_code, std::size_t))
  440. async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  441. CompletionCondition completion_condition,
  442. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  443. typename enable_if<
  444. is_const_buffer_sequence<ConstBufferSequence>::value
  445. >::type*)
  446. {
  447. return async_initiate<WriteHandler,
  448. void (boost::system::error_code, std::size_t)>(
  449. detail::initiate_async_write_buffer_sequence(), handler, &s, buffers,
  450. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  451. }
  452. template <typename AsyncWriteStream, typename ConstBufferSequence,
  453. typename WriteHandler>
  454. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  455. void (boost::system::error_code, std::size_t))
  456. async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  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(),
  465. handler, &s, buffers, transfer_all());
  466. }
  467. #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  468. namespace detail
  469. {
  470. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  471. typename CompletionCondition, typename WriteHandler>
  472. class write_dynbuf_v1_op
  473. {
  474. public:
  475. template <typename BufferSequence>
  476. write_dynbuf_v1_op(AsyncWriteStream& stream,
  477. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  478. CompletionCondition& completion_condition, WriteHandler& handler)
  479. : stream_(stream),
  480. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  481. completion_condition_(
  482. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
  483. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  484. {
  485. }
  486. #if defined(BOOST_ASIO_HAS_MOVE)
  487. write_dynbuf_v1_op(const write_dynbuf_v1_op& other)
  488. : stream_(other.stream_),
  489. buffers_(other.buffers_),
  490. completion_condition_(other.completion_condition_),
  491. handler_(other.handler_)
  492. {
  493. }
  494. write_dynbuf_v1_op(write_dynbuf_v1_op&& other)
  495. : stream_(other.stream_),
  496. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
  497. completion_condition_(
  498. BOOST_ASIO_MOVE_CAST(CompletionCondition)(
  499. other.completion_condition_)),
  500. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  501. {
  502. }
  503. #endif // defined(BOOST_ASIO_HAS_MOVE)
  504. void operator()(const boost::system::error_code& ec,
  505. std::size_t bytes_transferred, int start = 0)
  506. {
  507. switch (start)
  508. {
  509. case 1:
  510. async_write(stream_, buffers_.data(),
  511. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition_),
  512. BOOST_ASIO_MOVE_CAST(write_dynbuf_v1_op)(*this));
  513. return; default:
  514. buffers_.consume(bytes_transferred);
  515. handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
  516. }
  517. }
  518. //private:
  519. AsyncWriteStream& stream_;
  520. DynamicBuffer_v1 buffers_;
  521. CompletionCondition completion_condition_;
  522. WriteHandler handler_;
  523. };
  524. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  525. typename CompletionCondition, typename WriteHandler>
  526. inline void* asio_handler_allocate(std::size_t size,
  527. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  528. CompletionCondition, WriteHandler>* this_handler)
  529. {
  530. return boost_asio_handler_alloc_helpers::allocate(
  531. size, this_handler->handler_);
  532. }
  533. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  534. typename CompletionCondition, typename WriteHandler>
  535. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  536. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  537. CompletionCondition, WriteHandler>* this_handler)
  538. {
  539. boost_asio_handler_alloc_helpers::deallocate(
  540. pointer, size, this_handler->handler_);
  541. }
  542. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  543. typename CompletionCondition, typename WriteHandler>
  544. inline bool asio_handler_is_continuation(
  545. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  546. CompletionCondition, WriteHandler>* this_handler)
  547. {
  548. return boost_asio_handler_cont_helpers::is_continuation(
  549. this_handler->handler_);
  550. }
  551. template <typename Function, typename AsyncWriteStream,
  552. typename DynamicBuffer_v1, typename CompletionCondition,
  553. typename WriteHandler>
  554. inline void asio_handler_invoke(Function& function,
  555. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  556. CompletionCondition, WriteHandler>* this_handler)
  557. {
  558. boost_asio_handler_invoke_helpers::invoke(
  559. function, this_handler->handler_);
  560. }
  561. template <typename Function, typename AsyncWriteStream,
  562. typename DynamicBuffer_v1, typename CompletionCondition,
  563. typename WriteHandler>
  564. inline void asio_handler_invoke(const Function& function,
  565. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  566. CompletionCondition, WriteHandler>* this_handler)
  567. {
  568. boost_asio_handler_invoke_helpers::invoke(
  569. function, this_handler->handler_);
  570. }
  571. struct initiate_async_write_dynbuf_v1
  572. {
  573. template <typename WriteHandler, typename AsyncWriteStream,
  574. typename DynamicBuffer_v1, typename CompletionCondition>
  575. void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  576. AsyncWriteStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  577. BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  578. {
  579. // If you get an error on the following line it means that your handler
  580. // does not meet the documented type requirements for a WriteHandler.
  581. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  582. non_const_lvalue<WriteHandler> handler2(handler);
  583. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  584. write_dynbuf_v1_op<AsyncWriteStream,
  585. typename decay<DynamicBuffer_v1>::type,
  586. CompletionCondition, typename decay<WriteHandler>::type>(
  587. *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  588. completion_cond2.value, handler2.value)(
  589. boost::system::error_code(), 0, 1);
  590. }
  591. };
  592. } // namespace detail
  593. #if !defined(GENERATING_DOCUMENTATION)
  594. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  595. typename CompletionCondition, typename WriteHandler, typename Allocator>
  596. struct associated_allocator<
  597. detail::write_dynbuf_v1_op<AsyncWriteStream,
  598. DynamicBuffer_v1, CompletionCondition, WriteHandler>,
  599. Allocator>
  600. {
  601. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  602. static type get(
  603. const detail::write_dynbuf_v1_op<AsyncWriteStream,
  604. DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
  605. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  606. {
  607. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  608. }
  609. };
  610. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  611. typename CompletionCondition, typename WriteHandler, typename Executor>
  612. struct associated_executor<
  613. detail::write_dynbuf_v1_op<AsyncWriteStream,
  614. DynamicBuffer_v1, CompletionCondition, WriteHandler>,
  615. Executor>
  616. {
  617. typedef typename associated_executor<WriteHandler, Executor>::type type;
  618. static type get(
  619. const detail::write_dynbuf_v1_op<AsyncWriteStream,
  620. DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
  621. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  622. {
  623. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  624. }
  625. };
  626. #endif // !defined(GENERATING_DOCUMENTATION)
  627. template <typename AsyncWriteStream,
  628. typename DynamicBuffer_v1, typename WriteHandler>
  629. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  630. void (boost::system::error_code, std::size_t))
  631. async_write(AsyncWriteStream& s,
  632. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  633. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  634. typename enable_if<
  635. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  636. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  637. >::type*)
  638. {
  639. return async_write(s,
  640. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  641. transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  642. }
  643. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  644. typename CompletionCondition, typename WriteHandler>
  645. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  646. void (boost::system::error_code, std::size_t))
  647. async_write(AsyncWriteStream& s,
  648. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  649. CompletionCondition completion_condition,
  650. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  651. typename enable_if<
  652. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  653. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  654. >::type*)
  655. {
  656. return async_initiate<WriteHandler,
  657. void (boost::system::error_code, std::size_t)>(
  658. detail::initiate_async_write_dynbuf_v1(), handler, &s,
  659. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  660. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  661. }
  662. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  663. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  664. template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
  665. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  666. void (boost::system::error_code, std::size_t))
  667. async_write(AsyncWriteStream& s,
  668. boost::asio::basic_streambuf<Allocator>& b,
  669. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  670. {
  671. return async_write(s, basic_streambuf_ref<Allocator>(b),
  672. BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  673. }
  674. template <typename AsyncWriteStream, typename Allocator,
  675. typename CompletionCondition, typename WriteHandler>
  676. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  677. void (boost::system::error_code, std::size_t))
  678. async_write(AsyncWriteStream& s,
  679. boost::asio::basic_streambuf<Allocator>& b,
  680. CompletionCondition completion_condition,
  681. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  682. {
  683. return async_write(s, basic_streambuf_ref<Allocator>(b),
  684. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
  685. BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  686. }
  687. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  688. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  689. #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  690. namespace detail
  691. {
  692. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  693. typename CompletionCondition, typename WriteHandler>
  694. class write_dynbuf_v2_op
  695. {
  696. public:
  697. template <typename BufferSequence>
  698. write_dynbuf_v2_op(AsyncWriteStream& stream,
  699. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  700. CompletionCondition& completion_condition, WriteHandler& handler)
  701. : stream_(stream),
  702. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  703. completion_condition_(
  704. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
  705. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
  706. {
  707. }
  708. #if defined(BOOST_ASIO_HAS_MOVE)
  709. write_dynbuf_v2_op(const write_dynbuf_v2_op& other)
  710. : stream_(other.stream_),
  711. buffers_(other.buffers_),
  712. completion_condition_(other.completion_condition_),
  713. handler_(other.handler_)
  714. {
  715. }
  716. write_dynbuf_v2_op(write_dynbuf_v2_op&& other)
  717. : stream_(other.stream_),
  718. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
  719. completion_condition_(
  720. BOOST_ASIO_MOVE_CAST(CompletionCondition)(
  721. other.completion_condition_)),
  722. handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  723. {
  724. }
  725. #endif // defined(BOOST_ASIO_HAS_MOVE)
  726. void operator()(const boost::system::error_code& ec,
  727. std::size_t bytes_transferred, int start = 0)
  728. {
  729. switch (start)
  730. {
  731. case 1:
  732. async_write(stream_, buffers_.data(0, buffers_.size()),
  733. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition_),
  734. BOOST_ASIO_MOVE_CAST(write_dynbuf_v2_op)(*this));
  735. return; default:
  736. buffers_.consume(bytes_transferred);
  737. handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
  738. }
  739. }
  740. //private:
  741. AsyncWriteStream& stream_;
  742. DynamicBuffer_v2 buffers_;
  743. CompletionCondition completion_condition_;
  744. WriteHandler handler_;
  745. };
  746. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  747. typename CompletionCondition, typename WriteHandler>
  748. inline void* asio_handler_allocate(std::size_t size,
  749. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  750. CompletionCondition, WriteHandler>* this_handler)
  751. {
  752. return boost_asio_handler_alloc_helpers::allocate(
  753. size, this_handler->handler_);
  754. }
  755. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  756. typename CompletionCondition, typename WriteHandler>
  757. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  758. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  759. CompletionCondition, WriteHandler>* this_handler)
  760. {
  761. boost_asio_handler_alloc_helpers::deallocate(
  762. pointer, size, this_handler->handler_);
  763. }
  764. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  765. typename CompletionCondition, typename WriteHandler>
  766. inline bool asio_handler_is_continuation(
  767. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  768. CompletionCondition, WriteHandler>* this_handler)
  769. {
  770. return boost_asio_handler_cont_helpers::is_continuation(
  771. this_handler->handler_);
  772. }
  773. template <typename Function, typename AsyncWriteStream,
  774. typename DynamicBuffer_v2, typename CompletionCondition,
  775. typename WriteHandler>
  776. inline void asio_handler_invoke(Function& function,
  777. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  778. CompletionCondition, WriteHandler>* this_handler)
  779. {
  780. boost_asio_handler_invoke_helpers::invoke(
  781. function, this_handler->handler_);
  782. }
  783. template <typename Function, typename AsyncWriteStream,
  784. typename DynamicBuffer_v2, typename CompletionCondition,
  785. typename WriteHandler>
  786. inline void asio_handler_invoke(const Function& function,
  787. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  788. CompletionCondition, WriteHandler>* this_handler)
  789. {
  790. boost_asio_handler_invoke_helpers::invoke(
  791. function, this_handler->handler_);
  792. }
  793. struct initiate_async_write_dynbuf_v2
  794. {
  795. template <typename WriteHandler, typename AsyncWriteStream,
  796. typename DynamicBuffer_v2, typename CompletionCondition>
  797. void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  798. AsyncWriteStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
  799. BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  800. {
  801. // If you get an error on the following line it means that your handler
  802. // does not meet the documented type requirements for a WriteHandler.
  803. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  804. non_const_lvalue<WriteHandler> handler2(handler);
  805. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  806. write_dynbuf_v2_op<AsyncWriteStream,
  807. typename decay<DynamicBuffer_v2>::type,
  808. CompletionCondition, typename decay<WriteHandler>::type>(
  809. *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  810. completion_cond2.value, handler2.value)(
  811. boost::system::error_code(), 0, 1);
  812. }
  813. };
  814. } // namespace detail
  815. #if !defined(GENERATING_DOCUMENTATION)
  816. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  817. typename CompletionCondition, typename WriteHandler, typename Allocator>
  818. struct associated_allocator<
  819. detail::write_dynbuf_v2_op<AsyncWriteStream,
  820. DynamicBuffer_v2, CompletionCondition, WriteHandler>,
  821. Allocator>
  822. {
  823. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  824. static type get(
  825. const detail::write_dynbuf_v2_op<AsyncWriteStream,
  826. DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
  827. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  828. {
  829. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  830. }
  831. };
  832. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  833. typename CompletionCondition, typename WriteHandler, typename Executor>
  834. struct associated_executor<
  835. detail::write_dynbuf_v2_op<AsyncWriteStream,
  836. DynamicBuffer_v2, CompletionCondition, WriteHandler>,
  837. Executor>
  838. {
  839. typedef typename associated_executor<WriteHandler, Executor>::type type;
  840. static type get(
  841. const detail::write_dynbuf_v2_op<AsyncWriteStream,
  842. DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
  843. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  844. {
  845. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  846. }
  847. };
  848. #endif // !defined(GENERATING_DOCUMENTATION)
  849. template <typename AsyncWriteStream,
  850. typename DynamicBuffer_v2, typename WriteHandler>
  851. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  852. void (boost::system::error_code, std::size_t))
  853. async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
  854. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  855. typename enable_if<
  856. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  857. >::type*)
  858. {
  859. return async_write(s,
  860. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  861. transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  862. }
  863. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  864. typename CompletionCondition, typename WriteHandler>
  865. inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  866. void (boost::system::error_code, std::size_t))
  867. async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
  868. CompletionCondition completion_condition,
  869. BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
  870. typename enable_if<
  871. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  872. >::type*)
  873. {
  874. return async_initiate<WriteHandler,
  875. void (boost::system::error_code, std::size_t)>(
  876. detail::initiate_async_write_dynbuf_v2(), handler, &s,
  877. BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  878. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  879. }
  880. } // namespace asio
  881. } // namespace boost
  882. #include <boost/asio/detail/pop_options.hpp>
  883. #endif // BOOST_ASIO_IMPL_WRITE_HPP