in demo_example/asio/asio/experimental/promise.hpp [204:275]
static auto all(Executor1 exec, Ps ... ps)
-> promise<void(typename Ps::value_type...), Executor1>
{
using pi = detail::promise_impl<
void(typename Ps::value_type...), Executor1>;
struct impl_t : pi
{
impl_t(Executor1 exec, Ps&& ... ps)
: pi(std::move(exec)),
tup(std::move(ps)...)
{
this->slot.template emplace<cancel_handler>(this);
}
struct cancel_handler
{
impl_t* self;
cancel_handler(impl_t* self)
: self(self)
{
}
void operator()(cancellation_type level)
{
[level, s=self]<std::size_t... Idx>(std::index_sequence<Idx...>)
{
(std::get<Idx>(s->tup).cancel(level), ... );
}(std::make_index_sequence<sizeof...(Ps)>{});
}
};
std::tuple<std::remove_reference_t<Ps>...> tup;
std::tuple<std::optional<typename Ps::value_type>...> partial_result;
cancellation_slot slot{this->cancel.slot()};
};
auto impl = std::allocate_shared<impl_t>(
get_associated_allocator(exec), exec, std::move(ps)...);
impl->executor = exec;
[impl, exec]<std::size_t... Idx>(std::index_sequence<Idx...>)
{
auto step =
[&]<std::size_t I>(std::integral_constant<std::size_t, I>)
{
return [impl]<typename... Args>(Args&& ... args)
{
std::get<I>(impl->partial_result).emplace(
std::forward<Args>(args)...);
if ((std::get<Idx>(impl->partial_result) && ...)) // we're done.
{
impl->result = {*std::get<Idx>(impl->partial_result)...};
impl->done = true;
if (auto f = std::exchange(impl->completion, nullptr); !!f)
std::apply(std::move(f), std::move(*impl->result));
}
};
};
(
std::get<Idx>(impl->tup).async_wait(
bind_executor(exec,
step(std::integral_constant<std::size_t, Idx>{}))),
...
);
}(std::make_index_sequence<sizeof...(Ps)>{});
return {impl};
}