2 // detail/winrt_async_manager.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP
12 #define BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
20 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
23 #include <boost/asio/detail/atomic_count.hpp>
24 #include <boost/asio/detail/winrt_async_op.hpp>
25 #include <boost/asio/error.hpp>
26 #include <boost/asio/execution_context.hpp>
28 #if defined(BOOST_ASIO_HAS_IOCP)
29 # include <boost/asio/detail/win_iocp_io_context.hpp>
30 #else // defined(BOOST_ASIO_HAS_IOCP)
31 # include <boost/asio/detail/scheduler.hpp>
32 #endif // defined(BOOST_ASIO_HAS_IOCP)
34 #include <boost/asio/detail/push_options.hpp>
40 class winrt_async_manager
41 : public execution_context_service_base<winrt_async_manager>
45 winrt_async_manager(execution_context& context)
46 : execution_context_service_base<winrt_async_manager>(context),
47 scheduler_(use_service<scheduler_impl>(context)),
53 ~winrt_async_manager()
57 // Destroy all user-defined handler objects owned by the service.
60 if (--outstanding_ops_ > 0)
62 // Block until last operation is complete.
63 std::future<void> f = promise_.get_future();
68 void sync(Windows::Foundation::IAsyncAction^ action,
69 boost::system::error_code& ec)
71 using namespace Windows::Foundation;
72 using Windows::Foundation::AsyncStatus;
74 auto promise = std::make_shared<std::promise<boost::system::error_code>>();
75 auto future = promise->get_future();
77 action->Completed = ref new AsyncActionCompletedHandler(
78 [promise](IAsyncAction^ action, AsyncStatus status)
82 case AsyncStatus::Canceled:
83 promise->set_value(boost::asio::error::operation_aborted);
85 case AsyncStatus::Error:
86 case AsyncStatus::Completed:
88 boost::system::error_code ec(
89 action->ErrorCode.Value,
90 boost::system::system_category());
91 promise->set_value(ec);
99 template <typename TResult>
100 TResult sync(Windows::Foundation::IAsyncOperation<TResult>^ operation,
101 boost::system::error_code& ec)
103 using namespace Windows::Foundation;
104 using Windows::Foundation::AsyncStatus;
106 auto promise = std::make_shared<std::promise<boost::system::error_code>>();
107 auto future = promise->get_future();
109 operation->Completed = ref new AsyncOperationCompletedHandler<TResult>(
110 [promise](IAsyncOperation<TResult>^ operation, AsyncStatus status)
114 case AsyncStatus::Canceled:
115 promise->set_value(boost::asio::error::operation_aborted);
117 case AsyncStatus::Error:
118 case AsyncStatus::Completed:
120 boost::system::error_code ec(
121 operation->ErrorCode.Value,
122 boost::system::system_category());
123 promise->set_value(ec);
129 return operation->GetResults();
132 template <typename TResult, typename TProgress>
134 Windows::Foundation::IAsyncOperationWithProgress<
135 TResult, TProgress>^ operation,
136 boost::system::error_code& ec)
138 using namespace Windows::Foundation;
139 using Windows::Foundation::AsyncStatus;
141 auto promise = std::make_shared<std::promise<boost::system::error_code>>();
142 auto future = promise->get_future();
145 = ref new AsyncOperationWithProgressCompletedHandler<TResult, TProgress>(
146 [promise](IAsyncOperationWithProgress<TResult, TProgress>^ operation,
151 case AsyncStatus::Canceled:
152 promise->set_value(boost::asio::error::operation_aborted);
154 case AsyncStatus::Started:
156 case AsyncStatus::Error:
157 case AsyncStatus::Completed:
159 boost::system::error_code ec(
160 operation->ErrorCode.Value,
161 boost::system::system_category());
162 promise->set_value(ec);
168 return operation->GetResults();
171 void async(Windows::Foundation::IAsyncAction^ action,
172 winrt_async_op<void>* handler)
174 using namespace Windows::Foundation;
175 using Windows::Foundation::AsyncStatus;
177 auto on_completed = ref new AsyncActionCompletedHandler(
178 [this, handler](IAsyncAction^ action, AsyncStatus status)
182 case AsyncStatus::Canceled:
183 handler->ec_ = boost::asio::error::operation_aborted;
185 case AsyncStatus::Started:
187 case AsyncStatus::Completed:
188 case AsyncStatus::Error:
190 handler->ec_ = boost::system::error_code(
191 action->ErrorCode.Value,
192 boost::system::system_category());
195 scheduler_.post_deferred_completion(handler);
196 if (--outstanding_ops_ == 0)
197 promise_.set_value();
200 scheduler_.work_started();
202 action->Completed = on_completed;
205 template <typename TResult>
206 void async(Windows::Foundation::IAsyncOperation<TResult>^ operation,
207 winrt_async_op<TResult>* handler)
209 using namespace Windows::Foundation;
210 using Windows::Foundation::AsyncStatus;
212 auto on_completed = ref new AsyncOperationCompletedHandler<TResult>(
213 [this, handler](IAsyncOperation<TResult>^ operation, AsyncStatus status)
217 case AsyncStatus::Canceled:
218 handler->ec_ = boost::asio::error::operation_aborted;
220 case AsyncStatus::Started:
222 case AsyncStatus::Completed:
223 handler->result_ = operation->GetResults();
225 case AsyncStatus::Error:
227 handler->ec_ = boost::system::error_code(
228 operation->ErrorCode.Value,
229 boost::system::system_category());
232 scheduler_.post_deferred_completion(handler);
233 if (--outstanding_ops_ == 0)
234 promise_.set_value();
237 scheduler_.work_started();
239 operation->Completed = on_completed;
242 template <typename TResult, typename TProgress>
244 Windows::Foundation::IAsyncOperationWithProgress<
245 TResult, TProgress>^ operation,
246 winrt_async_op<TResult>* handler)
248 using namespace Windows::Foundation;
249 using Windows::Foundation::AsyncStatus;
252 = ref new AsyncOperationWithProgressCompletedHandler<TResult, TProgress>(
253 [this, handler](IAsyncOperationWithProgress<
254 TResult, TProgress>^ operation, AsyncStatus status)
258 case AsyncStatus::Canceled:
259 handler->ec_ = boost::asio::error::operation_aborted;
261 case AsyncStatus::Started:
263 case AsyncStatus::Completed:
264 handler->result_ = operation->GetResults();
266 case AsyncStatus::Error:
268 handler->ec_ = boost::system::error_code(
269 operation->ErrorCode.Value,
270 boost::system::system_category());
273 scheduler_.post_deferred_completion(handler);
274 if (--outstanding_ops_ == 0)
275 promise_.set_value();
278 scheduler_.work_started();
280 operation->Completed = on_completed;
284 // The scheduler implementation used to post completed handlers.
285 #if defined(BOOST_ASIO_HAS_IOCP)
286 typedef class win_iocp_io_context scheduler_impl;
288 typedef class scheduler scheduler_impl;
290 scheduler_impl& scheduler_;
292 // Count of outstanding operations.
293 atomic_count outstanding_ops_;
295 // Used to keep wait for outstanding operations to complete.
296 std::promise<void> promise_;
299 } // namespace detail
303 #include <boost/asio/detail/pop_options.hpp>
305 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
307 #endif // BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP