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_ |