static auto race()

in demo_example/asio/asio/experimental/promise.hpp [299:389]


  static auto race(Executor1 exec, Range range)
  {
    using var_t = typename std::decay_t<
        decltype(*std::begin(range))>::value_type;
    using signature_type = std::conditional_t<
        std::is_same_v<var_t, std::monostate>,
        void(std::size_t),
        void(std::size_t, var_t)>;
    using pi = detail::promise_impl<signature_type, Executor1>;
    using promise_t = promise<signature_type, 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()(asio::cancellation_type ct)
        {
          for (auto& r : self->range)
            r.cancel(ct);
        }
      };

      Range range;
      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;

    if (size == 0u)
    {
      if constexpr (std::is_same_v<var_t, std::monostate>)
        impl->result = {-1};
      else
        impl->result = {-1, var_t{}};

      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 promise_t{impl};
    }
    auto idx = 0u;
    for (auto& val : impl->range)
    {
      val.async_wait(
          bind_executor(exec,
            [idx, impl]<typename... Args>(Args&&... args)
            {
              if (impl->done)
                return;
              if constexpr (std::is_same_v<var_t, std::monostate>)
                impl->result = idx;
              else
                impl->result = std::make_tuple(idx,
                    var_t(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 jdx = 0u;

              for (auto &tc : impl->range)
                if (jdx++ != idx)
                  tc.cancel();
            }));
      idx++;
    }
    return promise_t{impl};
  }