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.

306 lines
8.5KB

  1. //
  2. // detail/winrt_async_manager.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_DETAIL_WINRT_ASYNC_MANAGER_HPP
  11. #define ASIO_DETAIL_WINRT_ASYNC_MANAGER_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. #if defined(ASIO_WINDOWS_RUNTIME)
  17. #include <future>
  18. #include "asio/detail/atomic_count.hpp"
  19. #include "asio/detail/winrt_async_op.hpp"
  20. #include "asio/error.hpp"
  21. #include "asio/execution_context.hpp"
  22. #if defined(ASIO_HAS_IOCP)
  23. # include "asio/detail/win_iocp_io_context.hpp"
  24. #else // defined(ASIO_HAS_IOCP)
  25. # include "asio/detail/scheduler.hpp"
  26. #endif // defined(ASIO_HAS_IOCP)
  27. #include "asio/detail/push_options.hpp"
  28. namespace asio {
  29. namespace detail {
  30. class winrt_async_manager
  31. : public execution_context_service_base<winrt_async_manager>
  32. {
  33. public:
  34. // Constructor.
  35. winrt_async_manager(execution_context& context)
  36. : execution_context_service_base<winrt_async_manager>(context),
  37. scheduler_(use_service<scheduler_impl>(context)),
  38. outstanding_ops_(1)
  39. {
  40. }
  41. // Destructor.
  42. ~winrt_async_manager()
  43. {
  44. }
  45. // Destroy all user-defined handler objects owned by the service.
  46. void shutdown()
  47. {
  48. if (--outstanding_ops_ > 0)
  49. {
  50. // Block until last operation is complete.
  51. std::future<void> f = promise_.get_future();
  52. f.wait();
  53. }
  54. }
  55. void sync(Windows::Foundation::IAsyncAction^ action,
  56. asio::error_code& ec)
  57. {
  58. using namespace Windows::Foundation;
  59. using Windows::Foundation::AsyncStatus;
  60. auto promise = std::make_shared<std::promise<asio::error_code>>();
  61. auto future = promise->get_future();
  62. action->Completed = ref new AsyncActionCompletedHandler(
  63. [promise](IAsyncAction^ action, AsyncStatus status)
  64. {
  65. switch (status)
  66. {
  67. case AsyncStatus::Canceled:
  68. promise->set_value(asio::error::operation_aborted);
  69. break;
  70. case AsyncStatus::Error:
  71. case AsyncStatus::Completed:
  72. default:
  73. asio::error_code ec(
  74. action->ErrorCode.Value,
  75. asio::system_category());
  76. promise->set_value(ec);
  77. break;
  78. }
  79. });
  80. ec = future.get();
  81. }
  82. template <typename TResult>
  83. TResult sync(Windows::Foundation::IAsyncOperation<TResult>^ operation,
  84. asio::error_code& ec)
  85. {
  86. using namespace Windows::Foundation;
  87. using Windows::Foundation::AsyncStatus;
  88. auto promise = std::make_shared<std::promise<asio::error_code>>();
  89. auto future = promise->get_future();
  90. operation->Completed = ref new AsyncOperationCompletedHandler<TResult>(
  91. [promise](IAsyncOperation<TResult>^ operation, AsyncStatus status)
  92. {
  93. switch (status)
  94. {
  95. case AsyncStatus::Canceled:
  96. promise->set_value(asio::error::operation_aborted);
  97. break;
  98. case AsyncStatus::Error:
  99. case AsyncStatus::Completed:
  100. default:
  101. asio::error_code ec(
  102. operation->ErrorCode.Value,
  103. asio::system_category());
  104. promise->set_value(ec);
  105. break;
  106. }
  107. });
  108. ec = future.get();
  109. return operation->GetResults();
  110. }
  111. template <typename TResult, typename TProgress>
  112. TResult sync(
  113. Windows::Foundation::IAsyncOperationWithProgress<
  114. TResult, TProgress>^ operation,
  115. asio::error_code& ec)
  116. {
  117. using namespace Windows::Foundation;
  118. using Windows::Foundation::AsyncStatus;
  119. auto promise = std::make_shared<std::promise<asio::error_code>>();
  120. auto future = promise->get_future();
  121. operation->Completed
  122. = ref new AsyncOperationWithProgressCompletedHandler<TResult, TProgress>(
  123. [promise](IAsyncOperationWithProgress<TResult, TProgress>^ operation,
  124. AsyncStatus status)
  125. {
  126. switch (status)
  127. {
  128. case AsyncStatus::Canceled:
  129. promise->set_value(asio::error::operation_aborted);
  130. break;
  131. case AsyncStatus::Started:
  132. break;
  133. case AsyncStatus::Error:
  134. case AsyncStatus::Completed:
  135. default:
  136. asio::error_code ec(
  137. operation->ErrorCode.Value,
  138. asio::system_category());
  139. promise->set_value(ec);
  140. break;
  141. }
  142. });
  143. ec = future.get();
  144. return operation->GetResults();
  145. }
  146. void async(Windows::Foundation::IAsyncAction^ action,
  147. winrt_async_op<void>* handler)
  148. {
  149. using namespace Windows::Foundation;
  150. using Windows::Foundation::AsyncStatus;
  151. auto on_completed = ref new AsyncActionCompletedHandler(
  152. [this, handler](IAsyncAction^ action, AsyncStatus status)
  153. {
  154. switch (status)
  155. {
  156. case AsyncStatus::Canceled:
  157. handler->ec_ = asio::error::operation_aborted;
  158. break;
  159. case AsyncStatus::Started:
  160. return;
  161. case AsyncStatus::Completed:
  162. case AsyncStatus::Error:
  163. default:
  164. handler->ec_ = asio::error_code(
  165. action->ErrorCode.Value,
  166. asio::system_category());
  167. break;
  168. }
  169. scheduler_.post_deferred_completion(handler);
  170. if (--outstanding_ops_ == 0)
  171. promise_.set_value();
  172. });
  173. scheduler_.work_started();
  174. ++outstanding_ops_;
  175. action->Completed = on_completed;
  176. }
  177. template <typename TResult>
  178. void async(Windows::Foundation::IAsyncOperation<TResult>^ operation,
  179. winrt_async_op<TResult>* handler)
  180. {
  181. using namespace Windows::Foundation;
  182. using Windows::Foundation::AsyncStatus;
  183. auto on_completed = ref new AsyncOperationCompletedHandler<TResult>(
  184. [this, handler](IAsyncOperation<TResult>^ operation, AsyncStatus status)
  185. {
  186. switch (status)
  187. {
  188. case AsyncStatus::Canceled:
  189. handler->ec_ = asio::error::operation_aborted;
  190. break;
  191. case AsyncStatus::Started:
  192. return;
  193. case AsyncStatus::Completed:
  194. handler->result_ = operation->GetResults();
  195. // Fall through.
  196. case AsyncStatus::Error:
  197. default:
  198. handler->ec_ = asio::error_code(
  199. operation->ErrorCode.Value,
  200. asio::system_category());
  201. break;
  202. }
  203. scheduler_.post_deferred_completion(handler);
  204. if (--outstanding_ops_ == 0)
  205. promise_.set_value();
  206. });
  207. scheduler_.work_started();
  208. ++outstanding_ops_;
  209. operation->Completed = on_completed;
  210. }
  211. template <typename TResult, typename TProgress>
  212. void async(
  213. Windows::Foundation::IAsyncOperationWithProgress<
  214. TResult, TProgress>^ operation,
  215. winrt_async_op<TResult>* handler)
  216. {
  217. using namespace Windows::Foundation;
  218. using Windows::Foundation::AsyncStatus;
  219. auto on_completed
  220. = ref new AsyncOperationWithProgressCompletedHandler<TResult, TProgress>(
  221. [this, handler](IAsyncOperationWithProgress<
  222. TResult, TProgress>^ operation, AsyncStatus status)
  223. {
  224. switch (status)
  225. {
  226. case AsyncStatus::Canceled:
  227. handler->ec_ = asio::error::operation_aborted;
  228. break;
  229. case AsyncStatus::Started:
  230. return;
  231. case AsyncStatus::Completed:
  232. handler->result_ = operation->GetResults();
  233. // Fall through.
  234. case AsyncStatus::Error:
  235. default:
  236. handler->ec_ = asio::error_code(
  237. operation->ErrorCode.Value,
  238. asio::system_category());
  239. break;
  240. }
  241. scheduler_.post_deferred_completion(handler);
  242. if (--outstanding_ops_ == 0)
  243. promise_.set_value();
  244. });
  245. scheduler_.work_started();
  246. ++outstanding_ops_;
  247. operation->Completed = on_completed;
  248. }
  249. private:
  250. // The scheduler implementation used to post completed handlers.
  251. #if defined(ASIO_HAS_IOCP)
  252. typedef class win_iocp_io_context scheduler_impl;
  253. #else
  254. typedef class scheduler scheduler_impl;
  255. #endif
  256. scheduler_impl& scheduler_;
  257. // Count of outstanding operations.
  258. atomic_count outstanding_ops_;
  259. // Used to keep wait for outstanding operations to complete.
  260. std::promise<void> promise_;
  261. };
  262. } // namespace detail
  263. } // namespace asio
  264. #include "asio/detail/pop_options.hpp"
  265. #endif // defined(ASIO_WINDOWS_RUNTIME)
  266. #endif // ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP