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.

407 lines
12KB

  1. //
  2. // impl/buffered_write_stream.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_BUFFERED_WRITE_STREAM_HPP
  11. #define ASIO_IMPL_BUFFERED_WRITE_STREAM_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/detail/handler_alloc_helpers.hpp"
  18. #include "asio/detail/handler_cont_helpers.hpp"
  19. #include "asio/detail/handler_invoke_helpers.hpp"
  20. #include "asio/detail/handler_type_requirements.hpp"
  21. #include "asio/detail/push_options.hpp"
  22. namespace asio {
  23. template <typename Stream>
  24. std::size_t buffered_write_stream<Stream>::flush()
  25. {
  26. std::size_t bytes_written = write(next_layer_,
  27. buffer(storage_.data(), storage_.size()));
  28. storage_.consume(bytes_written);
  29. return bytes_written;
  30. }
  31. template <typename Stream>
  32. std::size_t buffered_write_stream<Stream>::flush(asio::error_code& ec)
  33. {
  34. std::size_t bytes_written = write(next_layer_,
  35. buffer(storage_.data(), storage_.size()),
  36. transfer_all(), ec);
  37. storage_.consume(bytes_written);
  38. return bytes_written;
  39. }
  40. namespace detail
  41. {
  42. template <typename WriteHandler>
  43. class buffered_flush_handler
  44. {
  45. public:
  46. buffered_flush_handler(detail::buffered_stream_storage& storage,
  47. WriteHandler& handler)
  48. : storage_(storage),
  49. handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
  50. {
  51. }
  52. #if defined(ASIO_HAS_MOVE)
  53. buffered_flush_handler(const buffered_flush_handler& other)
  54. : storage_(other.storage_),
  55. handler_(other.handler_)
  56. {
  57. }
  58. buffered_flush_handler(buffered_flush_handler&& other)
  59. : storage_(other.storage_),
  60. handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  61. {
  62. }
  63. #endif // defined(ASIO_HAS_MOVE)
  64. void operator()(const asio::error_code& ec,
  65. const std::size_t bytes_written)
  66. {
  67. storage_.consume(bytes_written);
  68. handler_(ec, bytes_written);
  69. }
  70. //private:
  71. detail::buffered_stream_storage& storage_;
  72. WriteHandler handler_;
  73. };
  74. template <typename WriteHandler>
  75. inline void* asio_handler_allocate(std::size_t size,
  76. buffered_flush_handler<WriteHandler>* this_handler)
  77. {
  78. return asio_handler_alloc_helpers::allocate(
  79. size, this_handler->handler_);
  80. }
  81. template <typename WriteHandler>
  82. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  83. buffered_flush_handler<WriteHandler>* this_handler)
  84. {
  85. asio_handler_alloc_helpers::deallocate(
  86. pointer, size, this_handler->handler_);
  87. }
  88. template <typename WriteHandler>
  89. inline bool asio_handler_is_continuation(
  90. buffered_flush_handler<WriteHandler>* this_handler)
  91. {
  92. return asio_handler_cont_helpers::is_continuation(
  93. this_handler->handler_);
  94. }
  95. template <typename Function, typename WriteHandler>
  96. inline void asio_handler_invoke(Function& function,
  97. buffered_flush_handler<WriteHandler>* this_handler)
  98. {
  99. asio_handler_invoke_helpers::invoke(
  100. function, this_handler->handler_);
  101. }
  102. template <typename Function, typename WriteHandler>
  103. inline void asio_handler_invoke(const Function& function,
  104. buffered_flush_handler<WriteHandler>* this_handler)
  105. {
  106. asio_handler_invoke_helpers::invoke(
  107. function, this_handler->handler_);
  108. }
  109. } // namespace detail
  110. #if !defined(GENERATING_DOCUMENTATION)
  111. template <typename WriteHandler, typename Allocator>
  112. struct associated_allocator<
  113. detail::buffered_flush_handler<WriteHandler>, Allocator>
  114. {
  115. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  116. static type get(const detail::buffered_flush_handler<WriteHandler>& h,
  117. const Allocator& a = Allocator()) ASIO_NOEXCEPT
  118. {
  119. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  120. }
  121. };
  122. template <typename WriteHandler, typename Executor>
  123. struct associated_executor<
  124. detail::buffered_flush_handler<WriteHandler>, Executor>
  125. {
  126. typedef typename associated_executor<WriteHandler, Executor>::type type;
  127. static type get(const detail::buffered_flush_handler<WriteHandler>& h,
  128. const Executor& ex = Executor()) ASIO_NOEXCEPT
  129. {
  130. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  131. }
  132. };
  133. #endif // !defined(GENERATING_DOCUMENTATION)
  134. template <typename Stream>
  135. template <typename WriteHandler>
  136. ASIO_INITFN_RESULT_TYPE(WriteHandler,
  137. void (asio::error_code, std::size_t))
  138. buffered_write_stream<Stream>::async_flush(
  139. ASIO_MOVE_ARG(WriteHandler) handler)
  140. {
  141. // If you get an error on the following line it means that your handler does
  142. // not meet the documented type requirements for a WriteHandler.
  143. ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  144. async_completion<WriteHandler,
  145. void (asio::error_code, std::size_t)> init(handler);
  146. async_write(next_layer_, buffer(storage_.data(), storage_.size()),
  147. detail::buffered_flush_handler<ASIO_HANDLER_TYPE(
  148. WriteHandler, void (asio::error_code, std::size_t))>(
  149. storage_, init.handler));
  150. return init.result.get();
  151. }
  152. template <typename Stream>
  153. template <typename ConstBufferSequence>
  154. std::size_t buffered_write_stream<Stream>::write_some(
  155. const ConstBufferSequence& buffers)
  156. {
  157. if (asio::buffer_size(buffers) == 0)
  158. return 0;
  159. if (storage_.size() == storage_.capacity())
  160. this->flush();
  161. return this->copy(buffers);
  162. }
  163. template <typename Stream>
  164. template <typename ConstBufferSequence>
  165. std::size_t buffered_write_stream<Stream>::write_some(
  166. const ConstBufferSequence& buffers, asio::error_code& ec)
  167. {
  168. ec = asio::error_code();
  169. if (asio::buffer_size(buffers) == 0)
  170. return 0;
  171. if (storage_.size() == storage_.capacity() && !flush(ec))
  172. return 0;
  173. return this->copy(buffers);
  174. }
  175. namespace detail
  176. {
  177. template <typename ConstBufferSequence, typename WriteHandler>
  178. class buffered_write_some_handler
  179. {
  180. public:
  181. buffered_write_some_handler(detail::buffered_stream_storage& storage,
  182. const ConstBufferSequence& buffers, WriteHandler& handler)
  183. : storage_(storage),
  184. buffers_(buffers),
  185. handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
  186. {
  187. }
  188. #if defined(ASIO_HAS_MOVE)
  189. buffered_write_some_handler(const buffered_write_some_handler& other)
  190. : storage_(other.storage_),
  191. buffers_(other.buffers_),
  192. handler_(other.handler_)
  193. {
  194. }
  195. buffered_write_some_handler(buffered_write_some_handler&& other)
  196. : storage_(other.storage_),
  197. buffers_(other.buffers_),
  198. handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
  199. {
  200. }
  201. #endif // defined(ASIO_HAS_MOVE)
  202. void operator()(const asio::error_code& ec, std::size_t)
  203. {
  204. if (ec)
  205. {
  206. const std::size_t length = 0;
  207. handler_(ec, length);
  208. }
  209. else
  210. {
  211. std::size_t orig_size = storage_.size();
  212. std::size_t space_avail = storage_.capacity() - orig_size;
  213. std::size_t bytes_avail = asio::buffer_size(buffers_);
  214. std::size_t length = bytes_avail < space_avail
  215. ? bytes_avail : space_avail;
  216. storage_.resize(orig_size + length);
  217. const std::size_t bytes_copied = asio::buffer_copy(
  218. storage_.data() + orig_size, buffers_, length);
  219. handler_(ec, bytes_copied);
  220. }
  221. }
  222. //private:
  223. detail::buffered_stream_storage& storage_;
  224. ConstBufferSequence buffers_;
  225. WriteHandler handler_;
  226. };
  227. template <typename ConstBufferSequence, typename WriteHandler>
  228. inline void* asio_handler_allocate(std::size_t size,
  229. buffered_write_some_handler<
  230. ConstBufferSequence, WriteHandler>* this_handler)
  231. {
  232. return asio_handler_alloc_helpers::allocate(
  233. size, this_handler->handler_);
  234. }
  235. template <typename ConstBufferSequence, typename WriteHandler>
  236. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  237. buffered_write_some_handler<
  238. ConstBufferSequence, WriteHandler>* this_handler)
  239. {
  240. asio_handler_alloc_helpers::deallocate(
  241. pointer, size, this_handler->handler_);
  242. }
  243. template <typename ConstBufferSequence, typename WriteHandler>
  244. inline bool asio_handler_is_continuation(
  245. buffered_write_some_handler<
  246. ConstBufferSequence, WriteHandler>* this_handler)
  247. {
  248. return asio_handler_cont_helpers::is_continuation(
  249. this_handler->handler_);
  250. }
  251. template <typename Function, typename ConstBufferSequence,
  252. typename WriteHandler>
  253. inline void asio_handler_invoke(Function& function,
  254. buffered_write_some_handler<
  255. ConstBufferSequence, WriteHandler>* this_handler)
  256. {
  257. asio_handler_invoke_helpers::invoke(
  258. function, this_handler->handler_);
  259. }
  260. template <typename Function, typename ConstBufferSequence,
  261. typename WriteHandler>
  262. inline void asio_handler_invoke(const Function& function,
  263. buffered_write_some_handler<
  264. ConstBufferSequence, WriteHandler>* this_handler)
  265. {
  266. asio_handler_invoke_helpers::invoke(
  267. function, this_handler->handler_);
  268. }
  269. } // namespace detail
  270. #if !defined(GENERATING_DOCUMENTATION)
  271. template <typename ConstBufferSequence,
  272. typename WriteHandler, typename Allocator>
  273. struct associated_allocator<
  274. detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,
  275. Allocator>
  276. {
  277. typedef typename associated_allocator<WriteHandler, Allocator>::type type;
  278. static type get(
  279. const detail::buffered_write_some_handler<
  280. ConstBufferSequence, WriteHandler>& h,
  281. const Allocator& a = Allocator()) ASIO_NOEXCEPT
  282. {
  283. return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
  284. }
  285. };
  286. template <typename ConstBufferSequence,
  287. typename WriteHandler, typename Executor>
  288. struct associated_executor<
  289. detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,
  290. Executor>
  291. {
  292. typedef typename associated_executor<WriteHandler, Executor>::type type;
  293. static type get(
  294. const detail::buffered_write_some_handler<
  295. ConstBufferSequence, WriteHandler>& h,
  296. const Executor& ex = Executor()) ASIO_NOEXCEPT
  297. {
  298. return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
  299. }
  300. };
  301. #endif // !defined(GENERATING_DOCUMENTATION)
  302. template <typename Stream>
  303. template <typename ConstBufferSequence, typename WriteHandler>
  304. ASIO_INITFN_RESULT_TYPE(WriteHandler,
  305. void (asio::error_code, std::size_t))
  306. buffered_write_stream<Stream>::async_write_some(
  307. const ConstBufferSequence& buffers,
  308. ASIO_MOVE_ARG(WriteHandler) handler)
  309. {
  310. // If you get an error on the following line it means that your handler does
  311. // not meet the documented type requirements for a WriteHandler.
  312. ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  313. async_completion<WriteHandler,
  314. void (asio::error_code, std::size_t)> init(handler);
  315. if (asio::buffer_size(buffers) == 0
  316. || storage_.size() < storage_.capacity())
  317. {
  318. next_layer_.async_write_some(asio::const_buffers_1(0, 0),
  319. detail::buffered_write_some_handler<
  320. ConstBufferSequence, ASIO_HANDLER_TYPE(
  321. WriteHandler, void (asio::error_code, std::size_t))>(
  322. storage_, buffers, init.handler));
  323. }
  324. else
  325. {
  326. this->async_flush(detail::buffered_write_some_handler<
  327. ConstBufferSequence, ASIO_HANDLER_TYPE(
  328. WriteHandler, void (asio::error_code, std::size_t))>(
  329. storage_, buffers, init.handler));
  330. }
  331. return init.result.get();
  332. }
  333. template <typename Stream>
  334. template <typename ConstBufferSequence>
  335. std::size_t buffered_write_stream<Stream>::copy(
  336. const ConstBufferSequence& buffers)
  337. {
  338. std::size_t orig_size = storage_.size();
  339. std::size_t space_avail = storage_.capacity() - orig_size;
  340. std::size_t bytes_avail = asio::buffer_size(buffers);
  341. std::size_t length = bytes_avail < space_avail ? bytes_avail : space_avail;
  342. storage_.resize(orig_size + length);
  343. return asio::buffer_copy(
  344. storage_.data() + orig_size, buffers, length);
  345. }
  346. } // namespace asio
  347. #include "asio/detail/pop_options.hpp"
  348. #endif // ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP