Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / asio / detail / winrt_async_manager.hpp
1 //
2 // detail/winrt_async_manager.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2014 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