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