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.

291 lines
8.5KB

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