Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

write.hpp 32KB

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