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.

979 lines
34KB

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