write.ipp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. //
  2. // write.ipp
  3. // ~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2010 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_WRITE_IPP
  11. #define ASIO_WRITE_IPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/push_options.hpp"
  16. #include "asio/buffer.hpp"
  17. #include "asio/completion_condition.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/handler_alloc_helpers.hpp"
  22. #include "asio/detail/handler_invoke_helpers.hpp"
  23. #include "asio/detail/throw_error.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. start_(true)
  113. {
  114. }
  115. void operator()(const asio::error_code& ec,
  116. std::size_t bytes_transferred)
  117. {
  118. switch (start_)
  119. {
  120. case true: start_ = false;
  121. buffers_.prepare(this->check(ec, total_transferred_));
  122. for (;;)
  123. {
  124. stream_.async_write_some(buffers_, *this);
  125. return; default:
  126. total_transferred_ += bytes_transferred;
  127. buffers_.consume(bytes_transferred);
  128. buffers_.prepare(this->check(ec, total_transferred_));
  129. if ((!ec && bytes_transferred == 0)
  130. || buffers_.begin() == buffers_.end())
  131. break;
  132. }
  133. handler_(ec, total_transferred_);
  134. }
  135. }
  136. //private:
  137. AsyncWriteStream& stream_;
  138. asio::detail::consuming_buffers<
  139. const_buffer, ConstBufferSequence> buffers_;
  140. std::size_t total_transferred_;
  141. WriteHandler handler_;
  142. bool start_;
  143. };
  144. template <typename AsyncWriteStream,
  145. typename CompletionCondition, typename WriteHandler>
  146. class write_op<AsyncWriteStream, asio::mutable_buffers_1,
  147. CompletionCondition, WriteHandler>
  148. : detail::base_from_completion_cond<CompletionCondition>
  149. {
  150. public:
  151. write_op(AsyncWriteStream& stream,
  152. const asio::mutable_buffers_1& buffers,
  153. CompletionCondition completion_condition,
  154. WriteHandler handler)
  155. : detail::base_from_completion_cond<
  156. CompletionCondition>(completion_condition),
  157. stream_(stream),
  158. buffer_(buffers),
  159. total_transferred_(0),
  160. handler_(handler),
  161. start_(true)
  162. {
  163. }
  164. void operator()(const asio::error_code& ec,
  165. std::size_t bytes_transferred)
  166. {
  167. std::size_t n = 0;
  168. switch (start_)
  169. {
  170. case true: start_ = false;
  171. n = this->check(ec, total_transferred_);
  172. for (;;)
  173. {
  174. stream_.async_write_some(asio::buffer(
  175. buffer_ + total_transferred_, n), *this);
  176. return; default:
  177. total_transferred_ += bytes_transferred;
  178. if ((!ec && bytes_transferred == 0)
  179. || (n = this->check(ec, total_transferred_)) == 0
  180. || total_transferred_ == asio::buffer_size(buffer_))
  181. break;
  182. }
  183. handler_(ec, total_transferred_);
  184. }
  185. }
  186. //private:
  187. AsyncWriteStream& stream_;
  188. asio::mutable_buffer buffer_;
  189. std::size_t total_transferred_;
  190. WriteHandler handler_;
  191. bool start_;
  192. };
  193. template <typename AsyncWriteStream,
  194. typename CompletionCondition, typename WriteHandler>
  195. class write_op<AsyncWriteStream, asio::const_buffers_1,
  196. CompletionCondition, WriteHandler>
  197. : detail::base_from_completion_cond<CompletionCondition>
  198. {
  199. public:
  200. write_op(AsyncWriteStream& stream,
  201. const asio::const_buffers_1& buffers,
  202. CompletionCondition completion_condition,
  203. WriteHandler handler)
  204. : detail::base_from_completion_cond<
  205. CompletionCondition>(completion_condition),
  206. stream_(stream),
  207. buffer_(buffers),
  208. total_transferred_(0),
  209. handler_(handler),
  210. start_(true)
  211. {
  212. }
  213. void operator()(const asio::error_code& ec,
  214. std::size_t bytes_transferred)
  215. {
  216. std::size_t n = 0;
  217. switch (start_)
  218. {
  219. case true: start_ = false;
  220. n = this->check(ec, total_transferred_);
  221. for (;;)
  222. {
  223. stream_.async_write_some(asio::buffer(
  224. buffer_ + total_transferred_, n), *this);
  225. return; default:
  226. total_transferred_ += bytes_transferred;
  227. if ((!ec && bytes_transferred == 0)
  228. || (n = this->check(ec, total_transferred_)) == 0
  229. || total_transferred_ == asio::buffer_size(buffer_))
  230. break;
  231. }
  232. handler_(ec, total_transferred_);
  233. }
  234. }
  235. //private:
  236. AsyncWriteStream& stream_;
  237. asio::const_buffer buffer_;
  238. std::size_t total_transferred_;
  239. WriteHandler handler_;
  240. bool start_;
  241. };
  242. template <typename AsyncWriteStream, typename ConstBufferSequence,
  243. typename CompletionCondition, typename WriteHandler>
  244. inline void* asio_handler_allocate(std::size_t size,
  245. write_op<AsyncWriteStream, ConstBufferSequence,
  246. CompletionCondition, WriteHandler>* this_handler)
  247. {
  248. return asio_handler_alloc_helpers::allocate(
  249. size, this_handler->handler_);
  250. }
  251. template <typename AsyncWriteStream, typename ConstBufferSequence,
  252. typename CompletionCondition, typename WriteHandler>
  253. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  254. write_op<AsyncWriteStream, ConstBufferSequence,
  255. CompletionCondition, WriteHandler>* this_handler)
  256. {
  257. asio_handler_alloc_helpers::deallocate(
  258. pointer, size, this_handler->handler_);
  259. }
  260. template <typename Function, typename AsyncWriteStream,
  261. typename ConstBufferSequence, typename CompletionCondition,
  262. typename WriteHandler>
  263. inline void asio_handler_invoke(const Function& function,
  264. write_op<AsyncWriteStream, ConstBufferSequence,
  265. CompletionCondition, WriteHandler>* this_handler)
  266. {
  267. asio_handler_invoke_helpers::invoke(
  268. function, this_handler->handler_);
  269. }
  270. } // namespace detail
  271. template <typename AsyncWriteStream, typename ConstBufferSequence,
  272. typename CompletionCondition, typename WriteHandler>
  273. inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  274. CompletionCondition completion_condition, WriteHandler handler)
  275. {
  276. detail::write_op<AsyncWriteStream, ConstBufferSequence,
  277. CompletionCondition, WriteHandler>(
  278. s, buffers, completion_condition, handler)(
  279. asio::error_code(), 0);
  280. }
  281. template <typename AsyncWriteStream, typename ConstBufferSequence,
  282. typename WriteHandler>
  283. inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
  284. WriteHandler handler)
  285. {
  286. async_write(s, buffers, transfer_all(), handler);
  287. }
  288. #if !defined(BOOST_NO_IOSTREAM)
  289. namespace detail
  290. {
  291. template <typename AsyncWriteStream, typename Allocator,
  292. typename WriteHandler>
  293. class write_streambuf_handler
  294. {
  295. public:
  296. write_streambuf_handler(asio::basic_streambuf<Allocator>& streambuf,
  297. WriteHandler handler)
  298. : streambuf_(streambuf),
  299. handler_(handler)
  300. {
  301. }
  302. void operator()(const asio::error_code& ec,
  303. std::size_t bytes_transferred)
  304. {
  305. streambuf_.consume(bytes_transferred);
  306. handler_(ec, bytes_transferred);
  307. }
  308. //private:
  309. asio::basic_streambuf<Allocator>& streambuf_;
  310. WriteHandler handler_;
  311. };
  312. template <typename AsyncWriteStream, typename Allocator,
  313. typename WriteHandler>
  314. inline void* asio_handler_allocate(std::size_t size,
  315. write_streambuf_handler<AsyncWriteStream,
  316. Allocator, WriteHandler>* this_handler)
  317. {
  318. return asio_handler_alloc_helpers::allocate(
  319. size, this_handler->handler_);
  320. }
  321. template <typename AsyncWriteStream, typename Allocator,
  322. typename WriteHandler>
  323. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  324. write_streambuf_handler<AsyncWriteStream,
  325. Allocator, WriteHandler>* this_handler)
  326. {
  327. asio_handler_alloc_helpers::deallocate(
  328. pointer, size, this_handler->handler_);
  329. }
  330. template <typename Function, typename AsyncWriteStream, typename Allocator,
  331. typename WriteHandler>
  332. inline void asio_handler_invoke(const Function& function,
  333. write_streambuf_handler<AsyncWriteStream,
  334. Allocator, WriteHandler>* this_handler)
  335. {
  336. asio_handler_invoke_helpers::invoke(
  337. function, this_handler->handler_);
  338. }
  339. } // namespace detail
  340. template <typename AsyncWriteStream, typename Allocator,
  341. typename CompletionCondition, typename WriteHandler>
  342. inline void async_write(AsyncWriteStream& s,
  343. asio::basic_streambuf<Allocator>& b,
  344. CompletionCondition completion_condition, WriteHandler handler)
  345. {
  346. async_write(s, b.data(), completion_condition,
  347. detail::write_streambuf_handler<
  348. AsyncWriteStream, Allocator, WriteHandler>(b, handler));
  349. }
  350. template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
  351. inline void async_write(AsyncWriteStream& s,
  352. asio::basic_streambuf<Allocator>& b, WriteHandler handler)
  353. {
  354. async_write(s, b, transfer_all(), handler);
  355. }
  356. #endif // !defined(BOOST_NO_IOSTREAM)
  357. } // namespace asio
  358. #include "asio/detail/pop_options.hpp"
  359. #endif // ASIO_WRITE_IPP