OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef COMPONENTS_SCHEDULER_PROMISES_PROMISE_H_ |
| 6 #define COMPONENTS_SCHEDULER_PROMISES_PROMISE_H_ |
| 7 |
| 8 #include "components/scheduler/promises/promise_internal.h" |
| 9 |
| 10 namespace promise { |
| 11 |
| 12 template <typename R> |
| 13 class SCHEDULER_EXPORT Promise { |
| 14 public: |
| 15 using ReturnType = R; |
| 16 using InternalPromise = internal::Promise<ReturnType>; |
| 17 |
| 18 Promise() {} |
| 19 |
| 20 explicit Promise(const scoped_refptr<InternalPromise>& promise) |
| 21 : promise_(promise) {} |
| 22 |
| 23 // Note this is non-explicit to support implicit conversion to allow |
| 24 // assigning promise::Race(...).Then() to a Promise<R>. |
| 25 Promise(scoped_refptr<InternalPromise>&& promise) |
| 26 : promise_(std::move(promise)) {} |
| 27 |
| 28 // A directive that instructs the executor to resolve this promise before |
| 29 // others if possible. |
| 30 void SetEager(bool eager) { promise_->SetThisAndPrerequisitesAsEager(eager); } |
| 31 |
| 32 // Cancels execution, can be restarted by PromiseExecutor::StartResolve. |
| 33 void Cancel() { promise_->Cancel(); } |
| 34 |
| 35 // This will DCHECK if the promise isn't resolved. |
| 36 template <typename RR = R> |
| 37 internal::enable_if_not_void_t<RR, RR&> GetResolved() { |
| 38 return promise_->GetResolved(); |
| 39 } |
| 40 |
| 41 // Resolves the promise. May schedule excution of callbacks. |
| 42 template <typename RR = R> |
| 43 internal::enable_if_not_void_t<RR, void> Resolve(const RR& r) { |
| 44 promise_->Resolve(r); |
| 45 } |
| 46 |
| 47 // Resolves the promise with a moveable type. May schedule excution of |
| 48 // callbacks. |
| 49 template <typename RR = R> |
| 50 internal::enable_if_not_void_t<RR, void> Resolve(RR&& r) { |
| 51 promise_->Resolve(std::move(r)); |
| 52 } |
| 53 |
| 54 // Resolves the promise. May schedule excution of callbacks. |
| 55 template <typename RR = R> |
| 56 internal::enable_if_void_t<RR, void> Resolve() { |
| 57 promise_->Resolve(); |
| 58 } |
| 59 |
| 60 // Rejects the promise. May schedule excution of callbacks. |
| 61 template <typename RR = R, typename T> |
| 62 typename enable_if_rejectable<RR, void>::type Reject(const T& r) { |
| 63 promise_->Reject(r); |
| 64 } |
| 65 |
| 66 // Rejects the promise with a moveable type. May schedule excution callbacks. |
| 67 template <typename RR = R, typename T> |
| 68 typename enable_if_rejectable<RR, void>::type Reject(T&& r) { |
| 69 promise_->Reject(std::move(r)); |
| 70 } |
| 71 |
| 72 // Rejects the promise. May schedule excution of callbacks. |
| 73 template <typename RR = R> |
| 74 typename enable_if_rejectable<RR, void>::type Reject() { |
| 75 promise_->Reject(); |
| 76 } |
| 77 |
| 78 // Resolves the promise with another promise which is sheduled for execution. |
| 79 // May schedule excution of callbacks. |
| 80 void Resolve(const Promise<R>& promise) { |
| 81 promise_->Resolve(promise->promise_); |
| 82 } |
| 83 |
| 84 bool is_resolved() const { return promise_->is_resolved(); } |
| 85 |
| 86 bool is_rejected() const { return promise_->is_rejected(); } |
| 87 |
| 88 template <typename ThenR, typename... ThenArgs> |
| 89 Promise<ThenR> Then(base::Callback<ThenR(ThenArgs...)>&& cb); |
| 90 |
| 91 template <typename ThenR> |
| 92 Promise<ThenR> Then(base::Callback<ThenR()>&& cb); |
| 93 |
| 94 template <typename ThenR, typename... ThenArgs> |
| 95 Promise<ThenR> Then(base::Callback<Promise<ThenR>(ThenArgs...)>&& cb); |
| 96 |
| 97 template <typename ThenR> |
| 98 Promise<ThenR> Then(base::Callback<Promise<ThenR>()>&& cb); |
| 99 |
| 100 private: |
| 101 friend class internal::PromiseExecutor; |
| 102 |
| 103 template <typename RR> |
| 104 friend class internal::Promise; |
| 105 |
| 106 template <typename RR> |
| 107 friend class internal::RaceSpec; |
| 108 |
| 109 template <typename... Promises> |
| 110 friend class internal::AllSpec; |
| 111 |
| 112 InternalPromise* promise() const { return promise_.get(); } |
| 113 |
| 114 scoped_refptr<InternalPromise> promise_; |
| 115 }; |
| 116 |
| 117 // Create promise that will run a callback. |
| 118 template <typename R, typename... Args> |
| 119 Promise<R> Create(base::Callback<R(Args...)> c) { |
| 120 return Promise<R>( |
| 121 make_scoped_refptr(new internal::FunctionPromise<R, Args...>(c))); |
| 122 } |
| 123 |
| 124 // Create a promise that is already resolved. |
| 125 template <typename R> |
| 126 Promise<R> Create(const R& r) { |
| 127 scoped_refptr<internal::Promise<R>> promise(new internal::Promise<R>( |
| 128 internal::PromiseBase::PrerequisitePolicy::NEVER)); |
| 129 promise->Resolve(r); |
| 130 return Promise<R>(promise); |
| 131 } |
| 132 |
| 133 // Create a promise that is already resolved. |
| 134 template <typename R> |
| 135 Promise<R> Create(R&& r) { |
| 136 scoped_refptr<internal::Promise<R>> promise(new internal::Promise<R>( |
| 137 internal::PromiseBase::PrerequisitePolicy::NEVER)); |
| 138 promise->Resolve(std::move(r)); |
| 139 return Promise<R>(promise); |
| 140 } |
| 141 |
| 142 // Create a promise that is manually resolved. |
| 143 template <typename R> |
| 144 Promise<R> Create() { |
| 145 return Promise<R>(make_scoped_refptr(new internal::Promise<R>( |
| 146 internal::PromiseBase::PrerequisitePolicy::NEVER))); |
| 147 } |
| 148 |
| 149 // === |
| 150 |
| 151 template <typename R> |
| 152 template <typename ThenR, typename... ThenArgs> |
| 153 Promise<ThenR> Promise<R>::Then(base::Callback<ThenR(ThenArgs...)>&& cb) { |
| 154 using PromiseType = internal::Promise<R>; |
| 155 return Promise<ThenR>( |
| 156 make_scoped_refptr(new internal::RacePromises<ThenR, ThenR, PromiseType>( |
| 157 std::move(cb), {promise_}))); |
| 158 } |
| 159 |
| 160 template <> |
| 161 template <typename ThenR> |
| 162 Promise<ThenR> Promise<void>::Then(base::Callback<ThenR()>&& cb) { |
| 163 return Promise<ThenR>(make_scoped_refptr( |
| 164 new internal::RaceVoidPromises<ThenR, ThenR>(std::move(cb), {promise_}))); |
| 165 } |
| 166 |
| 167 template <typename R> |
| 168 template <typename ThenR, typename... ThenArgs> |
| 169 Promise<ThenR> Promise<R>::Then( |
| 170 base::Callback<Promise<ThenR>(ThenArgs...)>&& cb) { |
| 171 using PromiseType = internal::Promise<R>; |
| 172 return Promise<ThenR>(make_scoped_refptr( |
| 173 new internal::RacePromises<ThenR, Promise<ThenR>, PromiseType>( |
| 174 std::move(cb), {promise_}))); |
| 175 } |
| 176 |
| 177 template <> |
| 178 template <typename ThenR> |
| 179 Promise<ThenR> Promise<void>::Then(base::Callback<Promise<ThenR>()>&& cb) { |
| 180 return Promise<ThenR>(make_scoped_refptr<internal::Promise<ThenR>>( |
| 181 new internal::RaceVoidPromises<ThenR, Promise<ThenR>>(std::move(cb), |
| 182 {promise_}))); |
| 183 } |
| 184 |
| 185 // === |
| 186 |
| 187 /* |
| 188 Promises::All(promises...).Then(callback) allows you to schedule a callback to |
| 189 run once all of the specified promises have been resolved. |
| 190 |
| 191 The promises specified must either be all void or all non-void. In the case of |
| 192 non-void promises, the callback specified by Then() is called with results of |
| 193 the promises. |
| 194 |
| 195 Race(...).Then() returns a promise which you need to schedule for execution. |
| 196 E.g. |
| 197 |
| 198 Promise<int> p1; |
| 199 Promise<bool> p2; |
| 200 Promise<float> p3; |
| 201 |
| 202 void MyFunc(int, bool, float); |
| 203 |
| 204 ... |
| 205 Promise<void> p( |
| 206 promise::All(p1, p2, p3).Then(base::Bind(&MyFunc)); |
| 207 |
| 208 // Schedule p1, p2 & p3 for execution and once they're run call MyFunc with |
| 209 // their return values. |
| 210 my_executor_->StartResolve(p); |
| 211 */ |
| 212 template <typename... Promises> |
| 213 internal::AllSpec<Promises...> All(Promises... promises) { |
| 214 static_assert( |
| 215 internal::check_all_same_type<Promise<void>, Promises...>::value || |
| 216 !internal::check_any_have_type<Promise<void>, Promises...>::value, |
| 217 "All(...) requires the promises to either be all void or all non-void."); |
| 218 return internal::AllSpec<Promises...>(promises...); |
| 219 } |
| 220 |
| 221 /* |
| 222 Promises::Race(promises...).Then(callback) allows you to schedule a callback to |
| 223 run once any of the specified promises have been resolved. |
| 224 |
| 225 The promises must all have the same type. If the promises are non-void, then |
| 226 the callback specified by Then() is called with results of the sellected |
| 227 resolved promise. The selection algorithm works as follows, when attempting to |
| 228 run the callback, the promises specifed in the Race(...) clause are examined in |
| 229 order and the first resolved one is selected. |
| 230 |
| 231 All(...).Then() returns a promise which you need to schedule for execution. E.g. |
| 232 |
| 233 Promise<int> p1; |
| 234 Promise<int> p2; |
| 235 Promise<int> p3; |
| 236 |
| 237 void MyFunc(int); |
| 238 |
| 239 ... |
| 240 Promise<void> p( |
| 241 promise::Race(p1, p2, p3).Then(base::Bind(&MyFunc)); |
| 242 |
| 243 // Schedule p1, p2 & p3 for execution and once any of them have been run. When |
| 244 // deciding which promise to call MyFunc the promises from the Race() clause |
| 245 // scanned in order and the the first resolved one is used. |
| 246 my_executor_->StartResolve(p); |
| 247 */ |
| 248 template <typename R, typename... Promises> |
| 249 internal::RaceSpec<R> Race(Promise<R> r1, Promises... promises) { |
| 250 static_assert(internal::check_all_same_type<Promise<R>, Promises...>::value, |
| 251 "Race(...) requires all the promises to have the same type."); |
| 252 return internal::RaceSpec<R>(r1, promises...); |
| 253 } |
| 254 |
| 255 } // namespace promise |
| 256 |
| 257 #endif // COMPONENTS_SCHEDULER_PROMISES_PROMISE_H_ |
OLD | NEW |