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.

314 lines
9.2KB

  1. //
  2. // strand.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_STRAND_HPP
  11. #define ASIO_STRAND_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include "asio/detail/strand_executor_service.hpp"
  17. #include "asio/detail/type_traits.hpp"
  18. #include "asio/detail/push_options.hpp"
  19. namespace asio {
  20. /// Provides serialised function invocation for any executor type.
  21. template <typename Executor>
  22. class strand
  23. {
  24. public:
  25. /// The type of the underlying executor.
  26. typedef Executor inner_executor_type;
  27. /// Default constructor.
  28. /**
  29. * This constructor is only valid if the underlying executor type is default
  30. * constructible.
  31. */
  32. strand()
  33. : executor_(),
  34. impl_(use_service<detail::strand_executor_service>(
  35. executor_.context()).create_implementation())
  36. {
  37. }
  38. /// Construct a strand for the specified executor.
  39. explicit strand(const Executor& e)
  40. : executor_(e),
  41. impl_(use_service<detail::strand_executor_service>(
  42. executor_.context()).create_implementation())
  43. {
  44. }
  45. /// Copy constructor.
  46. strand(const strand& other) ASIO_NOEXCEPT
  47. : executor_(other.executor_),
  48. impl_(other.impl_)
  49. {
  50. }
  51. /// Converting constructor.
  52. /**
  53. * This constructor is only valid if the @c OtherExecutor type is convertible
  54. * to @c Executor.
  55. */
  56. template <class OtherExecutor>
  57. strand(
  58. const strand<OtherExecutor>& other) ASIO_NOEXCEPT
  59. : executor_(other.executor_),
  60. impl_(other.impl_)
  61. {
  62. }
  63. /// Assignment operator.
  64. strand& operator=(const strand& other) ASIO_NOEXCEPT
  65. {
  66. executor_ = other.executor_;
  67. impl_ = other.impl_;
  68. return *this;
  69. }
  70. /// Converting assignment operator.
  71. /**
  72. * This assignment operator is only valid if the @c OtherExecutor type is
  73. * convertible to @c Executor.
  74. */
  75. template <class OtherExecutor>
  76. strand& operator=(
  77. const strand<OtherExecutor>& other) ASIO_NOEXCEPT
  78. {
  79. executor_ = other.executor_;
  80. impl_ = other.impl_;
  81. return *this;
  82. }
  83. #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  84. /// Move constructor.
  85. strand(strand&& other) ASIO_NOEXCEPT
  86. : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)),
  87. impl_(ASIO_MOVE_CAST(implementation_type)(other.impl_))
  88. {
  89. }
  90. /// Converting move constructor.
  91. /**
  92. * This constructor is only valid if the @c OtherExecutor type is convertible
  93. * to @c Executor.
  94. */
  95. template <class OtherExecutor>
  96. strand(strand<OtherExecutor>&& other) ASIO_NOEXCEPT
  97. : executor_(ASIO_MOVE_CAST(OtherExecutor)(other)),
  98. impl_(ASIO_MOVE_CAST(implementation_type)(other.impl_))
  99. {
  100. }
  101. /// Move assignment operator.
  102. strand& operator=(strand&& other) ASIO_NOEXCEPT
  103. {
  104. executor_ = ASIO_MOVE_CAST(Executor)(other);
  105. impl_ = ASIO_MOVE_CAST(implementation_type)(other.impl_);
  106. return *this;
  107. }
  108. /// Converting move assignment operator.
  109. /**
  110. * This assignment operator is only valid if the @c OtherExecutor type is
  111. * convertible to @c Executor.
  112. */
  113. template <class OtherExecutor>
  114. strand& operator=(
  115. const strand<OtherExecutor>&& other) ASIO_NOEXCEPT
  116. {
  117. executor_ = ASIO_MOVE_CAST(OtherExecutor)(other);
  118. impl_ = ASIO_MOVE_CAST(implementation_type)(other.impl_);
  119. return *this;
  120. }
  121. #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  122. /// Destructor.
  123. ~strand()
  124. {
  125. }
  126. /// Obtain the underlying executor.
  127. inner_executor_type get_inner_executor() const ASIO_NOEXCEPT
  128. {
  129. return executor_;
  130. }
  131. /// Obtain the underlying execution context.
  132. execution_context& context() const ASIO_NOEXCEPT
  133. {
  134. return executor_.context();
  135. }
  136. /// Inform the strand that it has some outstanding work to do.
  137. /**
  138. * The strand delegates this call to its underlying executor.
  139. */
  140. void on_work_started() const ASIO_NOEXCEPT
  141. {
  142. executor_.on_work_started();
  143. }
  144. /// Inform the strand that some work is no longer outstanding.
  145. /**
  146. * The strand delegates this call to its underlying executor.
  147. */
  148. void on_work_finished() const ASIO_NOEXCEPT
  149. {
  150. executor_.on_work_finished();
  151. }
  152. /// Request the strand to invoke the given function object.
  153. /**
  154. * This function is used to ask the strand to execute the given function
  155. * object on its underlying executor. The function object will be executed
  156. * inside this function if the strand is not otherwise busy and if the
  157. * underlying executor's @c dispatch() function is also able to execute the
  158. * function before returning.
  159. *
  160. * @param f The function object to be called. The executor will make
  161. * a copy of the handler object as required. The function signature of the
  162. * function object must be: @code void function(); @endcode
  163. *
  164. * @param a An allocator that may be used by the executor to allocate the
  165. * internal storage needed for function invocation.
  166. */
  167. template <typename Function, typename Allocator>
  168. void dispatch(ASIO_MOVE_ARG(Function) f, const Allocator& a) const
  169. {
  170. detail::strand_executor_service::dispatch(impl_,
  171. executor_, ASIO_MOVE_CAST(Function)(f), a);
  172. }
  173. /// Request the strand to invoke the given function object.
  174. /**
  175. * This function is used to ask the executor to execute the given function
  176. * object. The function object will never be executed inside this function.
  177. * Instead, it will be scheduled by the underlying executor's defer function.
  178. *
  179. * @param f The function object to be called. The executor will make
  180. * a copy of the handler object as required. The function signature of the
  181. * function object must be: @code void function(); @endcode
  182. *
  183. * @param a An allocator that may be used by the executor to allocate the
  184. * internal storage needed for function invocation.
  185. */
  186. template <typename Function, typename Allocator>
  187. void post(ASIO_MOVE_ARG(Function) f, const Allocator& a) const
  188. {
  189. detail::strand_executor_service::post(impl_,
  190. executor_, ASIO_MOVE_CAST(Function)(f), a);
  191. }
  192. /// Request the strand to invoke the given function object.
  193. /**
  194. * This function is used to ask the executor to execute the given function
  195. * object. The function object will never be executed inside this function.
  196. * Instead, it will be scheduled by the underlying executor's defer function.
  197. *
  198. * @param f The function object to be called. The executor will make
  199. * a copy of the handler object as required. The function signature of the
  200. * function object must be: @code void function(); @endcode
  201. *
  202. * @param a An allocator that may be used by the executor to allocate the
  203. * internal storage needed for function invocation.
  204. */
  205. template <typename Function, typename Allocator>
  206. void defer(ASIO_MOVE_ARG(Function) f, const Allocator& a) const
  207. {
  208. detail::strand_executor_service::defer(impl_,
  209. executor_, ASIO_MOVE_CAST(Function)(f), a);
  210. }
  211. /// Determine whether the strand is running in the current thread.
  212. /**
  213. * @return @c true if the current thread is executing a function that was
  214. * submitted to the strand using post(), dispatch() or defer(). Otherwise
  215. * returns @c false.
  216. */
  217. bool running_in_this_thread() const ASIO_NOEXCEPT
  218. {
  219. return detail::strand_executor_service::running_in_this_thread(impl_);
  220. }
  221. /// Compare two strands for equality.
  222. /**
  223. * Two strands are equal if they refer to the same ordered, non-concurrent
  224. * state.
  225. */
  226. friend bool operator==(const strand& a, const strand& b) ASIO_NOEXCEPT
  227. {
  228. return a.impl_ == b.impl_;
  229. }
  230. /// Compare two strands for inequality.
  231. /**
  232. * Two strands are equal if they refer to the same ordered, non-concurrent
  233. * state.
  234. */
  235. friend bool operator!=(const strand& a, const strand& b) ASIO_NOEXCEPT
  236. {
  237. return a.impl_ != b.impl_;
  238. }
  239. private:
  240. Executor executor_;
  241. typedef detail::strand_executor_service::implementation_type
  242. implementation_type;
  243. implementation_type impl_;
  244. };
  245. /** @defgroup make_strand asio::make_strand
  246. *
  247. * @brief The asio::make_strand function creates a @ref strand object for
  248. * an executor or execution context.
  249. */
  250. /*@{*/
  251. /// Create a @ref strand object for an executor.
  252. template <typename Executor>
  253. inline strand<Executor> make_strand(const Executor& ex,
  254. typename enable_if<is_executor<Executor>::value>::type* = 0)
  255. {
  256. return strand<Executor>(ex);
  257. }
  258. /// Create a @ref strand object for an execution context.
  259. template <typename ExecutionContext>
  260. inline strand<typename ExecutionContext::executor_type>
  261. make_strand(ExecutionContext& ctx,
  262. typename enable_if<
  263. is_convertible<ExecutionContext&, execution_context&>::value>::type* = 0)
  264. {
  265. return strand<typename ExecutionContext::executor_type>(ctx.get_executor());
  266. }
  267. /*@}*/
  268. } // namespace asio
  269. #include "asio/detail/pop_options.hpp"
  270. // If both io_context.hpp and strand.hpp have been included, automatically
  271. // include the header file needed for the io_context::strand class.
  272. #if !defined(ASIO_NO_EXTENSIONS)
  273. # if defined(ASIO_IO_CONTEXT_HPP)
  274. # include "asio/io_context_strand.hpp"
  275. # endif // defined(ASIO_IO_CONTEXT_HPP)
  276. #endif // !defined(ASIO_NO_EXTENSIONS)
  277. #endif // ASIO_STRAND_HPP