write.hpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  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. {
  61. return detail::write(s, buffers,
  62. boost::asio::buffer_sequence_begin(buffers),
  63. static_cast<CompletionCondition&&>(completion_condition), ec);
  64. }
  65. template <typename SyncWriteStream, typename ConstBufferSequence>
  66. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  67. constraint_t<
  68. is_const_buffer_sequence<ConstBufferSequence>::value
  69. >)
  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. constraint_t<
  80. is_const_buffer_sequence<ConstBufferSequence>::value
  81. >)
  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. constraint_t<
  90. is_const_buffer_sequence<ConstBufferSequence>::value
  91. >)
  92. {
  93. boost::system::error_code ec;
  94. std::size_t bytes_transferred = write(s, buffers,
  95. static_cast<CompletionCondition&&>(completion_condition), ec);
  96. boost::asio::detail::throw_error(ec, "write");
  97. return bytes_transferred;
  98. }
  99. #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  100. template <typename SyncWriteStream, typename DynamicBuffer_v1,
  101. typename CompletionCondition>
  102. std::size_t write(SyncWriteStream& s,
  103. DynamicBuffer_v1&& buffers,
  104. CompletionCondition completion_condition, boost::system::error_code& ec,
  105. constraint_t<
  106. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  107. >,
  108. constraint_t<
  109. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  110. >)
  111. {
  112. decay_t<DynamicBuffer_v1> b(
  113. static_cast<DynamicBuffer_v1&&>(buffers));
  114. std::size_t bytes_transferred = write(s, b.data(),
  115. static_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. DynamicBuffer_v1&& buffers,
  122. constraint_t<
  123. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  124. >,
  125. constraint_t<
  126. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  127. >)
  128. {
  129. boost::system::error_code ec;
  130. std::size_t bytes_transferred = write(s,
  131. static_cast<DynamicBuffer_v1&&>(buffers),
  132. transfer_all(), ec);
  133. boost::asio::detail::throw_error(ec, "write");
  134. return bytes_transferred;
  135. }
  136. template <typename SyncWriteStream, typename DynamicBuffer_v1>
  137. inline std::size_t write(SyncWriteStream& s,
  138. DynamicBuffer_v1&& buffers,
  139. boost::system::error_code& ec,
  140. constraint_t<
  141. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  142. >,
  143. constraint_t<
  144. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  145. >)
  146. {
  147. return write(s, static_cast<DynamicBuffer_v1&&>(buffers),
  148. transfer_all(), ec);
  149. }
  150. template <typename SyncWriteStream, typename DynamicBuffer_v1,
  151. typename CompletionCondition>
  152. inline std::size_t write(SyncWriteStream& s,
  153. DynamicBuffer_v1&& buffers,
  154. CompletionCondition completion_condition,
  155. constraint_t<
  156. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  157. >,
  158. constraint_t<
  159. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  160. >)
  161. {
  162. boost::system::error_code ec;
  163. std::size_t bytes_transferred = write(s,
  164. static_cast<DynamicBuffer_v1&&>(buffers),
  165. static_cast<CompletionCondition&&>(completion_condition), ec);
  166. boost::asio::detail::throw_error(ec, "write");
  167. return bytes_transferred;
  168. }
  169. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  170. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  171. template <typename SyncWriteStream, typename Allocator,
  172. typename CompletionCondition>
  173. inline std::size_t write(SyncWriteStream& s,
  174. boost::asio::basic_streambuf<Allocator>& b,
  175. CompletionCondition completion_condition, boost::system::error_code& ec)
  176. {
  177. return write(s, basic_streambuf_ref<Allocator>(b),
  178. static_cast<CompletionCondition&&>(completion_condition), ec);
  179. }
  180. template <typename SyncWriteStream, typename Allocator>
  181. inline std::size_t write(SyncWriteStream& s,
  182. boost::asio::basic_streambuf<Allocator>& b)
  183. {
  184. return write(s, basic_streambuf_ref<Allocator>(b));
  185. }
  186. template <typename SyncWriteStream, typename Allocator>
  187. inline std::size_t write(SyncWriteStream& s,
  188. boost::asio::basic_streambuf<Allocator>& b,
  189. boost::system::error_code& ec)
  190. {
  191. return write(s, basic_streambuf_ref<Allocator>(b), ec);
  192. }
  193. template <typename SyncWriteStream, typename Allocator,
  194. typename CompletionCondition>
  195. inline std::size_t write(SyncWriteStream& s,
  196. boost::asio::basic_streambuf<Allocator>& b,
  197. CompletionCondition completion_condition)
  198. {
  199. return write(s, basic_streambuf_ref<Allocator>(b),
  200. static_cast<CompletionCondition&&>(completion_condition));
  201. }
  202. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  203. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  204. #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  205. template <typename SyncWriteStream, typename DynamicBuffer_v2,
  206. typename CompletionCondition>
  207. std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  208. CompletionCondition completion_condition, boost::system::error_code& ec,
  209. constraint_t<
  210. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  211. >)
  212. {
  213. std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()),
  214. static_cast<CompletionCondition&&>(completion_condition), ec);
  215. buffers.consume(bytes_transferred);
  216. return bytes_transferred;
  217. }
  218. template <typename SyncWriteStream, typename DynamicBuffer_v2>
  219. inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  220. constraint_t<
  221. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  222. >)
  223. {
  224. boost::system::error_code ec;
  225. std::size_t bytes_transferred = write(s,
  226. static_cast<DynamicBuffer_v2&&>(buffers),
  227. transfer_all(), ec);
  228. boost::asio::detail::throw_error(ec, "write");
  229. return bytes_transferred;
  230. }
  231. template <typename SyncWriteStream, typename DynamicBuffer_v2>
  232. inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  233. boost::system::error_code& ec,
  234. constraint_t<
  235. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  236. >)
  237. {
  238. return write(s, static_cast<DynamicBuffer_v2&&>(buffers),
  239. transfer_all(), ec);
  240. }
  241. template <typename SyncWriteStream, typename DynamicBuffer_v2,
  242. typename CompletionCondition>
  243. inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
  244. CompletionCondition completion_condition,
  245. constraint_t<
  246. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  247. >)
  248. {
  249. boost::system::error_code ec;
  250. std::size_t bytes_transferred = write(s,
  251. static_cast<DynamicBuffer_v2&&>(buffers),
  252. static_cast<CompletionCondition&&>(completion_condition), ec);
  253. boost::asio::detail::throw_error(ec, "write");
  254. return bytes_transferred;
  255. }
  256. namespace detail
  257. {
  258. template <typename AsyncWriteStream, typename ConstBufferSequence,
  259. typename ConstBufferIterator, typename CompletionCondition,
  260. typename WriteHandler>
  261. class write_op
  262. : public base_from_cancellation_state<WriteHandler>,
  263. base_from_completion_cond<CompletionCondition>
  264. {
  265. public:
  266. write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
  267. CompletionCondition& completion_condition, WriteHandler& handler)
  268. : base_from_cancellation_state<WriteHandler>(
  269. handler, enable_partial_cancellation()),
  270. base_from_completion_cond<CompletionCondition>(completion_condition),
  271. stream_(stream),
  272. buffers_(buffers),
  273. start_(0),
  274. handler_(static_cast<WriteHandler&&>(handler))
  275. {
  276. }
  277. write_op(const write_op& other)
  278. : base_from_cancellation_state<WriteHandler>(other),
  279. base_from_completion_cond<CompletionCondition>(other),
  280. stream_(other.stream_),
  281. buffers_(other.buffers_),
  282. start_(other.start_),
  283. handler_(other.handler_)
  284. {
  285. }
  286. write_op(write_op&& other)
  287. : base_from_cancellation_state<WriteHandler>(
  288. static_cast<base_from_cancellation_state<WriteHandler>&&>(other)),
  289. base_from_completion_cond<CompletionCondition>(
  290. static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
  291. stream_(other.stream_),
  292. buffers_(static_cast<buffers_type&&>(other.buffers_)),
  293. start_(other.start_),
  294. handler_(static_cast<WriteHandler&&>(other.handler_))
  295. {
  296. }
  297. void operator()(boost::system::error_code ec,
  298. std::size_t bytes_transferred, int start = 0)
  299. {
  300. std::size_t max_size;
  301. switch (start_ = start)
  302. {
  303. case 1:
  304. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  305. for (;;)
  306. {
  307. {
  308. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write"));
  309. stream_.async_write_some(buffers_.prepare(max_size),
  310. static_cast<write_op&&>(*this));
  311. }
  312. return; default:
  313. buffers_.consume(bytes_transferred);
  314. if ((!ec && bytes_transferred == 0) || buffers_.empty())
  315. break;
  316. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  317. if (max_size == 0)
  318. break;
  319. if (this->cancelled() != cancellation_type::none)
  320. {
  321. ec = error::operation_aborted;
  322. break;
  323. }
  324. }
  325. static_cast<WriteHandler&&>(handler_)(
  326. static_cast<const boost::system::error_code&>(ec),
  327. static_cast<const std::size_t&>(buffers_.total_consumed()));
  328. }
  329. }
  330. //private:
  331. typedef boost::asio::detail::consuming_buffers<const_buffer,
  332. ConstBufferSequence, ConstBufferIterator> buffers_type;
  333. AsyncWriteStream& stream_;
  334. buffers_type buffers_;
  335. int start_;
  336. WriteHandler 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 AsyncWriteStream, typename ConstBufferSequence,
  350. typename ConstBufferIterator, typename CompletionCondition,
  351. typename WriteHandler>
  352. inline void start_write_op(AsyncWriteStream& stream,
  353. const ConstBufferSequence& buffers, const ConstBufferIterator&,
  354. CompletionCondition& completion_condition, WriteHandler& handler)
  355. {
  356. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  357. ConstBufferIterator, CompletionCondition, WriteHandler>(
  358. stream, buffers, completion_condition, handler)(
  359. boost::system::error_code(), 0, 1);
  360. }
  361. template <typename AsyncWriteStream>
  362. class initiate_async_write
  363. {
  364. public:
  365. typedef typename AsyncWriteStream::executor_type executor_type;
  366. explicit initiate_async_write(AsyncWriteStream& stream)
  367. : stream_(stream)
  368. {
  369. }
  370. executor_type get_executor() const noexcept
  371. {
  372. return stream_.get_executor();
  373. }
  374. template <typename WriteHandler, typename ConstBufferSequence,
  375. typename CompletionCondition>
  376. void operator()(WriteHandler&& handler,
  377. const ConstBufferSequence& buffers,
  378. CompletionCondition&& completion_cond) const
  379. {
  380. // If you get an error on the following line it means that your handler
  381. // does not meet the documented type requirements for a WriteHandler.
  382. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  383. non_const_lvalue<WriteHandler> handler2(handler);
  384. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  385. start_write_op(stream_, buffers,
  386. boost::asio::buffer_sequence_begin(buffers),
  387. completion_cond2.value, handler2.value);
  388. }
  389. private:
  390. AsyncWriteStream& stream_;
  391. };
  392. } // namespace detail
  393. #if !defined(GENERATING_DOCUMENTATION)
  394. template <template <typename, typename> class Associator,
  395. typename AsyncWriteStream, typename ConstBufferSequence,
  396. typename ConstBufferIterator, typename CompletionCondition,
  397. typename WriteHandler, typename DefaultCandidate>
  398. struct associator<Associator,
  399. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  400. ConstBufferIterator, CompletionCondition, WriteHandler>,
  401. DefaultCandidate>
  402. : Associator<WriteHandler, DefaultCandidate>
  403. {
  404. static typename Associator<WriteHandler, DefaultCandidate>::type get(
  405. const detail::write_op<AsyncWriteStream, ConstBufferSequence,
  406. ConstBufferIterator, CompletionCondition, WriteHandler>& h) noexcept
  407. {
  408. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
  409. }
  410. static auto get(
  411. const detail::write_op<AsyncWriteStream, ConstBufferSequence,
  412. ConstBufferIterator, CompletionCondition, WriteHandler>& h,
  413. const DefaultCandidate& c) noexcept
  414. -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
  415. {
  416. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
  417. }
  418. };
  419. #endif // !defined(GENERATING_DOCUMENTATION)
  420. template <typename AsyncWriteStream,
  421. typename ConstBufferSequence, typename CompletionCondition,
  422. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  423. std::size_t)) WriteToken>
  424. inline auto async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  425. CompletionCondition completion_condition, WriteToken&& token,
  426. constraint_t<
  427. is_const_buffer_sequence<ConstBufferSequence>::value
  428. >)
  429. -> decltype(
  430. async_initiate<WriteToken,
  431. void (boost::system::error_code, std::size_t)>(
  432. declval<detail::initiate_async_write<AsyncWriteStream>>(),
  433. token, buffers,
  434. static_cast<CompletionCondition&&>(completion_condition)))
  435. {
  436. return async_initiate<WriteToken,
  437. void (boost::system::error_code, std::size_t)>(
  438. detail::initiate_async_write<AsyncWriteStream>(s),
  439. token, buffers,
  440. static_cast<CompletionCondition&&>(completion_condition));
  441. }
  442. template <typename AsyncWriteStream, typename ConstBufferSequence,
  443. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  444. std::size_t)) WriteToken>
  445. inline auto async_write(AsyncWriteStream& s,
  446. const ConstBufferSequence& buffers, WriteToken&& token,
  447. constraint_t<
  448. is_const_buffer_sequence<ConstBufferSequence>::value
  449. >)
  450. -> decltype(
  451. async_initiate<WriteToken,
  452. void (boost::system::error_code, std::size_t)>(
  453. declval<detail::initiate_async_write<AsyncWriteStream>>(),
  454. token, buffers, transfer_all()))
  455. {
  456. return async_initiate<WriteToken,
  457. void (boost::system::error_code, std::size_t)>(
  458. detail::initiate_async_write<AsyncWriteStream>(s),
  459. token, buffers, transfer_all());
  460. }
  461. #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  462. namespace detail
  463. {
  464. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  465. typename CompletionCondition, typename WriteHandler>
  466. class write_dynbuf_v1_op
  467. {
  468. public:
  469. template <typename BufferSequence>
  470. write_dynbuf_v1_op(AsyncWriteStream& stream,
  471. BufferSequence&& buffers,
  472. CompletionCondition& completion_condition, WriteHandler& handler)
  473. : stream_(stream),
  474. buffers_(static_cast<BufferSequence&&>(buffers)),
  475. completion_condition_(
  476. static_cast<CompletionCondition&&>(completion_condition)),
  477. handler_(static_cast<WriteHandler&&>(handler))
  478. {
  479. }
  480. write_dynbuf_v1_op(const write_dynbuf_v1_op& other)
  481. : stream_(other.stream_),
  482. buffers_(other.buffers_),
  483. completion_condition_(other.completion_condition_),
  484. handler_(other.handler_)
  485. {
  486. }
  487. write_dynbuf_v1_op(write_dynbuf_v1_op&& other)
  488. : stream_(other.stream_),
  489. buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
  490. completion_condition_(
  491. static_cast<CompletionCondition&&>(
  492. other.completion_condition_)),
  493. handler_(static_cast<WriteHandler&&>(other.handler_))
  494. {
  495. }
  496. void operator()(const boost::system::error_code& ec,
  497. std::size_t bytes_transferred, int start = 0)
  498. {
  499. switch (start)
  500. {
  501. case 1:
  502. async_write(stream_, buffers_.data(),
  503. static_cast<CompletionCondition&&>(completion_condition_),
  504. static_cast<write_dynbuf_v1_op&&>(*this));
  505. return; default:
  506. buffers_.consume(bytes_transferred);
  507. static_cast<WriteHandler&&>(handler_)(ec,
  508. static_cast<const std::size_t&>(bytes_transferred));
  509. }
  510. }
  511. //private:
  512. AsyncWriteStream& stream_;
  513. DynamicBuffer_v1 buffers_;
  514. CompletionCondition completion_condition_;
  515. WriteHandler handler_;
  516. };
  517. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  518. typename CompletionCondition, typename WriteHandler>
  519. inline bool asio_handler_is_continuation(
  520. write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  521. CompletionCondition, WriteHandler>* this_handler)
  522. {
  523. return boost_asio_handler_cont_helpers::is_continuation(
  524. this_handler->handler_);
  525. }
  526. template <typename AsyncWriteStream>
  527. class initiate_async_write_dynbuf_v1
  528. {
  529. public:
  530. typedef typename AsyncWriteStream::executor_type executor_type;
  531. explicit initiate_async_write_dynbuf_v1(AsyncWriteStream& stream)
  532. : stream_(stream)
  533. {
  534. }
  535. executor_type get_executor() const noexcept
  536. {
  537. return stream_.get_executor();
  538. }
  539. template <typename WriteHandler, typename DynamicBuffer_v1,
  540. typename CompletionCondition>
  541. void operator()(WriteHandler&& handler,
  542. DynamicBuffer_v1&& buffers,
  543. CompletionCondition&& completion_cond) const
  544. {
  545. // If you get an error on the following line it means that your handler
  546. // does not meet the documented type requirements for a WriteHandler.
  547. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  548. non_const_lvalue<WriteHandler> handler2(handler);
  549. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  550. write_dynbuf_v1_op<AsyncWriteStream,
  551. decay_t<DynamicBuffer_v1>,
  552. CompletionCondition, decay_t<WriteHandler>>(
  553. stream_, static_cast<DynamicBuffer_v1&&>(buffers),
  554. completion_cond2.value, handler2.value)(
  555. boost::system::error_code(), 0, 1);
  556. }
  557. private:
  558. AsyncWriteStream& stream_;
  559. };
  560. } // namespace detail
  561. #if !defined(GENERATING_DOCUMENTATION)
  562. template <template <typename, typename> class Associator,
  563. typename AsyncWriteStream, typename DynamicBuffer_v1,
  564. typename CompletionCondition, typename WriteHandler,
  565. typename DefaultCandidate>
  566. struct associator<Associator,
  567. detail::write_dynbuf_v1_op<AsyncWriteStream,
  568. DynamicBuffer_v1, CompletionCondition, WriteHandler>,
  569. DefaultCandidate>
  570. : Associator<WriteHandler, DefaultCandidate>
  571. {
  572. static typename Associator<WriteHandler, DefaultCandidate>::type get(
  573. const detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
  574. CompletionCondition, WriteHandler>& h) noexcept
  575. {
  576. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
  577. }
  578. static auto get(
  579. const detail::write_dynbuf_v1_op<AsyncWriteStream,
  580. DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
  581. const DefaultCandidate& c) noexcept
  582. -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
  583. {
  584. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
  585. }
  586. };
  587. #endif // !defined(GENERATING_DOCUMENTATION)
  588. template <typename AsyncWriteStream, typename DynamicBuffer_v1,
  589. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  590. std::size_t)) WriteToken>
  591. inline auto async_write(AsyncWriteStream& s,
  592. DynamicBuffer_v1&& buffers, WriteToken&& token,
  593. constraint_t<
  594. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  595. >,
  596. constraint_t<
  597. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  598. >)
  599. -> decltype(
  600. async_initiate<WriteToken,
  601. void (boost::system::error_code, std::size_t)>(
  602. declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
  603. token, static_cast<DynamicBuffer_v1&&>(buffers),
  604. transfer_all()))
  605. {
  606. return async_initiate<WriteToken,
  607. void (boost::system::error_code, std::size_t)>(
  608. detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
  609. token, static_cast<DynamicBuffer_v1&&>(buffers),
  610. transfer_all());
  611. }
  612. template <typename AsyncWriteStream,
  613. typename DynamicBuffer_v1, typename CompletionCondition,
  614. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  615. std::size_t)) WriteToken>
  616. inline auto async_write(AsyncWriteStream& s, DynamicBuffer_v1&& buffers,
  617. CompletionCondition completion_condition, WriteToken&& token,
  618. constraint_t<
  619. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  620. >,
  621. constraint_t<
  622. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  623. >)
  624. -> decltype(
  625. async_initiate<WriteToken,
  626. void (boost::system::error_code, std::size_t)>(
  627. declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
  628. token, static_cast<DynamicBuffer_v1&&>(buffers),
  629. static_cast<CompletionCondition&&>(completion_condition)))
  630. {
  631. return async_initiate<WriteToken,
  632. void (boost::system::error_code, std::size_t)>(
  633. detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
  634. token, static_cast<DynamicBuffer_v1&&>(buffers),
  635. static_cast<CompletionCondition&&>(completion_condition));
  636. }
  637. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  638. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  639. template <typename AsyncWriteStream, typename Allocator,
  640. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  641. std::size_t)) WriteToken>
  642. inline auto async_write(AsyncWriteStream& s,
  643. boost::asio::basic_streambuf<Allocator>& b,
  644. WriteToken&& token)
  645. -> decltype(
  646. async_initiate<WriteToken,
  647. void (boost::system::error_code, std::size_t)>(
  648. declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
  649. token, basic_streambuf_ref<Allocator>(b), transfer_all()))
  650. {
  651. return async_initiate<WriteToken,
  652. void (boost::system::error_code, std::size_t)>(
  653. detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
  654. token, basic_streambuf_ref<Allocator>(b), transfer_all());
  655. }
  656. template <typename AsyncWriteStream,
  657. typename Allocator, typename CompletionCondition,
  658. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  659. std::size_t)) WriteToken>
  660. inline auto async_write(AsyncWriteStream& s,
  661. boost::asio::basic_streambuf<Allocator>& b,
  662. CompletionCondition completion_condition, WriteToken&& token)
  663. -> decltype(
  664. async_initiate<WriteToken,
  665. void (boost::system::error_code, std::size_t)>(
  666. declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
  667. token, basic_streambuf_ref<Allocator>(b),
  668. static_cast<CompletionCondition&&>(completion_condition)))
  669. {
  670. return async_initiate<WriteToken,
  671. void (boost::system::error_code, std::size_t)>(
  672. detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
  673. token, basic_streambuf_ref<Allocator>(b),
  674. static_cast<CompletionCondition&&>(completion_condition));
  675. }
  676. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  677. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  678. #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  679. namespace detail
  680. {
  681. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  682. typename CompletionCondition, typename WriteHandler>
  683. class write_dynbuf_v2_op
  684. {
  685. public:
  686. template <typename BufferSequence>
  687. write_dynbuf_v2_op(AsyncWriteStream& stream,
  688. BufferSequence&& buffers,
  689. CompletionCondition& completion_condition, WriteHandler& handler)
  690. : stream_(stream),
  691. buffers_(static_cast<BufferSequence&&>(buffers)),
  692. completion_condition_(
  693. static_cast<CompletionCondition&&>(completion_condition)),
  694. handler_(static_cast<WriteHandler&&>(handler))
  695. {
  696. }
  697. write_dynbuf_v2_op(const write_dynbuf_v2_op& other)
  698. : stream_(other.stream_),
  699. buffers_(other.buffers_),
  700. completion_condition_(other.completion_condition_),
  701. handler_(other.handler_)
  702. {
  703. }
  704. write_dynbuf_v2_op(write_dynbuf_v2_op&& other)
  705. : stream_(other.stream_),
  706. buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
  707. completion_condition_(
  708. static_cast<CompletionCondition&&>(
  709. other.completion_condition_)),
  710. handler_(static_cast<WriteHandler&&>(other.handler_))
  711. {
  712. }
  713. void operator()(const boost::system::error_code& ec,
  714. std::size_t bytes_transferred, int start = 0)
  715. {
  716. switch (start)
  717. {
  718. case 1:
  719. async_write(stream_, buffers_.data(0, buffers_.size()),
  720. static_cast<CompletionCondition&&>(completion_condition_),
  721. static_cast<write_dynbuf_v2_op&&>(*this));
  722. return; default:
  723. buffers_.consume(bytes_transferred);
  724. static_cast<WriteHandler&&>(handler_)(ec,
  725. static_cast<const std::size_t&>(bytes_transferred));
  726. }
  727. }
  728. //private:
  729. AsyncWriteStream& stream_;
  730. DynamicBuffer_v2 buffers_;
  731. CompletionCondition completion_condition_;
  732. WriteHandler handler_;
  733. };
  734. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  735. typename CompletionCondition, typename WriteHandler>
  736. inline bool asio_handler_is_continuation(
  737. write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  738. CompletionCondition, WriteHandler>* this_handler)
  739. {
  740. return boost_asio_handler_cont_helpers::is_continuation(
  741. this_handler->handler_);
  742. }
  743. template <typename AsyncWriteStream>
  744. class initiate_async_write_dynbuf_v2
  745. {
  746. public:
  747. typedef typename AsyncWriteStream::executor_type executor_type;
  748. explicit initiate_async_write_dynbuf_v2(AsyncWriteStream& stream)
  749. : stream_(stream)
  750. {
  751. }
  752. executor_type get_executor() const noexcept
  753. {
  754. return stream_.get_executor();
  755. }
  756. template <typename WriteHandler, typename DynamicBuffer_v2,
  757. typename CompletionCondition>
  758. void operator()(WriteHandler&& handler,
  759. DynamicBuffer_v2&& buffers,
  760. CompletionCondition&& completion_cond) const
  761. {
  762. // If you get an error on the following line it means that your handler
  763. // does not meet the documented type requirements for a WriteHandler.
  764. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  765. non_const_lvalue<WriteHandler> handler2(handler);
  766. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  767. write_dynbuf_v2_op<AsyncWriteStream, decay_t<DynamicBuffer_v2>,
  768. CompletionCondition, decay_t<WriteHandler>>(
  769. stream_, static_cast<DynamicBuffer_v2&&>(buffers),
  770. completion_cond2.value, handler2.value)(
  771. boost::system::error_code(), 0, 1);
  772. }
  773. private:
  774. AsyncWriteStream& stream_;
  775. };
  776. } // namespace detail
  777. #if !defined(GENERATING_DOCUMENTATION)
  778. template <template <typename, typename> class Associator,
  779. typename AsyncWriteStream, typename DynamicBuffer_v2,
  780. typename CompletionCondition, typename WriteHandler,
  781. typename DefaultCandidate>
  782. struct associator<Associator,
  783. detail::write_dynbuf_v2_op<AsyncWriteStream,
  784. DynamicBuffer_v2, CompletionCondition, WriteHandler>,
  785. DefaultCandidate>
  786. : Associator<WriteHandler, DefaultCandidate>
  787. {
  788. static typename Associator<WriteHandler, DefaultCandidate>::type get(
  789. const detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
  790. CompletionCondition, WriteHandler>& h) noexcept
  791. {
  792. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
  793. }
  794. static auto get(
  795. const detail::write_dynbuf_v2_op<AsyncWriteStream,
  796. DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
  797. const DefaultCandidate& c) noexcept
  798. -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
  799. {
  800. return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
  801. }
  802. };
  803. #endif // !defined(GENERATING_DOCUMENTATION)
  804. template <typename AsyncWriteStream, typename DynamicBuffer_v2,
  805. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  806. std::size_t)) WriteToken>
  807. inline auto async_write(AsyncWriteStream& s,
  808. DynamicBuffer_v2 buffers, WriteToken&& token,
  809. constraint_t<
  810. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  811. >)
  812. -> decltype(
  813. async_initiate<WriteToken,
  814. void (boost::system::error_code, std::size_t)>(
  815. declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>>(),
  816. token, static_cast<DynamicBuffer_v2&&>(buffers),
  817. transfer_all()))
  818. {
  819. return async_initiate<WriteToken,
  820. void (boost::system::error_code, std::size_t)>(
  821. detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),
  822. token, static_cast<DynamicBuffer_v2&&>(buffers),
  823. transfer_all());
  824. }
  825. template <typename AsyncWriteStream,
  826. typename DynamicBuffer_v2, typename CompletionCondition,
  827. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  828. std::size_t)) WriteToken>
  829. inline auto async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
  830. CompletionCondition completion_condition, WriteToken&& token,
  831. constraint_t<
  832. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  833. >)
  834. -> decltype(
  835. async_initiate<WriteToken,
  836. void (boost::system::error_code, std::size_t)>(
  837. declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>>(),
  838. token, static_cast<DynamicBuffer_v2&&>(buffers),
  839. static_cast<CompletionCondition&&>(completion_condition)))
  840. {
  841. return async_initiate<WriteToken,
  842. void (boost::system::error_code, std::size_t)>(
  843. detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),
  844. token, static_cast<DynamicBuffer_v2&&>(buffers),
  845. static_cast<CompletionCondition&&>(completion_condition));
  846. }
  847. } // namespace asio
  848. } // namespace boost
  849. #include <boost/asio/detail/pop_options.hpp>
  850. #endif // BOOST_ASIO_IMPL_WRITE_HPP