|
6 | 6 |
|
7 | 7 | #include <beman/execution/detail/sender.hpp> |
8 | 8 | #include <beman/execution/detail/async_scope_token.hpp> |
| 9 | +#include <beman/execution/detail/get_allocator.hpp> |
| 10 | +#include <beman/execution/detail/get_env.hpp> |
| 11 | +#include <beman/execution/detail/make_sender.hpp> |
| 12 | +#include <beman/execution/detail/completion_signatures_of_t.hpp> |
9 | 13 | #include <beman/execution/detail/empty_env.hpp> |
10 | 14 | #include <beman/execution/detail/queryable.hpp> |
11 | 15 | #include <beman/execution/detail/as_tuple.hpp> |
12 | 16 | #include <beman/execution/detail/meta_unique.hpp> |
13 | 17 | #include <beman/execution/detail/receiver.hpp> |
| 18 | +#include <beman/execution/detail/prop.hpp> |
| 19 | +#include <beman/execution/detail/join_env.hpp> |
14 | 20 | #include <beman/execution/detail/set_error.hpp> |
15 | 21 | #include <beman/execution/detail/set_stopped.hpp> |
16 | 22 | #include <beman/execution/detail/set_value.hpp> |
| 23 | +#include <beman/execution/detail/stop_when.hpp> |
| 24 | +#include <beman/execution/detail/write_env.hpp> |
| 25 | +#include <beman/execution/detail/inplace_stop_source.hpp> |
| 26 | +#include <mutex> |
| 27 | +#include <memory> |
17 | 28 | #include <utility> |
18 | 29 | #include <variant> |
19 | 30 | #include <type_traits> |
@@ -82,11 +93,91 @@ struct spawn_future_receiver { |
82 | 93 | } |
83 | 94 | }; |
84 | 95 |
|
| 96 | +template <::beman::execution::sender Sndr, typename Env> |
| 97 | +using future_spawned_sender = decltype(::beman::execution::write_env( |
| 98 | + ::beman::execution::detail::stop_when(::std::declval<Sndr>(), |
| 99 | + ::std::declval<::beman::execution::inplace_stop_token>()), |
| 100 | + ::std::declval<Env>())); |
| 101 | + |
| 102 | +template <typename Allocator, |
| 103 | + ::beman::execution::async_scope_token Token, |
| 104 | + ::beman::execution::sender Sndr, |
| 105 | + typename Env> |
| 106 | +struct spawn_future_state |
| 107 | + : ::beman::execution::detail::spawn_future_state_base<::beman::execution::completion_signatures_of_t< |
| 108 | + ::beman::execution::detail::future_spawned_sender<Sndr, Env>>> { |
| 109 | + using alloc_t = typename ::std::allocator_traits<Allocator>::template rebind_alloc<spawn_future_state>; |
| 110 | + using traits_t = ::std::allocator_traits<alloc_t>; |
| 111 | + |
| 112 | + spawn_future_state(auto a, auto&&, Token tok, auto&&...) : token(tok), alloc(a) { /*-dk:TODO*/ } |
| 113 | + auto complete() noexcept -> void override { /*-dk:TODO*/ } |
| 114 | + auto abandon() noexcept -> void { |
| 115 | + /*-dk:TODO*/ |
| 116 | + this->destroy(); |
| 117 | + } |
| 118 | + auto destroy() noexcept -> void { |
| 119 | + Token tok{this->token}; |
| 120 | + bool assoc{this->associated}; |
| 121 | + { |
| 122 | + alloc_t a{this->alloc}; |
| 123 | + traits_t::destroy(a, this); |
| 124 | + traits_t::deallocate(a, this, 1u); |
| 125 | + } |
| 126 | + if (assoc) { |
| 127 | + tok.disassociate(); |
| 128 | + } |
| 129 | + } |
| 130 | + |
| 131 | + ::std::mutex cerberos{}; |
| 132 | + Token token; |
| 133 | + bool associated{false}; |
| 134 | + alloc_t alloc; |
| 135 | +}; |
| 136 | + |
| 137 | +template <::beman::execution::sender Sndr, typename Ev> |
| 138 | +auto spawn_future_get_allocator(const Sndr& sndr, const Ev& ev) { |
| 139 | + if constexpr (requires { ::beman::execution::get_allocator(ev); }) { |
| 140 | + return ::std::pair(::beman::execution::get_allocator(ev), ev); |
| 141 | + } else if constexpr (requires { ::beman::execution::get_allocator(::beman::execution::get_env(sndr)); }) { |
| 142 | + auto alloc{::beman::execution::get_allocator(::beman::execution::get_env(sndr))}; |
| 143 | + return ::std::pair(alloc, |
| 144 | + ::beman::execution::detail::join_env( |
| 145 | + ::beman::execution::prop(::beman::execution::get_allocator, alloc), ev)); |
| 146 | + } else { |
| 147 | + return ::std::pair(::std::allocator<void>{}, ev); |
| 148 | + } |
| 149 | +} |
| 150 | + |
85 | 151 | class spawn_future_t { |
86 | 152 | public: |
87 | | - template <::beman::execution::sender Sndr, ::beman::execution::async_scope_token Tok, typename Env> |
88 | | - requires ::beman::execution::detail::queryable<::std::remove_cvref_t<Env>> |
89 | | - auto operator()(Sndr&&, Tok&&, Env&&) const {} |
| 153 | + template <::beman::execution::sender Sndr, ::beman::execution::async_scope_token Tok, typename Ev> |
| 154 | + requires ::beman::execution::detail::queryable<::std::remove_cvref_t<Ev>> |
| 155 | + auto operator()(Sndr&& sndr, Tok&& tok, Ev&& ev) const { |
| 156 | + auto make{[&] -> decltype(auto) { //-dk:TODO while decltype(auto) instead of auto? |
| 157 | + return tok.wrap(::std::forward<Sndr>(sndr)); |
| 158 | + }}; |
| 159 | + using sndr_t = decltype(make()); |
| 160 | + static_assert(::beman::execution::sender<Sndr>); |
| 161 | + |
| 162 | + auto [alloc, senv] = spawn_future_get_allocator(sndr, ev); |
| 163 | + using state_t = ::beman::execution::detail::spawn_future_state<decltype(alloc), Tok, sndr_t, decltype(senv)>; |
| 164 | + using state_alloc_t = typename ::std::allocator_traits<decltype(alloc)>::template rebind_alloc<state_t>; |
| 165 | + using state_traits_t = ::std::allocator_traits<state_alloc_t>; |
| 166 | + state_alloc_t state_alloc(alloc); |
| 167 | + using deleter = decltype([](state_t* p) noexcept { |
| 168 | + if (p) |
| 169 | + p->abandon(); |
| 170 | + }); |
| 171 | + state_t* op{state_traits_t::allocate(state_alloc, 1u)}; |
| 172 | + try { |
| 173 | + state_traits_t::construct(state_alloc, op, alloc, make(), tok, senv); |
| 174 | + } catch (...) { |
| 175 | + state_traits_t::deallocate(state_alloc, op, 1u); |
| 176 | + throw; |
| 177 | + } |
| 178 | + |
| 179 | + return ::beman::execution::detail::make_sender(*this, ::std::unique_ptr<state_t, deleter>{op}); |
| 180 | + } |
90 | 181 | template <::beman::execution::sender Sndr, ::beman::execution::async_scope_token Tok> |
91 | 182 | auto operator()(Sndr&& sndr, Tok&& tok) const { |
92 | 183 | return (*this)(::std::forward<Sndr>(sndr), ::std::forward<Tok>(tok), ::beman::execution::empty_env{}); |
|
0 commit comments