in demo_example/asio/asio/experimental/promise.hpp [400:486]
static auto all(Executor1 exec, Range range)
-> promise<
void(
std::vector<
typename std::decay_t<
decltype(*std::begin(range))
>::value_type
>
), Executor1>
{
using var_t = typename std::decay_t<
decltype(*std::begin(range))>::value_type;
using pi = detail::promise_impl<void(std::vector<var_t>), Executor1>;
struct impl_t : pi
{
impl_t(Executor1 exec, Range&& range)
: pi(std::move(exec)),
range(std::move(range))
{
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)
{
for (auto& r : self->range)
r.cancel(ct);
}
};
Range range;
std::vector<std::optional<var_t>> partial_result;
cancellation_slot slot{this->cancel.slot()};
};
const auto size = std::distance(std::begin(range), std::end(range));
auto impl = std::allocate_shared<impl_t>(
get_associated_allocator(exec), exec, std::move(range));
impl->executor = exec;
impl->partial_result.resize(size);
if (size == 0u)
{
impl->result.emplace();
impl->done = true;
if (auto f = std::exchange(impl->completion, nullptr); !!f)
asio::post(exec, [impl, f = std::move(f)]() mutable
{
std::apply(std::move(f), std::move(*impl->result));
});
return {impl};
}
auto idx = 0u;
for (auto& val : impl->range) {
val.async_wait(bind_executor(
exec,
[idx, impl]<typename... Args>(Args&&... args) {
impl->partial_result[idx].emplace(std::forward<Args>(args)...);
if (std::all_of(impl->partial_result.begin(),
impl->partial_result.end(),
[](auto &opt) {return opt.has_value();}))
{
impl->result.emplace();
get<0>(*impl->result).reserve(impl->partial_result.size());
for (auto& p : impl->partial_result)
get<0>(*impl->result).push_back(std::move(*p));
impl->done = true;
if (auto f = std::exchange(impl->completion, nullptr); !!f)
std::apply(std::move(f), std::move(*impl->result));
}
}));
idx++;
}
return {impl};
}