write.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. //
  2. // impl/write.hpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2011 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/base_from_completion_cond.hpp"
  18. #include "asio/detail/bind_handler.hpp"
  19. #include "asio/detail/consuming_buffers.hpp"
  20. #include "asio/detail/handler_alloc_helpers.hpp"
  21. #include "asio/detail/handler_invoke_helpers.hpp"
  22. #include "asio/detail/throw_error.hpp"
  23. #include "asio/detail/push_options.hpp"
  24. namespace asio {
  25. template <typename SyncWriteStream, typename ConstBufferSequence,
  26. typename CompletionCondition>
  27. std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  28. CompletionCondition completion_condition, asio::error_code& ec)
  29. {
  30. ec = asio::error_code();
  31. asio::detail::consuming_buffers<
  32. const_buffer, ConstBufferSequence> tmp(buffers);
  33. std::size_t total_transferred = 0;
  34. tmp.prepare(detail::adapt_completion_condition_result(
  35. completion_condition(ec, total_transferred)));
  36. while (tmp.begin() != tmp.end())
  37. {
  38. std::size_t bytes_transferred = s.write_some(tmp, ec);
  39. tmp.consume(bytes_transferred);
  40. total_transferred += bytes_transferred;
  41. tmp.prepare(detail::adapt_completion_condition_result(
  42. completion_condition(ec, total_transferred)));
  43. }
  44. return total_transferred;
  45. }
  46. template <typename SyncWriteStream, typename ConstBufferSequence>
  47. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers)
  48. {
  49. asio::error_code ec;
  50. std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
  51. asio::detail::throw_error(ec);
  52. return bytes_transferred;
  53. }
  54. template <typename SyncWriteStream, typename ConstBufferSequence,
  55. typename CompletionCondition>
  56. inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
  57. CompletionCondition completion_condition)
  58. {
  59. asio::error_code ec;
  60. std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
  61. asio::detail::throw_error(ec);
  62. return bytes_transferred;
  63. }
  64. #if !defined(BOOST_NO_IOSTREAM)
  65. template <typename SyncWriteStream, typename Allocator,
  66. typename CompletionCondition>
  67. std::size_t write(SyncWriteStream& s,
  68. asio::basic_streambuf<Allocator>& b,
  69. CompletionCondition completion_condition, asio::error_code& ec)
  70. {
  71. std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
  72. b.consume(bytes_transferred);
  73. return bytes_transferred;
  74. }
  75. template <typename SyncWriteStream, typename Allocator>
  76. inline std::size_t write(SyncWriteStream& s,
  77. asio::basic_streambuf<Allocator>& b)
  78. {
  79. asio::error_code ec;
  80. std::size_t bytes_transferred = write(s, b, transfer_all(), ec);
  81. asio::detail::throw_error(ec);
  82. return bytes_transferred;
  83. }
  84. template <typename SyncWriteStream, typename Allocator,
  85. typename CompletionCondition>
  86. inline std::size_t write(SyncWriteStream& s,
  87. asio::basic_streambuf<Allocator>& b,
  88. CompletionCondition completion_condition)
  89. {
  90. asio::error_code ec;
  91. std::size_t bytes_transferred = write(s, b, completion_condition, ec);
  92. asio::detail::throw_error(ec);
  93. return bytes_transferred;
  94. }
  95. #endif // !defined(BOOST_NO_IOSTREAM)
  96. namespace detail
  97. {
  98. template <typename AsyncWriteStream, typename ConstBufferSequence,
  99. typename CompletionCondition, typename WriteHandler>
  100. class write_op
  101. : detail::base_from_completion_cond<CompletionCondition>
  102. {
  103. public:
  104. write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
  105. CompletionCondition completion_condition, WriteHandler handler)
  106. : detail::base_from_completion_cond<
  107. CompletionCondition>(completion_condition),
  108. stream_(stream),
  109. buffers_(buffers),
  110. total_transferred_(0),
  111. handler_(handler)
  112. {
  113. }
  114. void operator()(const asio::error_code& ec,
  115. std::size_t bytes_transferred, int start = 0)
  116. {
  117. switch (start)
  118. {
  119. case 1:
  120. buffers_.prepare(this->check_for_completion(ec, total_transferred_));
  121. for (;;)
  122. {
  123. stream_.async_write_some(buffers_, *this);
  124. return; default:
  125. total_transferred_ += bytes_transferred;
  126. buffers_.consume(bytes_transferred);
  127. buffers_.prepare(this->check_for_completion(ec, total_transferred_));
  128. if ((!ec && bytes_transferred == 0)
  129. || buffers_.begin() == buffers_.end())
  130. break;
  131. }
  132. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  133. }
  134. }
  135. //private:
  136. AsyncWriteStream& stream_;
  137. asio::detail::consuming_buffers<
  138. const_buffer, ConstBufferSequence> buffers_;
  139. std::size_t total_transferred_;
  140. WriteHandler handler_;
  141. };
  142. template <typename AsyncWriteStream,
  143. typename CompletionCondition, typename WriteHandler>
  144. class write_op<AsyncWriteStream, asio::mutable_buffers_1,
  145. CompletionCondition, WriteHandler>
  146. : detail::base_from_completion_cond<CompletionCondition>
  147. {
  148. public:
  149. write_op(AsyncWriteStream& stream,
  150. const asio::mutable_buffers_1& buffers,
  151. CompletionCondition completion_condition,
  152. WriteHandler handler)
  153. : detail::base_from_completion_cond<
  154. CompletionCondition>(completion_condition),
  155. stream_(stream),
  156. buffer_(buffers),
  157. total_transferred_(0),
  158. handler_(handler)
  159. {
  160. }
  161. void operator()(const asio::error_code& ec,
  162. std::size_t bytes_transferred, int start = 0)
  163. {
  164. std::size_t n = 0;
  165. switch (start)
  166. {
  167. case 1:
  168. n = this->check_for_completion(ec, total_transferred_);
  169. for (;;)
  170. {
  171. stream_.async_write_some(asio::buffer(
  172. buffer_ + total_transferred_, n), *this);
  173. return; default:
  174. total_transferred_ += bytes_transferred;
  175. if ((!ec && bytes_transferred == 0)
  176. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  177. || total_transferred_ == asio::buffer_size(buffer_))
  178. break;
  179. }
  180. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  181. }
  182. }
  183. //private:
  184. AsyncWriteStream& stream_;
  185. asio::mutable_buffer buffer_;
  186. std::size_t total_transferred_;
  187. WriteHandler handler_;
  188. };
  189. template <typename AsyncWriteStream,
  190. typename CompletionCondition, typename WriteHandler>
  191. class write_op<AsyncWriteStream, asio::const_buffers_1,
  192. CompletionCondition, WriteHandler>
  193. : detail::base_from_completion_cond<CompletionCondition>
  194. {
  195. public:
  196. write_op(AsyncWriteStream& stream,
  197. const asio::const_buffers_1& buffers,
  198. CompletionCondition completion_condition,
  199. WriteHandler handler)
  200. : detail::base_from_completion_cond<
  201. CompletionCondition>(completion_condition),
  202. stream_(stream),
  203. buffer_(buffers),
  204. total_transferred_(0),
  205. handler_(handler)
  206. {
  207. }
  208. void operator()(const asio::error_code& ec,
  209. std::size_t bytes_transferred, int start = 0)
  210. {
  211. std::size_t n = 0;
  212. switch (start)
  213. {
  214. case 1:
  215. n = this->check_for_completion(ec, total_transferred_);
  216. for (;;)
  217. {
  218. stream_.async_write_some(asio::buffer(
  219. buffer_ + total_transferred_, n), *this);
  220. return; default:
  221. total_transferred_ += bytes_transferred;
  222. if ((!ec && bytes_transferred == 0)
  223. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  224. || total_transferred_ == asio::buffer_size(buffer_))
  225. break;
  226. }
  227. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  228. }
  229. }
  230. //private:
  231. AsyncWriteStream& stream_;
  232. asio::const_buffer buffer_;
  233. std::size_t total_transferred_;
  234. WriteHandler handler_;
  235. };
  236. template <typename AsyncWriteStream, typename ConstBufferSequence,
  237. typename CompletionCondition, typename WriteHandler>
  238. inline void* asio_handler_allocate(std::size_t size,
  239. write_op<AsyncWriteStream, ConstBufferSequence,
  240. CompletionCondition, WriteHandler>* this_handler)
  241. {
  242. return asio_handler_alloc_helpers::allocate(
  243. size, this_handler->handler_);
  244. }
  245. template <typename AsyncWriteStream, typename ConstBufferSequence,
  246. typename CompletionCondition, typename WriteHandler>
  247. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  248. write_op<AsyncWriteStream, ConstBufferSequence,
  249. CompletionCondition, WriteHandler>* this_handler)
  250. {
  251. asio_handler_alloc_helpers::deallocate(
  252. pointer, size, this_handler->handler_);
  253. }
  254. template <typename Function, typename AsyncWriteStream,
  255. typename ConstBufferSequence, typename CompletionCondition,
  256. typename WriteHandler>
  257. inline void asio_handler_invoke(const Function& function,
  258. write_op<AsyncWriteStream, ConstBufferSequence,
  259. CompletionCondition, WriteHandler>* this_handler)
  260. {
  261. asio_handler_invoke_helpers::invoke(
  262. function, this_handler->handler_);
  263. }
  264. } // namespace detail
  265. template <typename AsyncWriteStream, typename ConstBufferSequence,
  266. typename CompletionCondition, typename WriteHandler>
  267. inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  268. CompletionCondition completion_condition, WriteHandler handler)
  269. {
  270. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  271. CompletionCondition, WriteHandler>(
  272. s, buffers, completion_condition, handler)(
  273. asio::error_code(), 0, 1);
  274. }
  275. template <typename AsyncWriteStream, typename ConstBufferSequence,
  276. typename WriteHandler>
  277. inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  278. WriteHandler handler)
  279. {
  280. async_write(s, buffers, transfer_all(), handler);
  281. }
  282. #if !defined(BOOST_NO_IOSTREAM)
  283. namespace detail
  284. {
  285. template <typename AsyncWriteStream, typename Allocator,
  286. typename WriteHandler>
  287. class write_streambuf_handler
  288. {
  289. public:
  290. write_streambuf_handler(asio::basic_streambuf<Allocator>& streambuf,
  291. WriteHandler handler)
  292. : streambuf_(streambuf),
  293. handler_(handler)
  294. {
  295. }
  296. void operator()(const asio::error_code& ec,
  297. const std::size_t bytes_transferred)
  298. {
  299. streambuf_.consume(bytes_transferred);
  300. handler_(ec, bytes_transferred);
  301. }
  302. //private:
  303. asio::basic_streambuf<Allocator>& streambuf_;
  304. WriteHandler handler_;
  305. };
  306. template <typename AsyncWriteStream, typename Allocator,
  307. typename WriteHandler>
  308. inline void* asio_handler_allocate(std::size_t size,
  309. write_streambuf_handler<AsyncWriteStream,
  310. Allocator, WriteHandler>* this_handler)
  311. {
  312. return asio_handler_alloc_helpers::allocate(
  313. size, this_handler->handler_);
  314. }
  315. template <typename AsyncWriteStream, typename Allocator,
  316. typename WriteHandler>
  317. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  318. write_streambuf_handler<AsyncWriteStream,
  319. Allocator, WriteHandler>* this_handler)
  320. {
  321. asio_handler_alloc_helpers::deallocate(
  322. pointer, size, this_handler->handler_);
  323. }
  324. template <typename Function, typename AsyncWriteStream, typename Allocator,
  325. typename WriteHandler>
  326. inline void asio_handler_invoke(const Function& function,
  327. write_streambuf_handler<AsyncWriteStream,
  328. Allocator, WriteHandler>* this_handler)
  329. {
  330. asio_handler_invoke_helpers::invoke(
  331. function, this_handler->handler_);
  332. }
  333. } // namespace detail
  334. template <typename AsyncWriteStream, typename Allocator,
  335. typename CompletionCondition, typename WriteHandler>
  336. inline void async_write(AsyncWriteStream& s,
  337. asio::basic_streambuf<Allocator>& b,
  338. CompletionCondition completion_condition, WriteHandler handler)
  339. {
  340. async_write(s, b.data(), completion_condition,
  341. detail::write_streambuf_handler<
  342. AsyncWriteStream, Allocator, WriteHandler>(b, handler));
  343. }
  344. template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
  345. inline void async_write(AsyncWriteStream& s,
  346. asio::basic_streambuf<Allocator>& b, WriteHandler handler)
  347. {
  348. async_write(s, b, transfer_all(), handler);
  349. }
  350. #endif // !defined(BOOST_NO_IOSTREAM)
  351. } // namespace asio
  352. #include "asio/detail/pop_options.hpp"
  353. #endif // ASIO_IMPL_WRITE_HPP