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