write.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. //
  2. // impl/write.hpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 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/associator.hpp>
  16. #include <boost/asio/buffer.hpp>
  17. #include <boost/asio/detail/array_fwd.hpp>
  18. #include <boost/asio/detail/base_from_cancellation_state.hpp>
  19. #include <boost/asio/detail/base_from_completion_cond.hpp>
  20. #include <boost/asio/detail/bind_handler.hpp>
  21. #include <boost/asio/detail/consuming_buffers.hpp>
  22. #include <boost/asio/detail/dependent_type.hpp>
  23. #include <boost/asio/detail/handler_cont_helpers.hpp>
  24. #include <boost/asio/detail/handler_tracking.hpp>
  25. #include <boost/asio/detail/handler_type_requirements.hpp>
  26. #include <boost/asio/detail/non_const_lvalue.hpp>
  27. #include <boost/asio/detail/throw_error.hpp>
  28. #include <boost/asio/detail/push_options.hpp>
  29. namespace boost {
  30. namespace asio {
  31. namespace detail
  32. {
  33. template <typename SyncWriteStream, typename ConstBufferSequence,
  34. typename ConstBufferIterator, typename CompletionCondition>
  35. std::size_t write(SyncWriteStream& s,
  36. const ConstBufferSequence& buffers, const ConstBufferIterator&,
  37. CompletionCondition completion_condition, boost::system::error_code& ec)
  38. {
  39. ec = boost::system::error_code();
  40. boost::asio::detail::consuming_buffers<const_buffer,
  41. ConstBufferSequence, ConstBufferIterator> tmp(buffers);
  42. while (!tmp.empty())
  43. {
  44. if (std::size_t max_size = detail::adapt_completion_condition_result(
  45. completion_condition(ec, tmp.total_consumed())))
  46. tmp.consume(s.write_some(tmp.prepare(max_size), ec));
  47. else
  48. break;
  49. }
  50. return tmp.total_consumed();
  51. }
  52. } // namespace detail
  53. template <typename SyncWriteStream, typename ConstBufferSequence,
  54. typename CompletionCondition>
  55. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  56. CompletionCondition completion_condition, boost::system::error_code& ec,
  57. constraint_t<
  58. is_const_buffer_sequence<ConstBufferSequence>::value
  59. >,
  60. constraint_t<
  61. is_completion_condition<CompletionCondition>::value
  62. >)
  63. {
  64. return detail::write(s, buffers,
  65. boost::asio::buffer_sequence_begin(buffers),
  66. static_cast<CompletionCondition&&>(completion_condition), ec);
  67. }
  68. template <typename SyncWriteStream, typename ConstBufferSequence>
  69. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  70. constraint_t<
  71. is_const_buffer_sequence<ConstBufferSequence>::value
  72. >)
  73. {
  74. boost::system::error_code ec;
  75. std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
  76. boost::asio::detail::throw_error(ec, "write");
  77. return bytes_transferred;
  78. }
  79. template <typename SyncWriteStream, typename ConstBufferSequence>
  80. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  81. boost::system::error_code& ec,
  82. constraint_t<
  83. is_const_buffer_sequence<ConstBufferSequence>::value
  84. >)
  85. {
  86. return write(s, buffers, transfer_all(), ec);
  87. }
  88. template <typename SyncWriteStream, typename ConstBufferSequence,
  89. typename CompletionCondition>
  90. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  91. CompletionCondition completion_condition,
  92. constraint_t<
  93. is_const_buffer_sequence<ConstBufferSequence>::value
  94. >,
  95. constraint_t<
  96. is_completion_condition<CompletionCondition>::value
  97. >)
  98. {
  99. boost::system::error_code ec;
  100. std::size_t bytes_transferred = write(s, buffers,
  101. static_cast<CompletionCondition&&>(completion_condition), ec);
  102. boost::asio::detail::throw_error(ec, "write");
  103. return bytes_transferred;
  104. }
  105. #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  106. template <typename SyncWriteStream, typename DynamicBuffer_v1,
  107. typename CompletionCondition>
  108. std::size_t write(SyncWriteStream& s,
  109. DynamicBuffer_v1&& buffers,
  110. CompletionCondition completion_condition, boost::system::error_code& ec,
  111. constraint_t<
  112. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  113. >,
  114. constraint_t<
  115. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  116. >,
  117. constraint_t<
  118. is_completion_condition<CompletionCondition>::value
  119. >)
  120. {
  121. decay_t<DynamicBuffer_v1> b(
  122. static_cast<DynamicBuffer_v1&&>(buffers));
  123. std::size_t bytes_transferred = write(s, b.data(),
  124. static_cast<CompletionCondition&&>(completion_condition), ec);
  125. b.consume(bytes_transferred);
  126. return bytes_transferred;
  127. }
  128. template <typename SyncWriteStream, typename DynamicBuffer_v1>
  129. inline std::size_t write(SyncWriteStream& s,
  130. DynamicBuffer_v1&& buffers,
  131. constraint_t<
  132. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  133. >,
  134. constraint_t<
  135. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  136. >)
  137. {
  138. boost::system::error_code ec;
  139. std::size_t bytes_transferred = write(s,
  140. static_cast<DynamicBuffer_v1&&>(buffers),
  141. transfer_all(), ec);
  142. boost::asio::detail::throw_error(ec, "write");
  143. return bytes_transferred;
  144. }
  145. template <typename SyncWriteStream, typename DynamicBuffer_v1>
  146. inline std::size_t write(SyncWriteStream& s,
  147. DynamicBuffer_v1&& buffers,
  148. boost::system::error_code& ec,
  149. constraint_t<
  150. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  151. >,
  152. constraint_t<
  153. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  154. >)
  155. {
  156. return write(s, static_cast<DynamicBuffer_v1&&>(buffers),
  157. transfer_all(), ec);
  158. }
  159. template <typename SyncWriteStream, typename DynamicBuffer_v1,
  160. typename CompletionCondition>
  161. inline std::size_t write(SyncWriteStream& s,
  162. DynamicBuffer_v1&& buffers,
  163. CompletionCondition completion_condition,
  164. constraint_t<
  165. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  166. >,
  167. constraint_t<
  168. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  169. >,
  170. constraint_t<
  171. is_completion_condition<CompletionCondition>::value
  172. >)
  173. {
  174. boost::system::error_code ec;
  175. std::size_t bytes_transferred = write(s,
  176. static_cast<DynamicBuffer_v1&&>(buffers),
  177. static_cast<CompletionCondition&&>(completion_condition), ec);
  178. boost::asio::detail::throw_error(ec, "write");
  179. return bytes_transferred;
  180. }
  181. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  182. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  183. template <typename SyncWriteStream, typename Allocator,
  184. typename CompletionCondition>
  185. inline std::size_t write(SyncWriteStream& s,
  186. boost::asio::basic_streambuf<Allocator>& b,
  187. CompletionCondition completion_condition, boost::system::error_code& ec,
  188. constraint_t<
  189. is_completion_condition<CompletionCondition>::value
  190. >)
  191. {
  192. return write(s, basic_streambuf_ref<Allocator>(b),
  193. static_cast<CompletionCondition&&>(completion_condition), ec);
  194. }
  195. template <typename SyncWriteStream, typename Allocator>
  196. inline std::size_t write(SyncWriteStream& s,
  197. boost::asio::basic_streambuf<Allocator>& b)
  198. {
  199. return write(s, basic_streambuf_ref<Allocator>(b));
  200. }
  201. template <typename SyncWriteStream, typename Allocator>
  202. inline std::size_t write(SyncWriteStream& s,
  203. boost::asio::basic_streambuf<Allocator>& b,
  204. boost::system::error_code& ec)
  205. {
  206. return write(s, basic_streambuf_ref<Allocator>(b), ec);
  207. }
  208. template <typename SyncWriteStream, typename Allocator,
  209. typename CompletionCondition>
  210. inline std::size_t write(SyncWriteStream& s,
  211. boost::asio::basic_streambuf<Allocator>& b,
  212. CompletionCondition completion_condition,
  213. constraint_t<
  214. is_completion_condition<CompletionCondition>::value
  215. >)
  216. {
  217. return write(s, basic_streambuf_ref<Allocator>(b),
  218. static_cast<CompletionCondition&&>(completion_condition));
  219. }
  220. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  221. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  222. #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  223. template <typename SyncWriteStream, typename DynamicBuffer_v2,
  224. typename CompletionCondition>
  225. std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  226. CompletionCondition completion_condition, boost::system::error_code& ec,
  227. constraint_t<
  228. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  229. >,
  230. constraint_t<
  231. is_completion_condition<CompletionCondition>::value
  232. >)
  233. {
  234. std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()),
  235. static_cast<CompletionCondition&&>(completion_condition), ec);
  236. buffers.consume(bytes_transferred);
  237. return bytes_transferred;
  238. }
  239. template <typename SyncWriteStream, typename DynamicBuffer_v2>
  240. inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  241. constraint_t<
  242. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  243. >)
  244. {
  245. boost::system::error_code ec;
  246. std::size_t bytes_transferred = write(s,
  247. static_cast<DynamicBuffer_v2&&>(buffers),
  248. transfer_all(), ec);
  249. boost::asio::detail::throw_error(ec, "write");
  250. return bytes_transferred;
  251. }
  252. template <typename SyncWriteStream, typename DynamicBuffer_v2>
  253. inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  254. boost::system::error_code& ec,
  255. constraint_t<
  256. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  257. >)
  258. {
  259. return write(s, static_cast<DynamicBuffer_v2&&>(buffers),
  260. transfer_all(), ec);
  261. }
  262. template <typename SyncWriteStream, typename DynamicBuffer_v2,
  263. typename CompletionCondition>
  264. inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  265. CompletionCondition completion_condition,
  266. constraint_t<
  267. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  268. >,
  269. constraint_t<
  270. is_completion_condition<CompletionCondition>::value
  271. >)
  272. {
  273. boost::system::error_code ec;
  274. std::size_t bytes_transferred = write(s,
  275. static_cast<DynamicBuffer_v2&&>(buffers),
  276. static_cast<CompletionCondition&&>(completion_condition), ec);
  277. boost::asio::detail::throw_error(ec, "write");
  278. return bytes_transferred;
  279. }
  280. namespace detail
  281. {
  282. template <typename AsyncWriteStream, typename ConstBufferSequence,
  283. typename ConstBufferIterator, typename CompletionCondition,
  284. typename WriteHandler>
  285. class write_op
  286. : public base_from_cancellation_state<WriteHandler>,
  287. base_from_completion_cond<CompletionCondition>
  288. {
  289. public:
  290. write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
  291. CompletionCondition& completion_condition, WriteHandler& handler)
  292. : base_from_cancellation_state<WriteHandler>(
  293. handler, enable_partial_cancellation()),
  294. base_from_completion_cond<CompletionCondition>(completion_condition),
  295. stream_(stream),
  296. buffers_(buffers),
  297. start_(0),
  298. handler_(static_cast<WriteHandler&&>(handler))
  299. {
  300. }
  301. write_op(const write_op& other)
  302. : base_from_cancellation_state<WriteHandler>(other),
  303. base_from_completion_cond<CompletionCondition>(other),
  304. stream_(other.stream_),
  305. buffers_(other.buffers_),
  306. start_(other.start_),
  307. handler_(other.handler_)
  308. {
  309. }
  310. write_op(write_op&& other)
  311. : base_from_cancellation_state<WriteHandler>(
  312. static_cast<base_from_cancellation_state<WriteHandler>&&>(other)),
  313. base_from_completion_cond<CompletionCondition>(
  314. static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
  315. stream_(other.stream_),
  316. buffers_(static_cast<buffers_type&&>(other.buffers_)),
  317. start_(other.start_),
  318. handler_(static_cast<WriteHandler&&>(other.handler_))
  319. {
  320. }
  321. void operator()(boost::system::error_code ec,
  322. std::size_t bytes_transferred, int start = 0)
  323. {
  324. std::size_t max_size;
  325. switch (start_ = start)
  326. {
  327. case 1:
  328. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  329. for (;;)
  330. {
  331. {
  332. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write"));
  333. stream_.async_write_some(buffers_.prepare(max_size),
  334. static_cast<write_op&&>(*this));
  335. }
  336. return; default:
  337. buffers_.consume(bytes_transferred);
  338. if ((!ec && bytes_transferred == 0) || buffers_.empty())
  339. break;
  340. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  341. if (max_size == 0)
  342. break;
  343. if (this->cancelled() != cancellation_type::none)
  344. {
  345. ec = error::operation_aborted;
  346. break;
  347. }
  348. }
  349. static_cast<WriteHandler&&>(handler_)(
  350. static_cast<const boost::system::error_code&>(ec),
  351. static_cast<const std::size_t&>(buffers_.total_consumed()));
  352. }
  353. }
  354. //private:
  355. typedef boost::asio::detail::consuming_buffers<const_buffer,
  356. ConstBufferSequence, ConstBufferIterator> buffers_type;
  357. AsyncWriteStream& stream_;
  358. buffers_type buffers_;
  359. int start_;
  360. WriteHandler handler_;
  361. };
  362. template <typename AsyncWriteStream, typename ConstBufferSequence,
  363. typename ConstBufferIterator, typename CompletionCondition,
  364. typename WriteHandler>
  365. inline bool asio_handler_is_continuation(
  366. write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
  367. CompletionCondition, WriteHandler>* this_handler)
  368. {
  369. return this_handler->start_ == 0 ? true
  370. : boost_asio_handler_cont_helpers::is_continuation(
  371. this_handler->handler_);
  372. }
  373. template <typename AsyncWriteStream, typename ConstBufferSequence,
  374. typename ConstBufferIterator, typename CompletionCondition,
  375. typename WriteHandler>
  376. inline void start_write_op(AsyncWriteStream& stream,
  377. const ConstBufferSequence& buffers, const ConstBufferIterator&,
  378. CompletionCondition& completion_condition, WriteHandler& handler)
  379. {
  380. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  381. ConstBufferIterator, CompletionCondition, WriteHandler>(
  382. stream, buffers, completion_condition, handler)(
  383. boost::system::error_code(), 0, 1);
  384. }
  385. template <typename AsyncWriteStream>
  386. class initiate_async_write
  387. {
  388. public:
  389. typedef typename AsyncWriteStream::executor_type executor_type;
  390. explicit initiate_async_write(AsyncWriteStream& stream)
  391. : stream_(stream)
  392. {
  393. }
  394. executor_type get_executor() const noexcept
  395. {
  396. return stream_.get_executor();
  397. }
  398. template <typename WriteHandler, typename ConstBufferSequence,
  399. typename CompletionCondition>
  400. void operator()(WriteHandler&& handler,
  401. const ConstBufferSequence& buffers,
  402. CompletionCondition&& completion_cond) const
  403. {
  404. // If you get an error on the following line it means that your handler
  405. // does not meet the documented type requirements for a WriteHandler.
  406. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  407. non_const_lvalue<WriteHandler> handler2(handler);
  408. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  409. start_write_op(stream_, buffers,
  410. boost::asio::buffer_sequence_begin(buffers),
  411. completion_cond2.value, handler2.value);
  412. }
  413. private:
  414. AsyncWriteStream& stream_;
  415. };
  416. } // namespace detail
  417. #if !defined(GENERATING_DOCUMENTATION)
  418. template <template <typename, typename> class Associator,
  419. typename AsyncWriteStream, typename ConstBufferSequence,
  420. typename ConstBufferIterator, typename CompletionCondition,
  421. typename WriteHandler, typename DefaultCandidate>
  422. struct associator<Associator,
  423. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  424. ConstBufferIterator, CompletionCondition, WriteHandler>,
  425. DefaultCandidate>
  426. : Associator<WriteHandler, DefaultCandidate>
  427. {
  428. static typename Associator<WriteHandler, DefaultCandidate>::type get(
  429. const detail::write_op<AsyncWriteStream, ConstBufferSequence,
  430. ConstBufferIterator, CompletionCondition, WriteHandler>& h) noexcept
  431. {
  432. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
  433. }
  434. static auto get(
  435. const detail::write_op<AsyncWriteStream, ConstBufferSequence,
  436. ConstBufferIterator, CompletionCondition, WriteHandler>& h,
  437. const DefaultCandidate& c) noexcept
  438. -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
  439. {
  440. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
  441. }
  442. };
  443. #endif // !defined(GENERATING_DOCUMENTATION)
  444. #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  445. namespace detail
  446. {
  447. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  448. typename CompletionCondition, typename WriteHandler>
  449. class write_dynbuf_v1_op
  450. {
  451. public:
  452. template <typename BufferSequence>
  453. write_dynbuf_v1_op(AsyncWriteStream& stream,
  454. BufferSequence&& buffers,
  455. CompletionCondition& completion_condition, WriteHandler& handler)
  456. : stream_(stream),
  457. buffers_(static_cast<BufferSequence&&>(buffers)),
  458. completion_condition_(
  459. static_cast<CompletionCondition&&>(completion_condition)),
  460. handler_(static_cast<WriteHandler&&>(handler))
  461. {
  462. }
  463. write_dynbuf_v1_op(const write_dynbuf_v1_op& other)
  464. : stream_(other.stream_),
  465. buffers_(other.buffers_),
  466. completion_condition_(other.completion_condition_),
  467. handler_(other.handler_)
  468. {
  469. }
  470. write_dynbuf_v1_op(write_dynbuf_v1_op&& other)
  471. : stream_(other.stream_),
  472. buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
  473. completion_condition_(
  474. static_cast<CompletionCondition&&>(
  475. other.completion_condition_)),
  476. handler_(static_cast<WriteHandler&&>(other.handler_))
  477. {
  478. }
  479. void operator()(const boost::system::error_code& ec,
  480. std::size_t bytes_transferred, int start = 0)
  481. {
  482. switch (start)
  483. {
  484. case 1:
  485. async_write(stream_, buffers_.data(),
  486. static_cast<CompletionCondition&&>(completion_condition_),
  487. static_cast<write_dynbuf_v1_op&&>(*this));
  488. return; default:
  489. buffers_.consume(bytes_transferred);
  490. static_cast<WriteHandler&&>(handler_)(ec,
  491. static_cast<const std::size_t&>(bytes_transferred));
  492. }
  493. }
  494. //private:
  495. AsyncWriteStream& stream_;
  496. DynamicBuffer_v1 buffers_;
  497. CompletionCondition completion_condition_;
  498. WriteHandler handler_;
  499. };
  500. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  501. typename CompletionCondition, typename WriteHandler>
  502. inline bool asio_handler_is_continuation(
  503. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  504. CompletionCondition, WriteHandler>* this_handler)
  505. {
  506. return boost_asio_handler_cont_helpers::is_continuation(
  507. this_handler->handler_);
  508. }
  509. template <typename AsyncWriteStream>
  510. class initiate_async_write_dynbuf_v1
  511. {
  512. public:
  513. typedef typename AsyncWriteStream::executor_type executor_type;
  514. explicit initiate_async_write_dynbuf_v1(AsyncWriteStream& stream)
  515. : stream_(stream)
  516. {
  517. }
  518. executor_type get_executor() const noexcept
  519. {
  520. return stream_.get_executor();
  521. }
  522. template <typename WriteHandler, typename DynamicBuffer_v1,
  523. typename CompletionCondition>
  524. void operator()(WriteHandler&& handler,
  525. DynamicBuffer_v1&& buffers,
  526. CompletionCondition&& completion_cond) const
  527. {
  528. // If you get an error on the following line it means that your handler
  529. // does not meet the documented type requirements for a WriteHandler.
  530. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  531. non_const_lvalue<WriteHandler> handler2(handler);
  532. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  533. write_dynbuf_v1_op<AsyncWriteStream,
  534. decay_t<DynamicBuffer_v1>,
  535. CompletionCondition, decay_t<WriteHandler>>(
  536. stream_, static_cast<DynamicBuffer_v1&&>(buffers),
  537. completion_cond2.value, handler2.value)(
  538. boost::system::error_code(), 0, 1);
  539. }
  540. private:
  541. AsyncWriteStream& stream_;
  542. };
  543. } // namespace detail
  544. #if !defined(GENERATING_DOCUMENTATION)
  545. template <template <typename, typename> class Associator,
  546. typename AsyncWriteStream, typename DynamicBuffer_v1,
  547. typename CompletionCondition, typename WriteHandler,
  548. typename DefaultCandidate>
  549. struct associator<Associator,
  550. detail::write_dynbuf_v1_op<AsyncWriteStream,
  551. DynamicBuffer_v1, CompletionCondition, WriteHandler>,
  552. DefaultCandidate>
  553. : Associator<WriteHandler, DefaultCandidate>
  554. {
  555. static typename Associator<WriteHandler, DefaultCandidate>::type get(
  556. const detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  557. CompletionCondition, WriteHandler>& h) noexcept
  558. {
  559. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
  560. }
  561. static auto get(
  562. const detail::write_dynbuf_v1_op<AsyncWriteStream,
  563. DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
  564. const DefaultCandidate& c) noexcept
  565. -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
  566. {
  567. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
  568. }
  569. };
  570. #endif // !defined(GENERATING_DOCUMENTATION)
  571. #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  572. namespace detail
  573. {
  574. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  575. typename CompletionCondition, typename WriteHandler>
  576. class write_dynbuf_v2_op
  577. {
  578. public:
  579. template <typename BufferSequence>
  580. write_dynbuf_v2_op(AsyncWriteStream& stream,
  581. BufferSequence&& buffers,
  582. CompletionCondition& completion_condition, WriteHandler& handler)
  583. : stream_(stream),
  584. buffers_(static_cast<BufferSequence&&>(buffers)),
  585. completion_condition_(
  586. static_cast<CompletionCondition&&>(completion_condition)),
  587. handler_(static_cast<WriteHandler&&>(handler))
  588. {
  589. }
  590. write_dynbuf_v2_op(const write_dynbuf_v2_op& other)
  591. : stream_(other.stream_),
  592. buffers_(other.buffers_),
  593. completion_condition_(other.completion_condition_),
  594. handler_(other.handler_)
  595. {
  596. }
  597. write_dynbuf_v2_op(write_dynbuf_v2_op&& other)
  598. : stream_(other.stream_),
  599. buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
  600. completion_condition_(
  601. static_cast<CompletionCondition&&>(
  602. other.completion_condition_)),
  603. handler_(static_cast<WriteHandler&&>(other.handler_))
  604. {
  605. }
  606. void operator()(const boost::system::error_code& ec,
  607. std::size_t bytes_transferred, int start = 0)
  608. {
  609. switch (start)
  610. {
  611. case 1:
  612. async_write(stream_, buffers_.data(0, buffers_.size()),
  613. static_cast<CompletionCondition&&>(completion_condition_),
  614. static_cast<write_dynbuf_v2_op&&>(*this));
  615. return; default:
  616. buffers_.consume(bytes_transferred);
  617. static_cast<WriteHandler&&>(handler_)(ec,
  618. static_cast<const std::size_t&>(bytes_transferred));
  619. }
  620. }
  621. //private:
  622. AsyncWriteStream& stream_;
  623. DynamicBuffer_v2 buffers_;
  624. CompletionCondition completion_condition_;
  625. WriteHandler handler_;
  626. };
  627. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  628. typename CompletionCondition, typename WriteHandler>
  629. inline bool asio_handler_is_continuation(
  630. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  631. CompletionCondition, WriteHandler>* this_handler)
  632. {
  633. return boost_asio_handler_cont_helpers::is_continuation(
  634. this_handler->handler_);
  635. }
  636. template <typename AsyncWriteStream>
  637. class initiate_async_write_dynbuf_v2
  638. {
  639. public:
  640. typedef typename AsyncWriteStream::executor_type executor_type;
  641. explicit initiate_async_write_dynbuf_v2(AsyncWriteStream& stream)
  642. : stream_(stream)
  643. {
  644. }
  645. executor_type get_executor() const noexcept
  646. {
  647. return stream_.get_executor();
  648. }
  649. template <typename WriteHandler, typename DynamicBuffer_v2,
  650. typename CompletionCondition>
  651. void operator()(WriteHandler&& handler,
  652. DynamicBuffer_v2&& buffers,
  653. CompletionCondition&& completion_cond) const
  654. {
  655. // If you get an error on the following line it means that your handler
  656. // does not meet the documented type requirements for a WriteHandler.
  657. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  658. non_const_lvalue<WriteHandler> handler2(handler);
  659. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  660. write_dynbuf_v2_op<AsyncWriteStream, decay_t<DynamicBuffer_v2>,
  661. CompletionCondition, decay_t<WriteHandler>>(
  662. stream_, static_cast<DynamicBuffer_v2&&>(buffers),
  663. completion_cond2.value, handler2.value)(
  664. boost::system::error_code(), 0, 1);
  665. }
  666. private:
  667. AsyncWriteStream& stream_;
  668. };
  669. } // namespace detail
  670. #if !defined(GENERATING_DOCUMENTATION)
  671. template <template <typename, typename> class Associator,
  672. typename AsyncWriteStream, typename DynamicBuffer_v2,
  673. typename CompletionCondition, typename WriteHandler,
  674. typename DefaultCandidate>
  675. struct associator<Associator,
  676. detail::write_dynbuf_v2_op<AsyncWriteStream,
  677. DynamicBuffer_v2, CompletionCondition, WriteHandler>,
  678. DefaultCandidate>
  679. : Associator<WriteHandler, DefaultCandidate>
  680. {
  681. static typename Associator<WriteHandler, DefaultCandidate>::type get(
  682. const detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  683. CompletionCondition, WriteHandler>& h) noexcept
  684. {
  685. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
  686. }
  687. static auto get(
  688. const detail::write_dynbuf_v2_op<AsyncWriteStream,
  689. DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
  690. const DefaultCandidate& c) noexcept
  691. -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
  692. {
  693. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
  694. }
  695. };
  696. #endif // !defined(GENERATING_DOCUMENTATION)
  697. } // namespace asio
  698. } // namespace boost
  699. #include <boost/asio/detail/pop_options.hpp>
  700. #endif // BOOST_ASIO_IMPL_WRITE_HPP