winrt_async_manager.hpp 8.5 KB

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