in demo_example/asio/asio/experimental/promise.hpp [124:201]
static auto race(Executor1 exec, Ps ... ps)
-> promise<void(std::variant<typename Ps::value_type...>), Executor1>
{
using var_t = std::variant<typename Ps::value_type...>;
using pi = detail::promise_impl<void(var_t), 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 ct)
{
[ct, s=self]<std::size_t... Idx>(std::index_sequence<Idx...>)
{
(std::get<Idx>(s->tup).cancel(ct), ... );
}(std::make_index_sequence<sizeof...(Ps)>{});
}
};
std::tuple<std::remove_reference_t<Ps>...> tup;
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)
{
if (impl->done)
return;
impl->result = var_t(std::in_place_index<I>,
std::forward<Args>(args)...);
impl->done = true;
if (auto f = std::exchange(impl->completion, nullptr); !!f)
std::apply(std::move(f), std::move(*impl->result));
auto cancel =
[&]<std::size_t Id>(std::integral_constant<std::size_t, Id>)
{
if constexpr (I != Id)
get<I>(impl->tup).cancel();
};
(cancel(std::integral_constant<std::size_t, Idx>{}), ...);
};
};
(
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};
}