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

Side by Side Diff: components/scheduler/promises/promise.cc

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 #include "components/scheduler/promises/promise.h"
6 #include "components/scheduler/promises/promise_executor.h"
7
8 namespace promise {
9 namespace internal {
10
11 PromiseBase::PromiseBase(PrerequisitePolicy prerequisite_policy)
12 : executor_(nullptr),
13 state_(State::NEW),
14 prerequisite_policy_(prerequisite_policy),
15 can_run_now_(false),
16 should_run_refcount_(0),
17 eager_refcount_(0) {}
18
19 PromiseBase::PromiseBase(std::vector<scoped_refptr<PromiseBase>> prerequisites,
20 PrerequisitePolicy prerequisite_policy)
21 : prerequisites_(std::move(prerequisites)),
22 executor_(nullptr),
23 state_(State::NEW),
24 prerequisite_policy_(prerequisite_policy),
25 can_run_now_(false),
26 should_run_refcount_(0),
27 eager_refcount_(0) {
28 for (scoped_refptr<PromiseBase>& prerequisite : prerequisites_) {
29 if (prerequisite->state_ != State::NEW)
30 continue;
31
32 prerequisite->dependants_.insert(this);
33 }
34 }
35
36 PromiseBase::~PromiseBase() {}
37
38 void PromiseBase::RegisterDynamicDependancy(
39 scoped_refptr<PromiseBase> dependency) {
40 PromiseBase* dependency_ptr = dependency.get();
41 dependency_ptr->dependants_.insert(this);
42 prerequisites_.push_back(std::move(dependency));
43
44 if (dependency_ptr->state() == PromiseBase::State::RESOLVED) {
45 MarkAsResolved();
46 return;
47 } else if (dependency_ptr->state() == PromiseBase::State::REJECTED) {
48 MarkAsRejected();
49 return;
50 }
51
52 // We need to execute later when dependency has been resolved.
53 can_run_now_ = false;
54
55 if (!executor_)
56 return;
57
58 if (eager_refcount_ > 0) {
59 executor_->eager_ready_set_.erase(this);
60 } else {
61 executor_->lazy_ready_set_.erase(this);
62 }
63
64 executor_->StartResolveInternal(dependency_ptr);
65 }
66
67 void PromiseBase::SetThisAndPrerequisitesAsEager(bool eager) {
68 if (state_ == PromiseBase::State::RESOLVED)
69 return;
70
71 DCHECK(state_ != PromiseBase::State::CANCELLED);
72 if (eager) {
73 eager_refcount_++;
74 if (executor_ && eager_refcount_ == 1 && can_run_now_) {
75 executor_->lazy_ready_set_.erase(this);
76 executor_->eager_ready_set_.insert(this);
77 }
78 } else {
79 eager_refcount_--;
80 DCHECK_GE(eager_refcount_, 0);
81 if (executor_ && eager_refcount_ == 0 && can_run_now_) {
82 executor_->eager_ready_set_.erase(this);
83 executor_->lazy_ready_set_.insert(this);
84 }
85 }
86
87 for (scoped_refptr<PromiseBase>& prerequisite : prerequisites_) {
88 prerequisite->SetThisAndPrerequisitesAsEager(eager);
89 }
90 }
91
92 void PromiseBase::SetThisAndPrerequisitesAsShouldRun(PromiseExecutor* executor,
93 bool should_run) {
94 if (state_ == State::RESOLVED)
95 return;
96
97 executor_ = executor;
98 if (should_run) {
99 should_run_refcount_++;
100 DCHECK_GT(should_run_refcount_, 0);
101 if (!can_run_now_ && AllPrerequisitesSatisfied())
102 SchedulePromiseForResolve();
103 } else {
104 should_run_refcount_--;
105 DCHECK_GE(should_run_refcount_, 0);
106 if (should_run_refcount_ == 0) {
107 can_run_now_ = false;
108 if (executor_) {
109 if (eager_refcount_ > 0) {
110 executor_->eager_ready_set_.erase(this);
111 } else {
112 executor_->lazy_ready_set_.erase(this);
113 }
114 }
115 }
116 }
117
118 for (scoped_refptr<PromiseBase>& prerequisite : prerequisites_) {
119 prerequisite->SetThisAndPrerequisitesAsShouldRun(executor_, should_run);
120 }
121 }
122
123 void PromiseBase::SchedulePromiseForResolve() {
124 DCHECK(AllPrerequisitesSatisfied());
125
126 can_run_now_ = true;
127
128 if (!executor_)
129 return;
130
131 if (eager_refcount_ > 0) {
132 executor_->eager_ready_set_.insert(this);
133 } else {
134 executor_->lazy_ready_set_.insert(this);
135 }
136 }
137
138 bool PromiseBase::AllPrerequisitesSatisfied() const {
139 if (state_ == State::CANCELLED || should_run_refcount_ == 0)
140 return false;
141
142 DCHECK(state_ != State::RESOLVED);
143 DCHECK(state_ != State::REJECTED);
144
145 // No need to wait if any dependency has been rejected.
146 if (state_ == State::DEPENDENCY_REJECTED)
147 return true;
148
149 switch (prerequisite_policy_) {
150 case PrerequisitePolicy::ALL:
151 for (const scoped_refptr<PromiseBase>& prerequisite : prerequisites_) {
152 if (prerequisite->state() != PromiseBase::State::RESOLVED) {
153 return false;
154 }
155 }
156 return true;
157
158 case PrerequisitePolicy::ANY:
159 DCHECK(!prerequisites_.empty());
160 for (const scoped_refptr<PromiseBase>& prerequisite : prerequisites_) {
161 if (prerequisite->state() == PromiseBase::State::RESOLVED) {
162 return true;
163 }
164 }
165 return false;
166
167 case PrerequisitePolicy::ALWAYS:
168 return true;
169
170 case PrerequisitePolicy::NEVER:
171 return false;
172 }
173
174 return false;
175 }
176
177 void PromiseBase::Cancel() {
178 DCHECK(dependants_.empty()) << "Canceling a task that others are waiting for "
179 "is unsupported and will leak memory.";
180
181 if (state_ == State::PENDING || state_ == State::PARTIALLY_RESOLVED)
182 SetThisAndPrerequisitesAsShouldRun(executor_, false);
183
184 state_ = State::CANCELLED;
185 }
186
187 void PromiseBase::MarkAsResolved() {
188 state_ = State::RESOLVED;
189
190 if (executor_)
191 executor_->OnPromiseResolved(this);
192 }
193
194 void PromiseBase::MarkAsRejected() {
195 state_ = State::REJECTED;
196
197 if (executor_)
198 executor_->OnPromiseRejected(this);
199 }
200
201 } // namespace internal
202 } // namespace promise
OLDNEW
« no previous file with comments | « components/scheduler/promises/promise.h ('k') | components/scheduler/promises/promise_executor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698