write.hpp 24 KB

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