write.hpp 31 KB

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