123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- //
- // detail/winrt_async_manager.hpp
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- // Copyright (c) 2003-2021 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/execution_context.hpp>
- #if defined(BOOST_ASIO_HAS_IOCP)
- # include <boost/asio/detail/win_iocp_io_context.hpp>
- #else // defined(BOOST_ASIO_HAS_IOCP)
- # include <boost/asio/detail/scheduler.hpp>
- #endif // defined(BOOST_ASIO_HAS_IOCP)
- #include <boost/asio/detail/push_options.hpp>
- namespace boost {
- namespace asio {
- namespace detail {
- class winrt_async_manager
- : public execution_context_service_base<winrt_async_manager>
- {
- public:
- // Constructor.
- winrt_async_manager(execution_context& context)
- : execution_context_service_base<winrt_async_manager>(context),
- scheduler_(use_service<scheduler_impl>(context)),
- outstanding_ops_(1)
- {
- }
- // Destructor.
- ~winrt_async_manager()
- {
- }
- // Destroy all user-defined handler objects owned by the service.
- void shutdown()
- {
- 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;
- }
- scheduler_.post_deferred_completion(handler);
- if (--outstanding_ops_ == 0)
- promise_.set_value();
- });
- scheduler_.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;
- }
- scheduler_.post_deferred_completion(handler);
- if (--outstanding_ops_ == 0)
- promise_.set_value();
- });
- scheduler_.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;
- }
- scheduler_.post_deferred_completion(handler);
- if (--outstanding_ops_ == 0)
- promise_.set_value();
- });
- scheduler_.work_started();
- ++outstanding_ops_;
- operation->Completed = on_completed;
- }
- private:
- // The scheduler implementation used to post completed handlers.
- #if defined(BOOST_ASIO_HAS_IOCP)
- typedef class win_iocp_io_context scheduler_impl;
- #else
- typedef class scheduler scheduler_impl;
- #endif
- scheduler_impl& scheduler_;
- // 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
|