static auto race()

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};
  }