| // |
| // detail/winrt_async_manager.hpp |
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| // |
| // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
| // |
| // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| // |
| |
| #ifndef BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP |
| #define BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
| # pragma once |
| #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
| |
| #include <boost/asio/detail/config.hpp> |
| |
| #if defined(BOOST_ASIO_WINDOWS_RUNTIME) |
| |
| #include <future> |
| #include <boost/asio/detail/atomic_count.hpp> |
| #include <boost/asio/detail/winrt_async_op.hpp> |
| #include <boost/asio/error.hpp> |
| #include <boost/asio/io_service.hpp> |
| |
| #include <boost/asio/detail/push_options.hpp> |
| |
| namespace boost { |
| namespace asio { |
| namespace detail { |
| |
| class winrt_async_manager |
| : public boost::asio::detail::service_base<winrt_async_manager> |
| { |
| public: |
| // Constructor. |
| winrt_async_manager(boost::asio::io_service& io_service) |
| : boost::asio::detail::service_base<winrt_async_manager>(io_service), |
| io_service_(use_service<io_service_impl>(io_service)), |
| outstanding_ops_(1) |
| { |
| } |
| |
| // Destructor. |
| ~winrt_async_manager() |
| { |
| } |
| |
| // Destroy all user-defined handler objects owned by the service. |
| void shutdown_service() |
| { |
| if (--outstanding_ops_ > 0) |
| { |
| // Block until last operation is complete. |
| std::future<void> f = promise_.get_future(); |
| f.wait(); |
| } |
| } |
| |
| void sync(Windows::Foundation::IAsyncAction^ action, |
| boost::system::error_code& ec) |
| { |
| using namespace Windows::Foundation; |
| using Windows::Foundation::AsyncStatus; |
| |
| auto promise = std::make_shared<std::promise<boost::system::error_code>>(); |
| auto future = promise->get_future(); |
| |
| action->Completed = ref new AsyncActionCompletedHandler( |
| [promise](IAsyncAction^ action, AsyncStatus status) |
| { |
| switch (status) |
| { |
| case AsyncStatus::Canceled: |
| promise->set_value(boost::asio::error::operation_aborted); |
| break; |
| case AsyncStatus::Error: |
| case AsyncStatus::Completed: |
| default: |
| boost::system::error_code ec( |
| action->ErrorCode.Value, |
| boost::system::system_category()); |
| promise->set_value(ec); |
| break; |
| } |
| }); |
| |
| ec = future.get(); |
| } |
| |
| template <typename TResult> |
| TResult sync(Windows::Foundation::IAsyncOperation<TResult>^ operation, |
| boost::system::error_code& ec) |
| { |
| using namespace Windows::Foundation; |
| using Windows::Foundation::AsyncStatus; |
| |
| auto promise = std::make_shared<std::promise<boost::system::error_code>>(); |
| auto future = promise->get_future(); |
| |
| operation->Completed = ref new AsyncOperationCompletedHandler<TResult>( |
| [promise](IAsyncOperation<TResult>^ operation, AsyncStatus status) |
| { |
| switch (status) |
| { |
| case AsyncStatus::Canceled: |
| promise->set_value(boost::asio::error::operation_aborted); |
| break; |
| case AsyncStatus::Error: |
| case AsyncStatus::Completed: |
| default: |
| boost::system::error_code ec( |
| operation->ErrorCode.Value, |
| boost::system::system_category()); |
| promise->set_value(ec); |
| break; |
| } |
| }); |
| |
| ec = future.get(); |
| return operation->GetResults(); |
| } |
| |
| template <typename TResult, typename TProgress> |
| TResult sync( |
| Windows::Foundation::IAsyncOperationWithProgress< |
| TResult, TProgress>^ operation, |
| boost::system::error_code& ec) |
| { |
| using namespace Windows::Foundation; |
| using Windows::Foundation::AsyncStatus; |
| |
| auto promise = std::make_shared<std::promise<boost::system::error_code>>(); |
| auto future = promise->get_future(); |
| |
| operation->Completed |
| = ref new AsyncOperationWithProgressCompletedHandler<TResult, TProgress>( |
| [promise](IAsyncOperationWithProgress<TResult, TProgress>^ operation, |
| AsyncStatus status) |
| { |
| switch (status) |
| { |
| case AsyncStatus::Canceled: |
| promise->set_value(boost::asio::error::operation_aborted); |
| break; |
| case AsyncStatus::Started: |
| break; |
| case AsyncStatus::Error: |
| case AsyncStatus::Completed: |
| default: |
| boost::system::error_code ec( |
| operation->ErrorCode.Value, |
| boost::system::system_category()); |
| promise->set_value(ec); |
| break; |
| } |
| }); |
| |
| ec = future.get(); |
| return operation->GetResults(); |
| } |
| |
| void async(Windows::Foundation::IAsyncAction^ action, |
| winrt_async_op<void>* handler) |
| { |
| using namespace Windows::Foundation; |
| using Windows::Foundation::AsyncStatus; |
| |
| auto on_completed = ref new AsyncActionCompletedHandler( |
| [this, handler](IAsyncAction^ action, AsyncStatus status) |
| { |
| switch (status) |
| { |
| case AsyncStatus::Canceled: |
| handler->ec_ = boost::asio::error::operation_aborted; |
| break; |
| case AsyncStatus::Started: |
| return; |
| case AsyncStatus::Completed: |
| case AsyncStatus::Error: |
| default: |
| handler->ec_ = boost::system::error_code( |
| action->ErrorCode.Value, |
| boost::system::system_category()); |
| break; |
| } |
| io_service_.post_deferred_completion(handler); |
| if (--outstanding_ops_ == 0) |
| promise_.set_value(); |
| }); |
| |
| io_service_.work_started(); |
| ++outstanding_ops_; |
| action->Completed = on_completed; |
| } |
| |
| template <typename TResult> |
| void async(Windows::Foundation::IAsyncOperation<TResult>^ operation, |
| winrt_async_op<TResult>* handler) |
| { |
| using namespace Windows::Foundation; |
| using Windows::Foundation::AsyncStatus; |
| |
| auto on_completed = ref new AsyncOperationCompletedHandler<TResult>( |
| [this, handler](IAsyncOperation<TResult>^ operation, AsyncStatus status) |
| { |
| switch (status) |
| { |
| case AsyncStatus::Canceled: |
| handler->ec_ = boost::asio::error::operation_aborted; |
| break; |
| case AsyncStatus::Started: |
| return; |
| case AsyncStatus::Completed: |
| handler->result_ = operation->GetResults(); |
| // Fall through. |
| case AsyncStatus::Error: |
| default: |
| handler->ec_ = boost::system::error_code( |
| operation->ErrorCode.Value, |
| boost::system::system_category()); |
| break; |
| } |
| io_service_.post_deferred_completion(handler); |
| if (--outstanding_ops_ == 0) |
| promise_.set_value(); |
| }); |
| |
| io_service_.work_started(); |
| ++outstanding_ops_; |
| operation->Completed = on_completed; |
| } |
| |
| template <typename TResult, typename TProgress> |
| void async( |
| Windows::Foundation::IAsyncOperationWithProgress< |
| TResult, TProgress>^ operation, |
| winrt_async_op<TResult>* handler) |
| { |
| using namespace Windows::Foundation; |
| using Windows::Foundation::AsyncStatus; |
| |
| auto on_completed |
| = ref new AsyncOperationWithProgressCompletedHandler<TResult, TProgress>( |
| [this, handler](IAsyncOperationWithProgress< |
| TResult, TProgress>^ operation, AsyncStatus status) |
| { |
| switch (status) |
| { |
| case AsyncStatus::Canceled: |
| handler->ec_ = boost::asio::error::operation_aborted; |
| break; |
| case AsyncStatus::Started: |
| return; |
| case AsyncStatus::Completed: |
| handler->result_ = operation->GetResults(); |
| // Fall through. |
| case AsyncStatus::Error: |
| default: |
| handler->ec_ = boost::system::error_code( |
| operation->ErrorCode.Value, |
| boost::system::system_category()); |
| break; |
| } |
| io_service_.post_deferred_completion(handler); |
| if (--outstanding_ops_ == 0) |
| promise_.set_value(); |
| }); |
| |
| io_service_.work_started(); |
| ++outstanding_ops_; |
| operation->Completed = on_completed; |
| } |
| |
| private: |
| // The io_service implementation used to post completed handlers. |
| io_service_impl& io_service_; |
| |
| // Count of outstanding operations. |
| atomic_count outstanding_ops_; |
| |
| // Used to keep wait for outstanding operations to complete. |
| std::promise<void> promise_; |
| }; |
| |
| } // namespace detail |
| } // namespace asio |
| } // namespace boost |
| |
| #include <boost/asio/detail/pop_options.hpp> |
| |
| #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) |
| |
| #endif // BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP |