File indexing completed on 2025-01-30 09:34:31
0001
0002
0003
0004
0005
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