write.hpp 25 KB

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