File indexing completed on 2025-01-18 09:28:47
0001
0002
0003
0004
0005
0006
0007
0008
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
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
0031 # include <boost/asio/detail/scheduler.hpp>
0032 #endif
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
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
0053 ~winrt_async_manager()
0054 {
0055 }
0056
0057
0058 void shutdown()
0059 {
0060 if (--outstanding_ops_ > 0)
0061 {
0062
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
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
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
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
0293 atomic_count outstanding_ops_;
0294
0295
0296 std::promise<void> promise_;
0297 };
0298
0299 }
0300 }
0301 }
0302
0303 #include <boost/asio/detail/pop_options.hpp>
0304
0305 #endif
0306
0307 #endif