blob: bc5a265d5fb4c7a90055ad1f0c6bc58b90c64438 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TASK_PROMISE_ALL_TUPLE_EXECUTOR_H_
#define BASE_TASK_PROMISE_ALL_TUPLE_EXECUTOR_H_
#include <tuple>
#include "base/task/promise/abstract_promise.h"
#include "base/task/promise/helpers.h"
namespace base {
namespace internal {
template <typename Tuple,
typename Indices =
std::make_index_sequence<std::tuple_size<Tuple>::value>>
struct TupleConstructor;
template <typename Tuple, size_t... Indices>
struct TupleConstructor<Tuple, std::index_sequence<Indices...>> {
template <typename ArgType>
static auto GetResolvedValueFromPromise(AbstractPromise* arg) {
using ResolvedType = base::Resolved<UndoToNonVoidT<ArgType>>;
return ArgMoveSemanticsHelper<ArgType, ResolvedType>::Get(arg);
}
// Resolves |result| with a std::tuple of the promise results of the dependent
// promises.
static void ConstructTuple(
const std::vector<DependentList::Node>* prerequisite_list,
AbstractPromise* result) {
DCHECK_EQ(sizeof...(Indices), prerequisite_list->size());
result->emplace(
in_place_type_t<Resolved<Tuple>>(),
GetResolvedValueFromPromise<std::tuple_element_t<Indices, Tuple>>(
(*prerequisite_list)[Indices].prerequisite())...);
}
};
template <typename T>
struct TupleCanResolveHelper;
template <typename... Ts>
struct TupleCanResolveHelper<std::tuple<Ts...>> {
static constexpr bool value =
any_of({!std::is_same<Ts, NoResolve>::value...});
};
// For Promises::All(Promise<Ts>... promises)
template <typename ResolveTuple, typename RejectType>
class AllTuplePromiseExecutor {
public:
using RejectT = Rejected<RejectType>;
bool IsCancelled() const { return false; }
static constexpr PromiseExecutor::PrerequisitePolicy kPrerequisitePolicy =
PromiseExecutor::PrerequisitePolicy::kAll;
void Execute(AbstractPromise* promise) {
// All is rejected if any prerequisites are rejected.
AbstractPromise* first_settled = promise->GetFirstSettledPrerequisite();
if (first_settled && first_settled->IsRejected()) {
AllPromiseRejectHelper<RejectT>::Reject(promise, first_settled);
return;
}
const std::vector<DependentList::Node>* prerequisite_list =
promise->prerequisite_list();
DCHECK(prerequisite_list);
TupleConstructor<ResolveTuple>::ConstructTuple(prerequisite_list, promise);
}
#if DCHECK_IS_ON()
PromiseExecutor::ArgumentPassingType ResolveArgumentPassingType() const {
return UseMoveSemantics<ResolveTuple>::argument_passing_type;
}
PromiseExecutor::ArgumentPassingType RejectArgumentPassingType() const {
return UseMoveSemantics<RejectType>::argument_passing_type;
}
bool CanResolve() const { return TupleCanResolveHelper<ResolveTuple>::value; }
bool CanReject() const { return !std::is_same<RejectType, NoReject>::value; }
#endif
};
} // namespace internal
} // namespace base
#endif // BASE_TASK_PROMISE_ALL_TUPLE_EXECUTOR_H_