Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(903)

Side by Side Diff: components/scheduler/promises/promise_internal.h

Issue 1401553002: NOT INTENDED FOR LANDING: A promises demo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Support for rejectatble promises! Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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_INTERNAL_H_
6 #define COMPONENTS_SCHEDULER_PROMISES_PROMISE_INTERNAL_H_
7
8 #include <set>
9 #include <vector>
10
11 #include "base/macros.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "components/scheduler/promises/rejectable.h"
16
17 namespace promise {
18 template <typename R>
19 class Promise;
20
21 namespace internal {
22
23 class PromiseExecutor;
24 class ThreadPoolPromiseExecutor;
25
26 template <typename R>
27 class Promise;
28
29 class SCHEDULER_EXPORT PromiseBase : public base::RefCounted<PromiseBase> {
30 public:
31 enum class PrerequisitePolicy { ALL, ANY, ALWAYS, NEVER };
32
33 explicit PromiseBase(PrerequisitePolicy prerequisite_policy);
34
35 PromiseBase(std::vector<scoped_refptr<PromiseBase>> prerequisites,
36 PrerequisitePolicy prerequisite_policy);
37
38 enum class State {
39 NEW,
40 PENDING,
41 PARTIALLY_RESOLVED,
42 RESOLVED,
43 REJECTED,
44 DEPENDENCY_REJECTED,
45 CANCELLED
46 };
47
48 State state() const { return state_; }
49
50 void SetThisAndPrerequisitesAsEager(bool eager);
51
52 void Cancel();
53
54 std::vector<scoped_refptr<PromiseBase>>& prerequisites() {
55 return prerequisites_;
56 }
57
58 std::set<PromiseBase*>& dependants() { return dependants_; }
59
60 bool can_run_now() const { return can_run_now_; }
61
62 bool is_resolved() const { return state() == PromiseBase::State::RESOLVED; }
63
64 protected:
65 friend class base::RefCounted<PromiseBase>;
66 friend class PromiseExecutor;
67 friend class ThreadPoolPromiseExecutor;
68
69 virtual ~PromiseBase();
70
71 virtual void ExecutorDrivenResolve() = 0;
72
73 void set_state(State state) { state_ = state; }
74
75 void SetThisAndPrerequisitesAsShouldRun(PromiseExecutor* executor,
76 bool should_run);
77
78 void RegisterDynamicDependancy(scoped_refptr<PromiseBase> dependency);
79
80 bool AllPrerequisitesSatisfied() const;
81
82 void SchedulePromiseForResolve();
83
84 void MarkAsResolved();
85 void MarkAsRejected();
86
87 std::vector<scoped_refptr<PromiseBase>> prerequisites_;
88 std::set<PromiseBase*> dependants_;
89 PromiseExecutor* executor_;
90 State state_;
91 PrerequisitePolicy prerequisite_policy_;
92 bool can_run_now_;
93 int should_run_refcount_;
94 int eager_refcount_;
95
96 DISALLOW_COPY_AND_ASSIGN(PromiseBase);
97 };
98
99 template <typename R>
100 class SCHEDULER_EXPORT Promise : public PromiseBase {
101 public:
102 using ReturnType = R;
103
104 // RStorageType = (R == void) ? bool : R;
105 // This is useful to avoid the need for partial template specalization.
106 using RStorageType =
107 typename std::conditional<std::is_void<R>::value, bool, R>::type;
108
109 explicit Promise(PrerequisitePolicy prerequisite_policy)
110 : PromiseBase(prerequisite_policy) {}
111
112 Promise(std::vector<scoped_refptr<PromiseBase>> prerequisites,
113 PrerequisitePolicy prerequisite_policy)
114 : PromiseBase(std::move(prerequisites), prerequisite_policy) {}
115
116 template <typename RR = R>
117 enable_if_not_void_t<RR, RR&> GetResolved() {
118 if (r_promise_)
119 return r_promise_->GetResolved();
120 DCHECK(state() == PromiseBase::State::RESOLVED);
121 return r_;
122 }
123
124 template <typename RR = R>
125 enable_if_not_void_t<RR, void> Resolve(const RR&& r) {
126 r_ = std::move(r);
127 PromiseBase::MarkAsResolved();
128 }
129
130 template <typename RR = R>
131 enable_if_not_void_t<RR, void> Resolve(RR&& r) {
132 r_ = std::move(r);
133 PromiseBase::MarkAsResolved();
134 }
135
136 template <typename RR = R>
137 enable_if_void_t<RR, void> Resolve() {
138 PromiseBase::MarkAsResolved();
139 }
140
141 void Resolve(::promise::Promise<R> promise) {
142 r_promise_ = std::move(promise.promise_);
143 prerequisite_policy_ = PrerequisitePolicy::ALL;
144 state_ = State::PARTIALLY_RESOLVED;
145 RegisterDynamicDependancy(r_promise_);
146 }
147
148 bool is_rejected() const { return false; }
149
150 protected:
151 void ExecutorDrivenResolve() override { NOTREACHED(); }
152
153 RStorageType r_;
154 scoped_refptr<Promise<R>> r_promise_;
155
156 virtual ~Promise() {}
157 };
158
159 // Partial template specilazation to provide syntatic sugar for Rejectable
160 // promises.
161 template <typename ResolveT, typename RejectT>
162 class SCHEDULER_EXPORT Promise<Rejectable<ResolveT, RejectT>>
163 : public PromiseBase {
164 public:
165 using ReturnType = Rejectable<ResolveT, RejectT>;
166
167 explicit Promise(PrerequisitePolicy prerequisite_policy)
168 : PromiseBase(prerequisite_policy) {}
169
170 Promise(std::vector<scoped_refptr<PromiseBase>> prerequisites,
171 PrerequisitePolicy prerequisite_policy)
172 : PromiseBase(std::move(prerequisites), prerequisite_policy) {}
173
174 ReturnType& GetResolved() {
175 if (r_promise_)
176 return r_promise_->GetResolved();
177 return r_;
178 }
179
180 bool is_rejected() const {
181 if (r_promise_)
182 return r_promise_->is_rejected();
183 return state() == PromiseBase::State::REJECTED;
184 }
185
186 template <typename RR = ResolveT>
187 enable_if_not_void_t<RR, void> Resolve(const RR& r) {
188 r_.Resolve(r);
189 PromiseBase::MarkAsResolved();
190 }
191
192 template <typename RR = ResolveT>
193 enable_if_not_void_t<RR, void> Resolve(RR&& r) {
194 r_.Resolve(std::move(r));
195 PromiseBase::MarkAsResolved();
196 }
197
198 template <typename RR = ResolveT>
199 enable_if_void_t<RR, void> Resolve() {
200 r_.Resolve();
201 PromiseBase::MarkAsResolved();
202 }
203
204 void Resolve(const ReturnType& r) {
205 r_ = r;
206 if (r_.is_resolved()) {
207 PromiseBase::MarkAsResolved();
208 } else {
209 PromiseBase::MarkAsRejected();
210 }
211 }
212
213 void Resolve(ReturnType&& r) {
214 r_ = std::move(r);
215 if (r_.is_resolved()) {
216 PromiseBase::MarkAsResolved();
217 } else {
218 PromiseBase::MarkAsRejected();
219 }
220 }
221
222 template <typename RR = RejectT>
223 enable_if_not_void_t<RR, void> Reject(const RR& r) {
224 r_.Reject(r);
225 PromiseBase::MarkAsRejected();
226 }
227
228 template <typename RR = RejectT>
229 enable_if_not_void_t<RR, void> Reject(RR&& r) {
230 r_.Reject(std::move(r));
231 PromiseBase::MarkAsRejected();
232 }
233
234 template <typename RR = RejectT>
235 enable_if_void_t<RR, void> Reject() {
236 r_.Reject();
237 PromiseBase::MarkAsRejected();
238 }
239
240 void Resolve(::promise::Promise<ReturnType> promise) {
241 r_promise_ = std::move(promise.promise_);
242 prerequisite_policy_ = PrerequisitePolicy::ALL;
243 state_ = State::PARTIALLY_RESOLVED;
244 RegisterDynamicDependancy(r_promise_);
245 }
246
247 protected:
248 void ExecutorDrivenResolve() override {
249 // This can get called if r_promise_ rejects.
250 DCHECK(state_ == PromiseBase::State::DEPENDENCY_REJECTED);
251 }
252
253 ReturnType r_;
254 scoped_refptr<Promise<ReturnType>> r_promise_;
255
256 virtual ~Promise() {}
257 };
258
259 template <typename R, typename... Args>
260 class FunctionPromise final : public Promise<R> {
261 public:
262 FunctionPromise(base::Callback<R(Args...)> cb)
263 : Promise<R>(PromiseBase::PrerequisitePolicy::ALWAYS), cb_(cb) {}
264
265 private:
266 ~FunctionPromise() override {}
267
268 void ExecutorDrivenResolve() override {
269 Promise<R>::Resolve(std::move(cb_.Run()));
270 }
271
272 base::Callback<R(Args...)> cb_;
273 };
274
275 template <typename... Args>
276 class FunctionPromise<void, Args...> final : public Promise<void> {
277 public:
278 FunctionPromise(base::Callback<void(Args...)> cb)
279 : Promise<void>(PromiseBase::PrerequisitePolicy::ALWAYS), cb_(cb) {}
280
281 private:
282 ~FunctionPromise() override {}
283
284 void ExecutorDrivenResolve() override {
285 cb_.Run();
286 Promise<void>::Resolve();
287 }
288
289 base::Callback<void(Args...)> cb_;
290 };
291
292 // === promise::Race().Then() implementation
293
294 template <typename ThenR, typename CallbackR, typename AnyPromise>
295 class SCHEDULER_EXPORT RacePromises final : public Promise<ThenR> {
296 public:
297 RacePromises(base::Callback<CallbackR(typename AnyPromise::ReturnType)>&& cb,
298 std::vector<scoped_refptr<PromiseBase>>&& promises)
299 : Promise<ThenR>(std::move(promises),
300 PromiseBase::PrerequisitePolicy::ANY),
301 cb_(std::move(cb)) {}
302
303 private:
304 template <typename CB = CallbackR>
305 enable_if_not_void_t<CB, void> ResolveInternal(PromiseBase* prerequisite) {
306 Promise<ThenR>::Resolve(std::move(cb_.Run(
307 std::move(static_cast<AnyPromise*>(prerequisite)->GetResolved()))));
308 }
309
310 template <typename CB = CallbackR>
311 enable_if_void_t<CB, void> ResolveInternal(PromiseBase* prerequisite) {
312 cb_.Run(std::move(static_cast<AnyPromise*>(prerequisite)->GetResolved()));
313 Promise<ThenR>::Resolve();
314 }
315
316 void ExecutorDrivenResolve() override {
317 for (const scoped_refptr<PromiseBase>& prerequisite :
318 PromiseBase::prerequisites_) {
319 if (prerequisite->state() == PromiseBase::State::RESOLVED ||
320 prerequisite->state() == PromiseBase::State::REJECTED) {
321 ResolveInternal(std::move(prerequisite.get()));
322 return;
323 }
324 }
325 NOTREACHED();
326 }
327
328 ~RacePromises() override {}
329
330 base::Callback<CallbackR(typename AnyPromise::ReturnType)> cb_;
331 };
332
333 template <typename ThenR, typename CallbackR>
334 class SCHEDULER_EXPORT RaceVoidPromises final : public Promise<ThenR> {
335 public:
336 RaceVoidPromises(base::Callback<CallbackR()>&& cb,
337 std::vector<scoped_refptr<PromiseBase>>&& promises)
338 : Promise<ThenR>(std::move(promises),
339 PromiseBase::PrerequisitePolicy::ANY),
340 cb_(std::move(cb)) {}
341
342 private:
343 template <typename CB = CallbackR>
344 enable_if_not_void_t<CB, void> ResolveInternal() {
345 Promise<ThenR>::Resolve(std::move(cb_.Run()));
346 }
347
348 template <typename CB = CallbackR>
349 enable_if_void_t<CB, void> ResolveInternal() {
350 cb_.Run();
351 Promise<ThenR>::Resolve();
352 }
353
354 void ExecutorDrivenResolve() override {
355 for (const scoped_refptr<PromiseBase>& prerequisite :
356 PromiseBase::prerequisites_) {
357 if (prerequisite->state() == PromiseBase::State::RESOLVED) {
358 ResolveInternal();
359 return;
360 }
361 }
362 NOTREACHED();
363 }
364
365 ~RaceVoidPromises() override {}
366
367 base::Callback<CallbackR()> cb_;
368 };
369
370 template <typename R>
371 class SCHEDULER_EXPORT RaceSpec {
372 public:
373 template <typename RR>
374 static PromiseBase* GetPromiseBase(RR r) {
375 return r.promise();
376 }
377
378 template <typename... Promises>
379 RaceSpec(::promise::Promise<R> r, Promises... promises)
380 : promises_({r.promise(), GetPromiseBase(promises)...}) {}
381
382 template <typename RR = R, typename ThenR>
383 enable_if_not_void_t<RR, ::promise::Promise<ThenR>> Then(
384 base::Callback<ThenR(RR)>&& cb) {
385 return ::promise::Promise<ThenR>(new RacePromises<ThenR, ThenR, Promise<R>>(
386 std::move(cb), std::move(promises_)));
387 }
388
389 template <typename ThenR>
390 ::promise::Promise<ThenR> Then(base::Callback<ThenR()>&& cb) {
391 return ::promise::Promise<ThenR>(new RaceVoidPromises<ThenR, ThenR>(
392 std::move(cb), std::move(promises_)));
393 }
394
395 template <typename RR = R, typename ThenR>
396 enable_if_not_void_t<RR, ::promise::Promise<ThenR>> Then(
397 base::Callback<::promise::Promise<ThenR>(RR)>&& cb) {
398 return ::promise::Promise<ThenR>(
399 new RacePromises<ThenR, ::promise::Promise<ThenR>, Promise<RR>>(
400 std::move(cb), std::move(promises_)));
401 }
402
403 template <typename ThenR>
404 ::promise::Promise<ThenR> Then(
405 base::Callback<::promise::Promise<ThenR>()>&& cb) {
406 return ::promise::Promise<ThenR>(
407 new RaceVoidPromises<ThenR, ::promise::Promise<ThenR>>(
408 std::move(cb), std::move(promises_)));
409 }
410
411 private:
412 std::vector<scoped_refptr<PromiseBase>> promises_;
413 };
414
415 // === promise::All().Then() implementation
416
417 template <typename ThenR, typename CB, typename... Promises>
418 class SCHEDULER_EXPORT RunAfterAllPromises final : public Promise<ThenR> {
419 public:
420 RunAfterAllPromises(base::Callback<CB>&& cb,
421 std::vector<scoped_refptr<PromiseBase>>&& promises)
422 : Promise<ThenR>(std::move(promises),
423 PromiseBase::PrerequisitePolicy::ALL),
424 cb_(std::move(cb)) {}
425
426 private:
427 template <size_t... Indices, class... Args>
428 ThenR forward(indices<Indices...>) {
429 // The PromiseResolver is evaluated for each index in the Indices parameter
430 // pack. The trailing '...' is the template magic that makes that work.
431 return cb_.Run(std::move(PromiseResolver<Indices, Promises...>::GetResolved(
432 PromiseBase::prerequisites_))...);
433 }
434
435 template <size_t... Indices, class... Args>
436 void forward_void(indices<Indices...>) {
437 // The PromiseResolver is evaluated for each index in the Indices parameter
438 // pack. The trailing '...' is the template magic that makes that work.
439 cb_.Run(std::move(PromiseResolver<Indices, Promises...>::GetResolved(
440 PromiseBase::prerequisites_))...);
441 }
442
443 template <typename ThenRR = ThenR>
444 enable_if_not_void_t<ThenRR, void> ResolveInternal() {
445 using Indices = typename make_indices<sizeof...(Promises)>::type;
446 Promise<ThenRR>::Resolve(std::move(forward(Indices())));
447 }
448
449 template <typename ThenRR = ThenR>
450 enable_if_void_t<ThenRR, void> ResolveInternal() {
451 using Indices = typename make_indices<sizeof...(Promises)>::type;
452 forward_void(Indices());
453 Promise<ThenRR>::Resolve();
454 }
455
456 void ExecutorDrivenResolve() override { ResolveInternal(); }
457
458 ~RunAfterAllPromises() override {}
459
460 base::Callback<CB> cb_;
461 };
462
463 template <typename ThenR, typename CB, typename... Promises>
464 class SCHEDULER_EXPORT RunAfterAllVoidPromises final : public Promise<ThenR> {
465 public:
466 RunAfterAllVoidPromises(base::Callback<CB>&& cb,
467 std::vector<scoped_refptr<PromiseBase>>&& promises)
468 : Promise<ThenR>(std::move(promises),
469 PromiseBase::PrerequisitePolicy::ALL),
470 cb_(std::move(cb)) {}
471
472 private:
473 template <typename ThenRR = ThenR>
474 enable_if_not_void_t<ThenRR, void> ResolveInternal() {
475 Promise<ThenR>::Resolve(std::move(std::move(cb_.Run())));
476 }
477
478 template <typename ThenRR = ThenR>
479 enable_if_void_t<ThenRR, void> ResolveInternal() {
480 cb_.Run();
481 Promise<ThenR>::Resolve();
482 }
483
484 void ExecutorDrivenResolve() override { ResolveInternal(); }
485
486 ~RunAfterAllVoidPromises() override {}
487
488 base::Callback<CB> cb_;
489 };
490
491 template <typename... Promises>
492 class SCHEDULER_EXPORT AllSpec {
493 public:
494 template <typename R>
495 static PromiseBase* GetPromiseBase(R r) {
496 return r.promise();
497 }
498
499 AllSpec(Promises... promises) : promises_({GetPromiseBase(promises)...}) {}
500
501 template <typename ThenR, typename... ThenArgs>
502 scoped_refptr<Promise<ThenR>> Then(base::Callback<ThenR(ThenArgs...)>&& cb) {
503 static_assert(
504 sizeof...(ThenArgs) == sizeof...(Promises),
505 "Must have the same number of promises and callback arguments");
506 static_assert(sizeof...(Promises) > 0,
507 "Must have at least one promise to wait on");
508 return make_scoped_refptr<Promise<ThenR>>(
509 new RunAfterAllPromises<ThenR, ThenR(ThenArgs...), Promises...>(
510 std::move(cb), std::move(promises_)));
511 }
512
513 template <typename ThenR>
514 scoped_refptr<Promise<ThenR>> Then(base::Callback<ThenR()>&& cb) {
515 static_assert(sizeof...(Promises) > 0,
516 "Must have at least one promise to wait on");
517 return make_scoped_refptr<Promise<ThenR>>(
518 new RunAfterAllVoidPromises<ThenR, ThenR(), Promises...>(
519 std::move(cb), std::move(promises_)));
520 }
521
522 private:
523 std::vector<scoped_refptr<PromiseBase>> promises_;
524 };
525
526 } // namespace internal
527 } // namespace promise
528
529 #endif // COMPONENTS_SCHEDULER_PROMISES_PROMISE_INTERNAL_H_
OLDNEW
« no previous file with comments | « components/scheduler/promises/promise_executor.cc ('k') | components/scheduler/promises/promise_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698