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