Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:29:03

0001 //
0002 // impl/use_future.hpp
0003 // ~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 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_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 // defined(_MSC_VER) && (_MSC_VER >= 1200)
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 // !defined(BOOST_ASIO_NO_EXCEPTIONS)
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 // !defined(BOOST_ASIO_NO_EXCEPTIONS)
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 // !defined(BOOST_ASIO_NO_EXCEPTIONS)
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 // !defined(BOOST_ASIO_NO_EXCEPTIONS)
0071 }
0072 
0073 // A function object adapter to invoke a nullary function object and capture
0074 // any exception thrown into a promise.
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 // !defined(BOOST_ASIO_NO_EXCEPTIONS)
0090     {
0091       f_();
0092     }
0093 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0094     catch (...)
0095     {
0096       p_->set_exception(std::current_exception());
0097     }
0098 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
0099   }
0100 
0101 private:
0102   shared_ptr<std::promise<T>> p_;
0103   decay_t<F> f_;
0104 };
0105 
0106 // An executor that adapts the system_executor to capture any exception thrown
0107 // by a submitted function object and save it into a promise.
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 // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
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 // The base class for all completion handlers that create promises.
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 // For completion signature void().
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 // For completion signature void(disposition auto).
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 // For completion signature void(T).
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 // For completion signature void(disposition auto, T).
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 // For completion signature void(T1, ..., Tn);
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 // For completion signature void(error_code, T1, ..., Tn);
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 // Helper template to choose the appropriate concrete promise handler
0324 // implementation based on the supplied completion signature.
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 // Completion handlers produced from the use_future completion token, when not
0357 // using use_future::operator().
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 // Helper base class for async_result specialisation.
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 // Return value from use_future::operator().
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 //private:
0436   Function function_;
0437   Allocator allocator_;
0438 };
0439 
0440 // Completion handlers produced from the use_future completion token, when
0441 // using use_future::operator().
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 // Helper base class for async_result specialisation.
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 } // namespace detail
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 // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
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 // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
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 // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
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 // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
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 // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
0634 
0635 } // namespace traits
0636 
0637 #endif // !defined(GENERATING_DOCUMENTATION)
0638 
0639 } // namespace asio
0640 } // namespace boost
0641 
0642 #include <boost/asio/detail/pop_options.hpp>
0643 
0644 #endif // BOOST_ASIO_IMPL_USE_FUTURE_HPP