File indexing completed on 2025-01-18 09:28:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_IMPL_USE_FUTURE_HPP
0012 #define BOOST_ASIO_IMPL_USE_FUTURE_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019 #include <tuple>
0020 #include <boost/asio/async_result.hpp>
0021 #include <boost/asio/detail/memory.hpp>
0022 #include <boost/asio/dispatch.hpp>
0023 #include <boost/system/error_code.hpp>
0024 #include <boost/asio/execution.hpp>
0025 #include <boost/asio/packaged_task.hpp>
0026 #include <boost/system/system_error.hpp>
0027 #include <boost/asio/system_executor.hpp>
0028
0029 #include <boost/asio/detail/push_options.hpp>
0030
0031 namespace boost {
0032 namespace asio {
0033 namespace detail {
0034
0035 template <typename T, typename F, typename... Args>
0036 inline void promise_invoke_and_set(std::promise<T>& p,
0037 F& f, Args&&... args)
0038 {
0039 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0040 try
0041 #endif
0042 {
0043 p.set_value(f(static_cast<Args&&>(args)...));
0044 }
0045 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0046 catch (...)
0047 {
0048 p.set_exception(std::current_exception());
0049 }
0050 #endif
0051 }
0052
0053 template <typename F, typename... Args>
0054 inline void promise_invoke_and_set(std::promise<void>& p,
0055 F& f, Args&&... args)
0056 {
0057 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0058 try
0059 #endif
0060 {
0061 f(static_cast<Args&&>(args)...);
0062 p.set_value();
0063 }
0064 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0065 catch (...)
0066 {
0067 p.set_exception(std::current_exception());
0068 }
0069 #endif
0070 }
0071
0072
0073
0074 template <typename T, typename F>
0075 class promise_invoker
0076 {
0077 public:
0078 promise_invoker(const shared_ptr<std::promise<T>>& p,
0079 F&& f)
0080 : p_(p), f_(static_cast<F&&>(f))
0081 {
0082 }
0083
0084 void operator()()
0085 {
0086 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0087 try
0088 #endif
0089 {
0090 f_();
0091 }
0092 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0093 catch (...)
0094 {
0095 p_->set_exception(std::current_exception());
0096 }
0097 #endif
0098 }
0099
0100 private:
0101 shared_ptr<std::promise<T>> p_;
0102 decay_t<F> f_;
0103 };
0104
0105
0106
0107 template <typename T, typename Blocking = execution::blocking_t::possibly_t>
0108 class promise_executor
0109 {
0110 public:
0111 explicit promise_executor(const shared_ptr<std::promise<T>>& p)
0112 : p_(p)
0113 {
0114 }
0115
0116 execution_context& query(execution::context_t) const noexcept
0117 {
0118 return boost::asio::query(system_executor(), execution::context);
0119 }
0120
0121 static constexpr Blocking query(execution::blocking_t)
0122 {
0123 return Blocking();
0124 }
0125
0126 promise_executor<T, execution::blocking_t::possibly_t>
0127 require(execution::blocking_t::possibly_t) const
0128 {
0129 return promise_executor<T, execution::blocking_t::possibly_t>(p_);
0130 }
0131
0132 promise_executor<T, execution::blocking_t::never_t>
0133 require(execution::blocking_t::never_t) const
0134 {
0135 return promise_executor<T, execution::blocking_t::never_t>(p_);
0136 }
0137
0138 template <typename F>
0139 void execute(F&& f) const
0140 {
0141 boost::asio::require(system_executor(), Blocking()).execute(
0142 promise_invoker<T, F>(p_, static_cast<F&&>(f)));
0143 }
0144
0145 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0146 execution_context& context() const noexcept
0147 {
0148 return system_executor().context();
0149 }
0150
0151 void on_work_started() const noexcept {}
0152 void on_work_finished() const noexcept {}
0153
0154 template <typename F, typename A>
0155 void dispatch(F&& f, const A&) const
0156 {
0157 promise_invoker<T, F>(p_, static_cast<F&&>(f))();
0158 }
0159
0160 template <typename F, typename A>
0161 void post(F&& f, const A& a) const
0162 {
0163 system_executor().post(
0164 promise_invoker<T, F>(p_, static_cast<F&&>(f)), a);
0165 }
0166
0167 template <typename F, typename A>
0168 void defer(F&& f, const A& a) const
0169 {
0170 system_executor().defer(
0171 promise_invoker<T, F>(p_, static_cast<F&&>(f)), a);
0172 }
0173 #endif
0174
0175 friend bool operator==(const promise_executor& a,
0176 const promise_executor& b) noexcept
0177 {
0178 return a.p_ == b.p_;
0179 }
0180
0181 friend bool operator!=(const promise_executor& a,
0182 const promise_executor& b) noexcept
0183 {
0184 return a.p_ != b.p_;
0185 }
0186
0187 private:
0188 shared_ptr<std::promise<T>> p_;
0189 };
0190
0191
0192 template <typename T>
0193 class promise_creator
0194 {
0195 public:
0196 typedef promise_executor<T> executor_type;
0197
0198 executor_type get_executor() const noexcept
0199 {
0200 return executor_type(p_);
0201 }
0202
0203 typedef std::future<T> future_type;
0204
0205 future_type get_future()
0206 {
0207 return p_->get_future();
0208 }
0209
0210 protected:
0211 template <typename Allocator>
0212 void create_promise(const Allocator& a)
0213 {
0214 BOOST_ASIO_REBIND_ALLOC(Allocator, char) b(a);
0215 p_ = std::allocate_shared<std::promise<T>>(b, std::allocator_arg, b);
0216 }
0217
0218 shared_ptr<std::promise<T>> p_;
0219 };
0220
0221
0222 class promise_handler_0
0223 : public promise_creator<void>
0224 {
0225 public:
0226 void operator()()
0227 {
0228 this->p_->set_value();
0229 }
0230 };
0231
0232
0233 class promise_handler_ec_0
0234 : public promise_creator<void>
0235 {
0236 public:
0237 void operator()(const boost::system::error_code& ec)
0238 {
0239 if (ec)
0240 {
0241 this->p_->set_exception(
0242 std::make_exception_ptr(
0243 boost::system::system_error(ec)));
0244 }
0245 else
0246 {
0247 this->p_->set_value();
0248 }
0249 }
0250 };
0251
0252
0253 class promise_handler_ex_0
0254 : public promise_creator<void>
0255 {
0256 public:
0257 void operator()(const std::exception_ptr& ex)
0258 {
0259 if (ex)
0260 {
0261 this->p_->set_exception(ex);
0262 }
0263 else
0264 {
0265 this->p_->set_value();
0266 }
0267 }
0268 };
0269
0270
0271 template <typename T>
0272 class promise_handler_1
0273 : public promise_creator<T>
0274 {
0275 public:
0276 template <typename Arg>
0277 void operator()(Arg&& arg)
0278 {
0279 this->p_->set_value(static_cast<Arg&&>(arg));
0280 }
0281 };
0282
0283
0284 template <typename T>
0285 class promise_handler_ec_1
0286 : public promise_creator<T>
0287 {
0288 public:
0289 template <typename Arg>
0290 void operator()(const boost::system::error_code& ec,
0291 Arg&& arg)
0292 {
0293 if (ec)
0294 {
0295 this->p_->set_exception(
0296 std::make_exception_ptr(
0297 boost::system::system_error(ec)));
0298 }
0299 else
0300 this->p_->set_value(static_cast<Arg&&>(arg));
0301 }
0302 };
0303
0304
0305 template <typename T>
0306 class promise_handler_ex_1
0307 : public promise_creator<T>
0308 {
0309 public:
0310 template <typename Arg>
0311 void operator()(const std::exception_ptr& ex,
0312 Arg&& arg)
0313 {
0314 if (ex)
0315 this->p_->set_exception(ex);
0316 else
0317 this->p_->set_value(static_cast<Arg&&>(arg));
0318 }
0319 };
0320
0321
0322 template <typename T>
0323 class promise_handler_n
0324 : public promise_creator<T>
0325 {
0326 public:
0327 template <typename... Args>
0328 void operator()(Args&&... args)
0329 {
0330 this->p_->set_value(
0331 std::forward_as_tuple(
0332 static_cast<Args&&>(args)...));
0333 }
0334 };
0335
0336
0337 template <typename T>
0338 class promise_handler_ec_n
0339 : public promise_creator<T>
0340 {
0341 public:
0342 template <typename... Args>
0343 void operator()(const boost::system::error_code& ec, Args&&... args)
0344 {
0345 if (ec)
0346 {
0347 this->p_->set_exception(
0348 std::make_exception_ptr(
0349 boost::system::system_error(ec)));
0350 }
0351 else
0352 {
0353 this->p_->set_value(
0354 std::forward_as_tuple(
0355 static_cast<Args&&>(args)...));
0356 }
0357 }
0358 };
0359
0360
0361 template <typename T>
0362 class promise_handler_ex_n
0363 : public promise_creator<T>
0364 {
0365 public:
0366 template <typename... Args>
0367 void operator()(const std::exception_ptr& ex,
0368 Args&&... args)
0369 {
0370 if (ex)
0371 this->p_->set_exception(ex);
0372 else
0373 {
0374 this->p_->set_value(
0375 std::forward_as_tuple(
0376 static_cast<Args&&>(args)...));
0377 }
0378 }
0379 };
0380
0381
0382
0383 template <typename> class promise_handler_selector;
0384
0385 template <>
0386 class promise_handler_selector<void()>
0387 : public promise_handler_0 {};
0388
0389 template <>
0390 class promise_handler_selector<void(boost::system::error_code)>
0391 : public promise_handler_ec_0 {};
0392
0393 template <>
0394 class promise_handler_selector<void(std::exception_ptr)>
0395 : public promise_handler_ex_0 {};
0396
0397 template <typename Arg>
0398 class promise_handler_selector<void(Arg)>
0399 : public promise_handler_1<Arg> {};
0400
0401 template <typename Arg>
0402 class promise_handler_selector<void(boost::system::error_code, Arg)>
0403 : public promise_handler_ec_1<Arg> {};
0404
0405 template <typename Arg>
0406 class promise_handler_selector<void(std::exception_ptr, Arg)>
0407 : public promise_handler_ex_1<Arg> {};
0408
0409 template <typename... Arg>
0410 class promise_handler_selector<void(Arg...)>
0411 : public promise_handler_n<std::tuple<Arg...>> {};
0412
0413 template <typename... Arg>
0414 class promise_handler_selector<void(boost::system::error_code, Arg...)>
0415 : public promise_handler_ec_n<std::tuple<Arg...>> {};
0416
0417 template <typename... Arg>
0418 class promise_handler_selector<void(std::exception_ptr, Arg...)>
0419 : public promise_handler_ex_n<std::tuple<Arg...>> {};
0420
0421
0422
0423 template <typename Signature, typename Allocator>
0424 class promise_handler
0425 : public promise_handler_selector<Signature>
0426 {
0427 public:
0428 typedef Allocator allocator_type;
0429 typedef void result_type;
0430
0431 promise_handler(use_future_t<Allocator> u)
0432 : allocator_(u.get_allocator())
0433 {
0434 this->create_promise(allocator_);
0435 }
0436
0437 allocator_type get_allocator() const noexcept
0438 {
0439 return allocator_;
0440 }
0441
0442 private:
0443 Allocator allocator_;
0444 };
0445
0446 template <typename Function>
0447 struct promise_function_wrapper
0448 {
0449 explicit promise_function_wrapper(Function& f)
0450 : function_(static_cast<Function&&>(f))
0451 {
0452 }
0453
0454 explicit promise_function_wrapper(const Function& f)
0455 : function_(f)
0456 {
0457 }
0458
0459 void operator()()
0460 {
0461 function_();
0462 }
0463
0464 Function function_;
0465 };
0466
0467
0468 template <typename Signature, typename Allocator>
0469 class promise_async_result
0470 {
0471 public:
0472 typedef promise_handler<Signature, Allocator> completion_handler_type;
0473 typedef typename completion_handler_type::future_type return_type;
0474
0475 explicit promise_async_result(completion_handler_type& h)
0476 : future_(h.get_future())
0477 {
0478 }
0479
0480 return_type get()
0481 {
0482 return static_cast<return_type&&>(future_);
0483 }
0484
0485 private:
0486 return_type future_;
0487 };
0488
0489
0490 template <typename Function, typename Allocator>
0491 class packaged_token
0492 {
0493 public:
0494 packaged_token(Function f, const Allocator& a)
0495 : function_(static_cast<Function&&>(f)),
0496 allocator_(a)
0497 {
0498 }
0499
0500
0501 Function function_;
0502 Allocator allocator_;
0503 };
0504
0505
0506
0507 template <typename Function, typename Allocator, typename Result>
0508 class packaged_handler
0509 : public promise_creator<Result>
0510 {
0511 public:
0512 typedef Allocator allocator_type;
0513 typedef void result_type;
0514
0515 packaged_handler(packaged_token<Function, Allocator> t)
0516 : function_(static_cast<Function&&>(t.function_)),
0517 allocator_(t.allocator_)
0518 {
0519 this->create_promise(allocator_);
0520 }
0521
0522 allocator_type get_allocator() const noexcept
0523 {
0524 return allocator_;
0525 }
0526
0527 template <typename... Args>
0528 void operator()(Args&&... args)
0529 {
0530 (promise_invoke_and_set)(*this->p_,
0531 function_, static_cast<Args&&>(args)...);
0532 }
0533
0534 private:
0535 Function function_;
0536 Allocator allocator_;
0537 };
0538
0539
0540 template <typename Function, typename Allocator, typename Result>
0541 class packaged_async_result
0542 {
0543 public:
0544 typedef packaged_handler<Function, Allocator, Result> completion_handler_type;
0545 typedef typename completion_handler_type::future_type return_type;
0546
0547 explicit packaged_async_result(completion_handler_type& h)
0548 : future_(h.get_future())
0549 {
0550 }
0551
0552 return_type get()
0553 {
0554 return static_cast<return_type&&>(future_);
0555 }
0556
0557 private:
0558 return_type future_;
0559 };
0560
0561 }
0562
0563 template <typename Allocator> template <typename Function>
0564 inline detail::packaged_token<decay_t<Function>, Allocator>
0565 use_future_t<Allocator>::operator()(Function&& f) const
0566 {
0567 return detail::packaged_token<decay_t<Function>, Allocator>(
0568 static_cast<Function&&>(f), allocator_);
0569 }
0570
0571 #if !defined(GENERATING_DOCUMENTATION)
0572
0573 template <typename Allocator, typename Result, typename... Args>
0574 class async_result<use_future_t<Allocator>, Result(Args...)>
0575 : public detail::promise_async_result<
0576 void(decay_t<Args>...), Allocator>
0577 {
0578 public:
0579 explicit async_result(
0580 typename detail::promise_async_result<void(decay_t<Args>...),
0581 Allocator>::completion_handler_type& h)
0582 : detail::promise_async_result<
0583 void(decay_t<Args>...), Allocator>(h)
0584 {
0585 }
0586 };
0587
0588 template <typename Function, typename Allocator,
0589 typename Result, typename... Args>
0590 class async_result<detail::packaged_token<Function, Allocator>, Result(Args...)>
0591 : public detail::packaged_async_result<Function, Allocator,
0592 result_of_t<Function(Args...)>>
0593 {
0594 public:
0595 explicit async_result(
0596 typename detail::packaged_async_result<Function, Allocator,
0597 result_of_t<Function(Args...)>>::completion_handler_type& h)
0598 : detail::packaged_async_result<Function, Allocator,
0599 result_of_t<Function(Args...)>>(h)
0600 {
0601 }
0602 };
0603
0604 namespace traits {
0605
0606 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
0607
0608 template <typename T, typename Blocking>
0609 struct equality_comparable<
0610 boost::asio::detail::promise_executor<T, Blocking>>
0611 {
0612 static constexpr bool is_valid = true;
0613 static constexpr bool is_noexcept = true;
0614 };
0615
0616 #endif
0617
0618 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
0619
0620 template <typename T, typename Blocking, typename Function>
0621 struct execute_member<
0622 boost::asio::detail::promise_executor<T, Blocking>, Function>
0623 {
0624 static constexpr bool is_valid = true;
0625 static constexpr bool is_noexcept = false;
0626 typedef void result_type;
0627 };
0628
0629 #endif
0630
0631 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
0632
0633 template <typename T, typename Blocking, typename Property>
0634 struct query_static_constexpr_member<
0635 boost::asio::detail::promise_executor<T, Blocking>,
0636 Property,
0637 typename boost::asio::enable_if<
0638 boost::asio::is_convertible<
0639 Property,
0640 boost::asio::execution::blocking_t
0641 >::value
0642 >::type
0643 >
0644 {
0645 static constexpr bool is_valid = true;
0646 static constexpr bool is_noexcept = true;
0647 typedef Blocking result_type;
0648
0649 static constexpr result_type value() noexcept
0650 {
0651 return Blocking();
0652 }
0653 };
0654
0655 #endif
0656
0657 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
0658
0659 template <typename T, typename Blocking>
0660 struct query_member<
0661 boost::asio::detail::promise_executor<T, Blocking>,
0662 execution::context_t
0663 >
0664 {
0665 static constexpr bool is_valid = true;
0666 static constexpr bool is_noexcept = true;
0667 typedef boost::asio::system_context& result_type;
0668 };
0669
0670 #endif
0671
0672 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
0673
0674 template <typename T, typename Blocking>
0675 struct require_member<
0676 boost::asio::detail::promise_executor<T, Blocking>,
0677 execution::blocking_t::possibly_t
0678 >
0679 {
0680 static constexpr bool is_valid = true;
0681 static constexpr bool is_noexcept = true;
0682 typedef boost::asio::detail::promise_executor<T,
0683 execution::blocking_t::possibly_t> result_type;
0684 };
0685
0686 template <typename T, typename Blocking>
0687 struct require_member<
0688 boost::asio::detail::promise_executor<T, Blocking>,
0689 execution::blocking_t::never_t
0690 >
0691 {
0692 static constexpr bool is_valid = true;
0693 static constexpr bool is_noexcept = true;
0694 typedef boost::asio::detail::promise_executor<T,
0695 execution::blocking_t::never_t> result_type;
0696 };
0697
0698 #endif
0699
0700 }
0701
0702 #endif
0703
0704 }
0705 }
0706
0707 #include <boost/asio/detail/pop_options.hpp>
0708
0709 #endif