Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:34:31

0001 //
0002 // Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_COBALT_DETAIL_SPAWN_HPP
0009 #define BOOST_COBALT_DETAIL_SPAWN_HPP
0010 
0011 #include <boost/cobalt/task.hpp>
0012 #include <boost/asio/dispatch.hpp>
0013 
0014 #include <boost/smart_ptr/allocate_unique.hpp>
0015 
0016 namespace boost::cobalt
0017 {
0018 template<typename T>
0019 struct task;
0020 }
0021 
0022 namespace boost::cobalt::detail
0023 {
0024 
0025 struct async_initiate_spawn
0026 {
0027   template<typename Handler, typename T>
0028   void operator()(Handler && h, task<T> a, executor exec)
0029   {
0030     auto & rec = a.receiver_;
0031     if (rec.done)
0032       return asio::dispatch(
0033           asio::get_associated_immediate_executor(h, exec),
0034           asio::append(std::forward<Handler>(h), rec.exception, rec.exception ? T() : *rec.get_result()));
0035 
0036 #if !defined(BOOST_COBALT_NO_PMR)
0037     auto dalloc = pmr::polymorphic_allocator<void>{boost::cobalt::this_thread::get_default_resource()};
0038     auto alloc = asio::get_associated_allocator(h, dalloc);
0039 #else
0040     auto alloc = asio::get_associated_allocator(h);
0041 #endif
0042     auto recs = allocate_unique<detail::task_receiver<T>>(alloc, std::move(rec));
0043 
0044     auto sl = asio::get_associated_cancellation_slot(h);
0045     if (sl.is_connected())
0046       sl.template emplace<detail::forward_dispatch_cancellation>(recs->promise->signal, exec);
0047 
0048     auto p = recs.get();
0049 
0050     p->promise->exec.emplace(exec);
0051     p->promise->exec_ = exec;
0052 
0053     struct completion_handler
0054     {
0055       using allocator_type = std::decay_t<decltype(alloc)>;
0056 
0057       allocator_type get_allocator() const { return alloc_; }
0058       allocator_type alloc_;
0059 
0060       using executor_type = std::decay_t<decltype(asio::get_associated_executor(h, exec))>;
0061       const executor_type &get_executor() const { return exec_; }
0062       executor_type exec_;
0063 
0064       decltype(recs) r;
0065       Handler handler;
0066 
0067       void operator()()
0068       {
0069         auto ex = r->exception;
0070         T rr{};
0071         if (r->result)
0072           rr = std::move(*r->result);
0073         r.reset();
0074         std::move(handler)(ex, std::move(rr));
0075       }
0076     };
0077 
0078     p->awaited_from.reset(detail::post_coroutine(
0079         completion_handler{
0080             alloc, asio::get_associated_executor(h, exec), std::move(recs), std::move(h)
0081         }).address());
0082 
0083     asio::dispatch(exec, std::coroutine_handle<detail::task_promise<T>>::from_promise(*p->promise));
0084   }
0085 
0086   template<typename Handler>
0087   void operator()(Handler && h, task<void> a, executor exec)
0088   {
0089     if (a.receiver_.done)
0090       return asio::dispatch(
0091           asio::get_associated_immediate_executor(h, exec),
0092           asio::append(std::forward<Handler>(h), a.receiver_.exception));
0093 
0094 
0095 #if !defined(BOOST_COBALT_NO_PMR)
0096     auto alloc = asio::get_associated_allocator(h, pmr::polymorphic_allocator<void>{boost::cobalt::this_thread::get_default_resource()});
0097 #else
0098     auto alloc = asio::get_associated_allocator(h);
0099 #endif
0100     auto recs = allocate_unique<detail::task_receiver<void>>(alloc, std::move(a.receiver_));
0101 
0102     if (recs->done)
0103       return asio::dispatch(asio::get_associated_immediate_executor(h, exec),
0104                             asio::append(std::forward<Handler>(h), recs->exception));
0105 
0106     auto sl = asio::get_associated_cancellation_slot(h);
0107     if (sl.is_connected())
0108       sl.template emplace<detail::forward_dispatch_cancellation>(recs->promise->signal, exec);
0109 
0110     auto p = recs.get();
0111 
0112     p->promise->exec.emplace(exec);
0113     p->promise->exec_ = exec;
0114 
0115     struct completion_handler
0116     {
0117       using allocator_type = std::decay_t<decltype(alloc)>;
0118 
0119       const allocator_type &get_allocator() const { return alloc_; }
0120 
0121       allocator_type alloc_;
0122 
0123       using executor_type = std::decay_t<decltype(asio::get_associated_executor(h, exec))>;
0124       const executor_type &get_executor() const { return exec_; }
0125 
0126       executor_type exec_;
0127       decltype(recs) r;
0128       Handler handler;
0129 
0130       void operator()()
0131       {
0132         auto ex = r->exception;
0133         r.reset();
0134         std::move(handler)(ex);
0135       }
0136     };
0137 
0138     p->awaited_from.reset(detail::post_coroutine(completion_handler{
0139         alloc, asio::get_associated_executor(h, exec), std::move(recs), std::forward<Handler>(h)
0140       }).address());
0141 
0142     asio::dispatch(exec, std::coroutine_handle<detail::task_promise<void>>::from_promise(*p->promise));
0143   }
0144 };
0145 
0146 }
0147 
0148 #endif //BOOST_COBALT_DETAIL_SPAWN_HPP