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

Side by Side Diff: components/scheduler/base/time_domain.cc

Issue 2118903002: scheduler: Move the Blink scheduler into Blink (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 4 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 2015 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/base/time_domain.h"
6
7 #include <set>
8
9 #include "components/scheduler/base/task_queue_impl.h"
10 #include "components/scheduler/base/task_queue_manager_delegate.h"
11 #include "components/scheduler/base/work_queue.h"
12 #include "components/scheduler/scheduler_export.h"
13
14 namespace scheduler {
15
16 TimeDomain::TimeDomain(Observer* observer) : observer_(observer) {}
17
18 TimeDomain::~TimeDomain() {
19 DCHECK(main_thread_checker_.CalledOnValidThread());
20 }
21
22 void TimeDomain::RegisterQueue(internal::TaskQueueImpl* queue) {
23 DCHECK(main_thread_checker_.CalledOnValidThread());
24 DCHECK_EQ(queue->GetTimeDomain(), this);
25 }
26
27 void TimeDomain::UnregisterQueue(internal::TaskQueueImpl* queue) {
28 DCHECK(main_thread_checker_.CalledOnValidThread());
29 DCHECK_EQ(queue->GetTimeDomain(), this);
30 UnregisterAsUpdatableTaskQueue(queue);
31
32 // We need to remove |task_queue| from delayed_wakeup_multimap_ which is a
33 // little awkward since it's keyed by time. O(n) running time.
34 for (DelayedWakeupMultimap::iterator iter = delayed_wakeup_multimap_.begin();
35 iter != delayed_wakeup_multimap_.end();) {
36 if (iter->second == queue) {
37 // O(1) amortized.
38 iter = delayed_wakeup_multimap_.erase(iter);
39 } else {
40 iter++;
41 }
42 }
43 }
44
45 void TimeDomain::MigrateQueue(internal::TaskQueueImpl* queue,
46 TimeDomain* destination_time_domain) {
47 DCHECK(main_thread_checker_.CalledOnValidThread());
48 DCHECK_EQ(queue->GetTimeDomain(), this);
49 DCHECK(destination_time_domain);
50
51 // Make sure we remember to update |queue| if it's got incoming immediate
52 // work.
53 if (UnregisterAsUpdatableTaskQueue(queue))
54 destination_time_domain->updatable_queue_set_.insert(queue);
55
56 base::TimeTicks destination_now = destination_time_domain->Now();
57 // We need to remove |task_queue| from delayed_wakeup_multimap_ which is a
58 // little awkward since it's keyed by time. O(n) running time.
59 for (DelayedWakeupMultimap::iterator iter = delayed_wakeup_multimap_.begin();
60 iter != delayed_wakeup_multimap_.end();) {
61 if (iter->second == queue) {
62 destination_time_domain->ScheduleDelayedWork(queue, iter->first,
63 destination_now);
64 // O(1) amortized.
65 iter = delayed_wakeup_multimap_.erase(iter);
66 } else {
67 iter++;
68 }
69 }
70 }
71
72 void TimeDomain::ScheduleDelayedWork(internal::TaskQueueImpl* queue,
73 base::TimeTicks delayed_run_time,
74 base::TimeTicks now) {
75 DCHECK(main_thread_checker_.CalledOnValidThread());
76 if (delayed_wakeup_multimap_.empty() ||
77 delayed_run_time < delayed_wakeup_multimap_.begin()->first) {
78 base::TimeDelta delay = std::max(base::TimeDelta(), delayed_run_time - now);
79 RequestWakeup(now, delay);
80 }
81
82 delayed_wakeup_multimap_.insert(std::make_pair(delayed_run_time, queue));
83 if (observer_)
84 observer_->OnTimeDomainHasDelayedWork();
85 }
86
87 void TimeDomain::RegisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue) {
88 {
89 base::AutoLock lock(newly_updatable_lock_);
90 newly_updatable_.push_back(queue);
91 }
92 if (observer_)
93 observer_->OnTimeDomainHasImmediateWork();
94 }
95
96 bool TimeDomain::UnregisterAsUpdatableTaskQueue(
97 internal::TaskQueueImpl* queue) {
98 DCHECK(main_thread_checker_.CalledOnValidThread());
99
100 bool was_updatable = updatable_queue_set_.erase(queue) != 0;
101
102 base::AutoLock lock(newly_updatable_lock_);
103 // Remove all copies of |queue| from |newly_updatable_|.
104 for (size_t i = 0; i < newly_updatable_.size();) {
105 if (newly_updatable_[i] == queue) {
106 // Move last element into slot #i and then compact.
107 newly_updatable_[i] = newly_updatable_.back();
108 newly_updatable_.pop_back();
109 was_updatable = true;
110 } else {
111 i++;
112 }
113 }
114 return was_updatable;
115 }
116
117 void TimeDomain::UpdateWorkQueues(
118 bool should_trigger_wakeup,
119 const internal::TaskQueueImpl::Task* previous_task,
120 LazyNow lazy_now) {
121 DCHECK(main_thread_checker_.CalledOnValidThread());
122
123 // Move any ready delayed tasks into the Incoming queues.
124 WakeupReadyDelayedQueues(&lazy_now, should_trigger_wakeup, previous_task);
125
126 MoveNewlyUpdatableQueuesIntoUpdatableQueueSet();
127
128 auto iter = updatable_queue_set_.begin();
129 while (iter != updatable_queue_set_.end()) {
130 internal::TaskQueueImpl* queue = *iter++;
131 // NOTE Update work queue may erase itself from |updatable_queue_set_|.
132 // This is fine, erasing an element won't invalidate any interator, as long
133 // as the iterator isn't the element being delated.
134 if (queue->immediate_work_queue()->Empty())
135 queue->UpdateImmediateWorkQueue(should_trigger_wakeup, previous_task);
136 }
137 }
138
139 void TimeDomain::MoveNewlyUpdatableQueuesIntoUpdatableQueueSet() {
140 DCHECK(main_thread_checker_.CalledOnValidThread());
141 base::AutoLock lock(newly_updatable_lock_);
142 while (!newly_updatable_.empty()) {
143 updatable_queue_set_.insert(newly_updatable_.back());
144 newly_updatable_.pop_back();
145 }
146 }
147
148 void TimeDomain::WakeupReadyDelayedQueues(
149 LazyNow* lazy_now,
150 bool should_trigger_wakeup,
151 const internal::TaskQueueImpl::Task* previous_task) {
152 DCHECK(main_thread_checker_.CalledOnValidThread());
153 // Wake up any queues with pending delayed work. Note std::multipmap stores
154 // the elements sorted by key, so the begin() iterator points to the earliest
155 // queue to wakeup.
156 std::set<internal::TaskQueueImpl*> dedup_set;
157 while (!delayed_wakeup_multimap_.empty()) {
158 DelayedWakeupMultimap::iterator next_wakeup =
159 delayed_wakeup_multimap_.begin();
160 if (next_wakeup->first > lazy_now->Now())
161 break;
162 // A queue could have any number of delayed tasks pending so it's worthwhile
163 // deduping calls to UpdateDelayedWorkQueue since it takes a lock.
164 // NOTE the order in which these are called matters since the order
165 // in which EnqueueTaskLocks is called is respected when choosing which
166 // queue to execute a task from.
167 if (dedup_set.insert(next_wakeup->second).second) {
168 next_wakeup->second->UpdateDelayedWorkQueue(
169 lazy_now, should_trigger_wakeup, previous_task);
170 }
171 delayed_wakeup_multimap_.erase(next_wakeup);
172 }
173 }
174
175 void TimeDomain::ClearExpiredWakeups() {
176 DCHECK(main_thread_checker_.CalledOnValidThread());
177 LazyNow lazy_now(CreateLazyNow());
178 while (!delayed_wakeup_multimap_.empty()) {
179 DelayedWakeupMultimap::iterator next_wakeup =
180 delayed_wakeup_multimap_.begin();
181 if (next_wakeup->first > lazy_now.Now())
182 break;
183 delayed_wakeup_multimap_.erase(next_wakeup);
184 }
185 }
186
187 bool TimeDomain::NextScheduledRunTime(base::TimeTicks* out_time) const {
188 DCHECK(main_thread_checker_.CalledOnValidThread());
189 if (delayed_wakeup_multimap_.empty())
190 return false;
191
192 *out_time = delayed_wakeup_multimap_.begin()->first;
193 return true;
194 }
195
196 bool TimeDomain::NextScheduledTaskQueue(TaskQueue** out_task_queue) const {
197 DCHECK(main_thread_checker_.CalledOnValidThread());
198 if (delayed_wakeup_multimap_.empty())
199 return false;
200
201 *out_task_queue = delayed_wakeup_multimap_.begin()->second;
202 return true;
203 }
204
205 void TimeDomain::AsValueInto(base::trace_event::TracedValue* state) const {
206 state->BeginDictionary();
207 state->SetString("name", GetName());
208 state->BeginArray("updatable_queue_set");
209 for (auto* queue : updatable_queue_set_)
210 state->AppendString(queue->GetName());
211 state->EndArray();
212 state->SetInteger("registered_delay_count", delayed_wakeup_multimap_.size());
213 if (!delayed_wakeup_multimap_.empty()) {
214 base::TimeDelta delay = delayed_wakeup_multimap_.begin()->first - Now();
215 state->SetDouble("next_delay_ms", delay.InMillisecondsF());
216 }
217 AsValueIntoInternal(state);
218 state->EndDictionary();
219 }
220
221 } // namespace scheduler
OLDNEW
« no previous file with comments | « components/scheduler/base/time_domain.h ('k') | components/scheduler/base/time_domain_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698