// // detail/winrt_async_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2014 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