| Index: components/scheduler/promises/promise.h
|
| diff --git a/components/scheduler/promises/promise.h b/components/scheduler/promises/promise.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1516cff96afafbd0b9be34658f8a63f47f787df8
|
| --- /dev/null
|
| +++ b/components/scheduler/promises/promise.h
|
| @@ -0,0 +1,257 @@
|
| +// Copyright 2016 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 COMPONENTS_SCHEDULER_PROMISES_PROMISE_H_
|
| +#define COMPONENTS_SCHEDULER_PROMISES_PROMISE_H_
|
| +
|
| +#include "components/scheduler/promises/promise_internal.h"
|
| +
|
| +namespace promise {
|
| +
|
| +template <typename R>
|
| +class SCHEDULER_EXPORT Promise {
|
| + public:
|
| + using ReturnType = R;
|
| + using InternalPromise = internal::Promise<ReturnType>;
|
| +
|
| + Promise() {}
|
| +
|
| + explicit Promise(const scoped_refptr<InternalPromise>& promise)
|
| + : promise_(promise) {}
|
| +
|
| + // Note this is non-explicit to support implicit conversion to allow
|
| + // assigning promise::Race(...).Then() to a Promise<R>.
|
| + Promise(scoped_refptr<InternalPromise>&& promise)
|
| + : promise_(std::move(promise)) {}
|
| +
|
| + // A directive that instructs the executor to resolve this promise before
|
| + // others if possible.
|
| + void SetEager(bool eager) { promise_->SetThisAndPrerequisitesAsEager(eager); }
|
| +
|
| + // Cancels execution, can be restarted by PromiseExecutor::StartResolve.
|
| + void Cancel() { promise_->Cancel(); }
|
| +
|
| + // This will DCHECK if the promise isn't resolved.
|
| + template <typename RR = R>
|
| + internal::enable_if_not_void_t<RR, RR&> GetResolved() {
|
| + return promise_->GetResolved();
|
| + }
|
| +
|
| + // Resolves the promise. May schedule excution of callbacks.
|
| + template <typename RR = R>
|
| + internal::enable_if_not_void_t<RR, void> Resolve(const RR& r) {
|
| + promise_->Resolve(r);
|
| + }
|
| +
|
| + // Resolves the promise with a moveable type. May schedule excution of
|
| + // callbacks.
|
| + template <typename RR = R>
|
| + internal::enable_if_not_void_t<RR, void> Resolve(RR&& r) {
|
| + promise_->Resolve(std::move(r));
|
| + }
|
| +
|
| + // Resolves the promise. May schedule excution of callbacks.
|
| + template <typename RR = R>
|
| + internal::enable_if_void_t<RR, void> Resolve() {
|
| + promise_->Resolve();
|
| + }
|
| +
|
| + // Rejects the promise. May schedule excution of callbacks.
|
| + template <typename RR = R, typename T>
|
| + typename enable_if_rejectable<RR, void>::type Reject(const T& r) {
|
| + promise_->Reject(r);
|
| + }
|
| +
|
| + // Rejects the promise with a moveable type. May schedule excution callbacks.
|
| + template <typename RR = R, typename T>
|
| + typename enable_if_rejectable<RR, void>::type Reject(T&& r) {
|
| + promise_->Reject(std::move(r));
|
| + }
|
| +
|
| + // Rejects the promise. May schedule excution of callbacks.
|
| + template <typename RR = R>
|
| + typename enable_if_rejectable<RR, void>::type Reject() {
|
| + promise_->Reject();
|
| + }
|
| +
|
| + // Resolves the promise with another promise which is sheduled for execution.
|
| + // May schedule excution of callbacks.
|
| + void Resolve(const Promise<R>& promise) {
|
| + promise_->Resolve(promise->promise_);
|
| + }
|
| +
|
| + bool is_resolved() const { return promise_->is_resolved(); }
|
| +
|
| + bool is_rejected() const { return promise_->is_rejected(); }
|
| +
|
| + template <typename ThenR, typename... ThenArgs>
|
| + Promise<ThenR> Then(base::Callback<ThenR(ThenArgs...)>&& cb);
|
| +
|
| + template <typename ThenR>
|
| + Promise<ThenR> Then(base::Callback<ThenR()>&& cb);
|
| +
|
| + template <typename ThenR, typename... ThenArgs>
|
| + Promise<ThenR> Then(base::Callback<Promise<ThenR>(ThenArgs...)>&& cb);
|
| +
|
| + template <typename ThenR>
|
| + Promise<ThenR> Then(base::Callback<Promise<ThenR>()>&& cb);
|
| +
|
| + private:
|
| + friend class internal::PromiseExecutor;
|
| +
|
| + template <typename RR>
|
| + friend class internal::Promise;
|
| +
|
| + template <typename RR>
|
| + friend class internal::RaceSpec;
|
| +
|
| + template <typename... Promises>
|
| + friend class internal::AllSpec;
|
| +
|
| + InternalPromise* promise() const { return promise_.get(); }
|
| +
|
| + scoped_refptr<InternalPromise> promise_;
|
| +};
|
| +
|
| +// Create promise that will run a callback.
|
| +template <typename R, typename... Args>
|
| +Promise<R> Create(base::Callback<R(Args...)> c) {
|
| + return Promise<R>(
|
| + make_scoped_refptr(new internal::FunctionPromise<R, Args...>(c)));
|
| +}
|
| +
|
| +// Create a promise that is already resolved.
|
| +template <typename R>
|
| +Promise<R> Create(const R& r) {
|
| + scoped_refptr<internal::Promise<R>> promise(new internal::Promise<R>(
|
| + internal::PromiseBase::PrerequisitePolicy::NEVER));
|
| + promise->Resolve(r);
|
| + return Promise<R>(promise);
|
| +}
|
| +
|
| +// Create a promise that is already resolved.
|
| +template <typename R>
|
| +Promise<R> Create(R&& r) {
|
| + scoped_refptr<internal::Promise<R>> promise(new internal::Promise<R>(
|
| + internal::PromiseBase::PrerequisitePolicy::NEVER));
|
| + promise->Resolve(std::move(r));
|
| + return Promise<R>(promise);
|
| +}
|
| +
|
| +// Create a promise that is manually resolved.
|
| +template <typename R>
|
| +Promise<R> Create() {
|
| + return Promise<R>(make_scoped_refptr(new internal::Promise<R>(
|
| + internal::PromiseBase::PrerequisitePolicy::NEVER)));
|
| +}
|
| +
|
| +// ===
|
| +
|
| +template <typename R>
|
| +template <typename ThenR, typename... ThenArgs>
|
| +Promise<ThenR> Promise<R>::Then(base::Callback<ThenR(ThenArgs...)>&& cb) {
|
| + using PromiseType = internal::Promise<R>;
|
| + return Promise<ThenR>(
|
| + make_scoped_refptr(new internal::RacePromises<ThenR, ThenR, PromiseType>(
|
| + std::move(cb), {promise_})));
|
| +}
|
| +
|
| +template <>
|
| +template <typename ThenR>
|
| +Promise<ThenR> Promise<void>::Then(base::Callback<ThenR()>&& cb) {
|
| + return Promise<ThenR>(make_scoped_refptr(
|
| + new internal::RaceVoidPromises<ThenR, ThenR>(std::move(cb), {promise_})));
|
| +}
|
| +
|
| +template <typename R>
|
| +template <typename ThenR, typename... ThenArgs>
|
| +Promise<ThenR> Promise<R>::Then(
|
| + base::Callback<Promise<ThenR>(ThenArgs...)>&& cb) {
|
| + using PromiseType = internal::Promise<R>;
|
| + return Promise<ThenR>(make_scoped_refptr(
|
| + new internal::RacePromises<ThenR, Promise<ThenR>, PromiseType>(
|
| + std::move(cb), {promise_})));
|
| +}
|
| +
|
| +template <>
|
| +template <typename ThenR>
|
| +Promise<ThenR> Promise<void>::Then(base::Callback<Promise<ThenR>()>&& cb) {
|
| + return Promise<ThenR>(make_scoped_refptr<internal::Promise<ThenR>>(
|
| + new internal::RaceVoidPromises<ThenR, Promise<ThenR>>(std::move(cb),
|
| + {promise_})));
|
| +}
|
| +
|
| +// ===
|
| +
|
| +/*
|
| +Promises::All(promises...).Then(callback) allows you to schedule a callback to
|
| +run once all of the specified promises have been resolved.
|
| +
|
| +The promises specified must either be all void or all non-void. In the case of
|
| +non-void promises, the callback specified by Then() is called with results of
|
| +the promises.
|
| +
|
| +Race(...).Then() returns a promise which you need to schedule for execution.
|
| +E.g.
|
| +
|
| +Promise<int> p1;
|
| +Promise<bool> p2;
|
| +Promise<float> p3;
|
| +
|
| +void MyFunc(int, bool, float);
|
| +
|
| +...
|
| +Promise<void> p(
|
| + promise::All(p1, p2, p3).Then(base::Bind(&MyFunc));
|
| +
|
| +// Schedule p1, p2 & p3 for execution and once they're run call MyFunc with
|
| +// their return values.
|
| +my_executor_->StartResolve(p);
|
| +*/
|
| +template <typename... Promises>
|
| +internal::AllSpec<Promises...> All(Promises... promises) {
|
| + static_assert(
|
| + internal::check_all_same_type<Promise<void>, Promises...>::value ||
|
| + !internal::check_any_have_type<Promise<void>, Promises...>::value,
|
| + "All(...) requires the promises to either be all void or all non-void.");
|
| + return internal::AllSpec<Promises...>(promises...);
|
| +}
|
| +
|
| +/*
|
| +Promises::Race(promises...).Then(callback) allows you to schedule a callback to
|
| +run once any of the specified promises have been resolved.
|
| +
|
| +The promises must all have the same type. If the promises are non-void, then
|
| +the callback specified by Then() is called with results of the sellected
|
| +resolved promise. The selection algorithm works as follows, when attempting to
|
| +run the callback, the promises specifed in the Race(...) clause are examined in
|
| +order and the first resolved one is selected.
|
| +
|
| +All(...).Then() returns a promise which you need to schedule for execution. E.g.
|
| +
|
| + Promise<int> p1;
|
| + Promise<int> p2;
|
| + Promise<int> p3;
|
| +
|
| + void MyFunc(int);
|
| +
|
| + ...
|
| + Promise<void> p(
|
| + promise::Race(p1, p2, p3).Then(base::Bind(&MyFunc));
|
| +
|
| + // Schedule p1, p2 & p3 for execution and once any of them have been run. When
|
| + // deciding which promise to call MyFunc the promises from the Race() clause
|
| + // scanned in order and the the first resolved one is used.
|
| + my_executor_->StartResolve(p);
|
| +*/
|
| +template <typename R, typename... Promises>
|
| +internal::RaceSpec<R> Race(Promise<R> r1, Promises... promises) {
|
| + static_assert(internal::check_all_same_type<Promise<R>, Promises...>::value,
|
| + "Race(...) requires all the promises to have the same type.");
|
| + return internal::RaceSpec<R>(r1, promises...);
|
| +}
|
| +
|
| +} // namespace promise
|
| +
|
| +#endif // COMPONENTS_SCHEDULER_PROMISES_PROMISE_H_
|
|
|