Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:47

0001 //
0002 // detail/winrt_async_manager.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP
0012 #define BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 
0020 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
0021 
0022 #include <future>
0023 #include <boost/asio/detail/atomic_count.hpp>
0024 #include <boost/asio/detail/winrt_async_op.hpp>
0025 #include <boost/asio/error.hpp>
0026 #include <boost/asio/execution_context.hpp>
0027 
0028 #if defined(BOOST_ASIO_HAS_IOCP)
0029 # include <boost/asio/detail/win_iocp_io_context.hpp>
0030 #else // defined(BOOST_ASIO_HAS_IOCP)
0031 # include <boost/asio/detail/scheduler.hpp>
0032 #endif // defined(BOOST_ASIO_HAS_IOCP)
0033 
0034 #include <boost/asio/detail/push_options.hpp>
0035 
0036 namespace boost {
0037 namespace asio {
0038 namespace detail {
0039 
0040 class winrt_async_manager
0041   : public execution_context_service_base<winrt_async_manager>
0042 {
0043 public:
0044   // Constructor.
0045   winrt_async_manager(execution_context& context)
0046     : execution_context_service_base<winrt_async_manager>(context),
0047       scheduler_(use_service<scheduler_impl>(context)),
0048       outstanding_ops_(1)
0049   {
0050   }
0051 
0052   // Destructor.
0053   ~winrt_async_manager()
0054   {
0055   }
0056 
0057   // Destroy all user-defined handler objects owned by the service.
0058   void shutdown()
0059   {
0060     if (--outstanding_ops_ > 0)
0061     {
0062       // Block until last operation is complete.
0063       std::future<void> f = promise_.get_future();
0064       f.wait();
0065     }
0066   }
0067 
0068   void sync(Windows::Foundation::IAsyncAction^ action,
0069       boost::system::error_code& ec)
0070   {
0071     using namespace Windows::Foundation;
0072     using Windows::Foundation::AsyncStatus;
0073 
0074     auto promise = std::make_shared<std::promise<boost::system::error_code>>();
0075     auto future = promise->get_future();
0076 
0077     action->Completed = ref new AsyncActionCompletedHandler(
0078       [promise](IAsyncAction^ action, AsyncStatus status)
0079       {
0080         switch (status)
0081         {
0082         case AsyncStatus::Canceled:
0083           promise->set_value(boost::asio::error::operation_aborted);
0084           break;
0085         case AsyncStatus::Error:
0086         case AsyncStatus::Completed:
0087         default:
0088           boost::system::error_code ec(
0089               action->ErrorCode.Value,
0090               boost::system::system_category());
0091           promise->set_value(ec);
0092           break;
0093         }
0094       });
0095 
0096     ec = future.get();
0097   }
0098 
0099   template <typename TResult>
0100   TResult sync(Windows::Foundation::IAsyncOperation<TResult>^ operation,
0101       boost::system::error_code& ec)
0102   {
0103     using namespace Windows::Foundation;
0104     using Windows::Foundation::AsyncStatus;
0105 
0106     auto promise = std::make_shared<std::promise<boost::system::error_code>>();
0107     auto future = promise->get_future();
0108 
0109     operation->Completed = ref new AsyncOperationCompletedHandler<TResult>(
0110       [promise](IAsyncOperation<TResult>^ operation, AsyncStatus status)
0111       {
0112         switch (status)
0113         {
0114         case AsyncStatus::Canceled:
0115           promise->set_value(boost::asio::error::operation_aborted);
0116           break;
0117         case AsyncStatus::Error:
0118         case AsyncStatus::Completed:
0119         default:
0120           boost::system::error_code ec(
0121               operation->ErrorCode.Value,
0122               boost::system::system_category());
0123           promise->set_value(ec);
0124           break;
0125         }
0126       });
0127 
0128     ec = future.get();
0129     return operation->GetResults();
0130   }
0131 
0132   template <typename TResult, typename TProgress>
0133   TResult sync(
0134       Windows::Foundation::IAsyncOperationWithProgress<
0135         TResult, TProgress>^ operation,
0136       boost::system::error_code& ec)
0137   {
0138     using namespace Windows::Foundation;
0139     using Windows::Foundation::AsyncStatus;
0140 
0141     auto promise = std::make_shared<std::promise<boost::system::error_code>>();
0142     auto future = promise->get_future();
0143 
0144     operation->Completed
0145       = ref new AsyncOperationWithProgressCompletedHandler<TResult, TProgress>(
0146         [promise](IAsyncOperationWithProgress<TResult, TProgress>^ operation,
0147           AsyncStatus status)
0148         {
0149           switch (status)
0150           {
0151           case AsyncStatus::Canceled:
0152             promise->set_value(boost::asio::error::operation_aborted);
0153             break;
0154           case AsyncStatus::Started:
0155             break;
0156           case AsyncStatus::Error:
0157           case AsyncStatus::Completed:
0158           default:
0159             boost::system::error_code ec(
0160                 operation->ErrorCode.Value,
0161                 boost::system::system_category());
0162             promise->set_value(ec);
0163             break;
0164           }
0165         });
0166 
0167     ec = future.get();
0168     return operation->GetResults();
0169   }
0170 
0171   void async(Windows::Foundation::IAsyncAction^ action,
0172       winrt_async_op<void>* handler)
0173   {
0174     using namespace Windows::Foundation;
0175     using Windows::Foundation::AsyncStatus;
0176 
0177     auto on_completed = ref new AsyncActionCompletedHandler(
0178       [this, handler](IAsyncAction^ action, AsyncStatus status)
0179       {
0180         switch (status)
0181         {
0182         case AsyncStatus::Canceled:
0183           handler->ec_ = boost::asio::error::operation_aborted;
0184           break;
0185         case AsyncStatus::Started:
0186           return;
0187         case AsyncStatus::Completed:
0188         case AsyncStatus::Error:
0189         default:
0190           handler->ec_ = boost::system::error_code(
0191               action->ErrorCode.Value,
0192               boost::system::system_category());
0193           break;
0194         }
0195         scheduler_.post_deferred_completion(handler);
0196         if (--outstanding_ops_ == 0)
0197           promise_.set_value();
0198       });
0199 
0200     scheduler_.work_started();
0201     ++outstanding_ops_;
0202     action->Completed = on_completed;
0203   }
0204 
0205   template <typename TResult>
0206   void async(Windows::Foundation::IAsyncOperation<TResult>^ operation,
0207       winrt_async_op<TResult>* handler)
0208   {
0209     using namespace Windows::Foundation;
0210     using Windows::Foundation::AsyncStatus;
0211 
0212     auto on_completed = ref new AsyncOperationCompletedHandler<TResult>(
0213       [this, handler](IAsyncOperation<TResult>^ operation, AsyncStatus status)
0214       {
0215         switch (status)
0216         {
0217         case AsyncStatus::Canceled:
0218           handler->ec_ = boost::asio::error::operation_aborted;
0219           break;
0220         case AsyncStatus::Started:
0221           return;
0222         case AsyncStatus::Completed:
0223           handler->result_ = operation->GetResults();
0224           // Fall through.
0225         case AsyncStatus::Error:
0226         default:
0227           handler->ec_ = boost::system::error_code(
0228               operation->ErrorCode.Value,
0229               boost::system::system_category());
0230           break;
0231         }
0232         scheduler_.post_deferred_completion(handler);
0233         if (--outstanding_ops_ == 0)
0234           promise_.set_value();
0235       });
0236 
0237     scheduler_.work_started();
0238     ++outstanding_ops_;
0239     operation->Completed = on_completed;
0240   }
0241 
0242   template <typename TResult, typename TProgress>
0243   void async(
0244       Windows::Foundation::IAsyncOperationWithProgress<
0245         TResult, TProgress>^ operation,
0246       winrt_async_op<TResult>* handler)
0247   {
0248     using namespace Windows::Foundation;
0249     using Windows::Foundation::AsyncStatus;
0250 
0251     auto on_completed
0252       = ref new AsyncOperationWithProgressCompletedHandler<TResult, TProgress>(
0253         [this, handler](IAsyncOperationWithProgress<
0254           TResult, TProgress>^ operation, AsyncStatus status)
0255         {
0256           switch (status)
0257           {
0258           case AsyncStatus::Canceled:
0259             handler->ec_ = boost::asio::error::operation_aborted;
0260             break;
0261           case AsyncStatus::Started:
0262             return;
0263           case AsyncStatus::Completed:
0264             handler->result_ = operation->GetResults();
0265             // Fall through.
0266           case AsyncStatus::Error:
0267           default:
0268             handler->ec_ = boost::system::error_code(
0269                 operation->ErrorCode.Value,
0270                 boost::system::system_category());
0271             break;
0272           }
0273           scheduler_.post_deferred_completion(handler);
0274           if (--outstanding_ops_ == 0)
0275             promise_.set_value();
0276         });
0277 
0278     scheduler_.work_started();
0279     ++outstanding_ops_;
0280     operation->Completed = on_completed;
0281   }
0282 
0283 private:
0284   // The scheduler implementation used to post completed handlers.
0285 #if defined(BOOST_ASIO_HAS_IOCP)
0286   typedef class win_iocp_io_context scheduler_impl;
0287 #else
0288   typedef class scheduler scheduler_impl;
0289 #endif
0290   scheduler_impl& scheduler_;
0291 
0292   // Count of outstanding operations.
0293   atomic_count outstanding_ops_;
0294 
0295   // Used to keep wait for outstanding operations to complete.
0296   std::promise<void> promise_;
0297 };
0298 
0299 } // namespace detail
0300 } // namespace asio
0301 } // namespace boost
0302 
0303 #include <boost/asio/detail/pop_options.hpp>
0304 
0305 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
0306 
0307 #endif // BOOST_ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP