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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/base/work_queue.cc

Issue 2276353002: Remove after wakeup logic and replace PumpTask with Fences (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 3 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform/scheduler/base/work_queue.h" 5 #include "platform/scheduler/base/work_queue.h"
6 6
7 #include "platform/scheduler/base/work_queue_sets.h" 7 #include "platform/scheduler/base/work_queue_sets.h"
8 8
9 namespace blink { 9 namespace blink {
10 namespace scheduler { 10 namespace scheduler {
11 namespace internal { 11 namespace internal {
12 12
13 WorkQueue::WorkQueue(TaskQueueImpl* task_queue, 13 WorkQueue::WorkQueue(TaskQueueImpl* task_queue,
14 const char* name, 14 const char* name,
15 TaskQueueImpl::Task::ComparatorFn comparator) 15 TaskQueueImpl::Task::ComparatorFn comparator)
16 : work_queue_(comparator), 16 : work_queue_(comparator),
17 work_queue_sets_(nullptr), 17 work_queue_sets_(nullptr),
18 task_queue_(task_queue), 18 task_queue_(task_queue),
19 work_queue_set_index_(0), 19 work_queue_set_index_(0),
20 name_(name) {} 20 name_(name),
21 fence_(0),
22 fence_hit_(false) {}
21 23
22 void WorkQueue::AsValueInto(base::trace_event::TracedValue* state) const { 24 void WorkQueue::AsValueInto(base::trace_event::TracedValue* state) const {
23 for (const TaskQueueImpl::Task& task : work_queue_) { 25 for (const TaskQueueImpl::Task& task : work_queue_) {
24 TaskQueueImpl::TaskAsValueInto(task, state); 26 TaskQueueImpl::TaskAsValueInto(task, state);
25 } 27 }
26 } 28 }
27 29
28 WorkQueue::~WorkQueue() { 30 WorkQueue::~WorkQueue() {
29 DCHECK(!work_queue_sets_) << task_queue_->GetName() << " : " 31 DCHECK(!work_queue_sets_) << task_queue_->GetName() << " : "
30 << work_queue_sets_->name() << " : " << name_; 32 << work_queue_sets_->name() << " : " << name_;
31 } 33 }
32 34
33 const TaskQueueImpl::Task* WorkQueue::GetFrontTask() const { 35 const TaskQueueImpl::Task* WorkQueue::GetFrontTask() const {
34 if (work_queue_.empty()) 36 if (work_queue_.empty())
35 return nullptr; 37 return nullptr;
36 return &*work_queue_.begin(); 38 return &*work_queue_.begin();
37 } 39 }
38 40
41 const TaskQueueImpl::Task* WorkQueue::GetBackTask() const {
42 if (work_queue_.empty())
43 return nullptr;
44 return &*work_queue_.rbegin();
45 }
46
39 bool WorkQueue::GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const { 47 bool WorkQueue::GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const {
40 if (work_queue_.empty()) 48 if (work_queue_.empty() || fence_hit_)
41 return false; 49 return false;
42 // Quick sanity check. 50 // Quick sanity check.
43 DCHECK_LE(work_queue_.begin()->enqueue_order(), 51 DCHECK_LE(work_queue_.begin()->enqueue_order(),
44 work_queue_.rbegin()->enqueue_order()) 52 work_queue_.rbegin()->enqueue_order())
45 << task_queue_->GetName() << " : " 53 << task_queue_->GetName() << " : "
46 << work_queue_sets_->name() << " : " << name_; 54 << work_queue_sets_->name() << " : " << name_;
47 *enqueue_order = work_queue_.begin()->enqueue_order(); 55 *enqueue_order = work_queue_.begin()->enqueue_order();
48 return true; 56 return true;
49 } 57 }
50 58
51 void WorkQueue::Push(TaskQueueImpl::Task task) { 59 void WorkQueue::Push(TaskQueueImpl::Task task) {
52 bool was_empty = work_queue_.empty(); 60 bool was_empty = work_queue_.empty();
53 #ifndef NDEBUG 61 #ifndef NDEBUG
54 DCHECK(task.enqueue_order_set()); 62 DCHECK(task.enqueue_order_set());
55 #endif 63 #endif
56 64
57 // We expect |task| to be inserted at the end. Amoritized O(1). 65 // We expect |task| to be inserted at the end. Amoritized O(1).
58 work_queue_.insert(work_queue_.end(), std::move(task)); 66 work_queue_.insert(work_queue_.end(), std::move(task));
59 DCHECK_EQ(task.enqueue_order(), work_queue_.rbegin()->enqueue_order()) 67 DCHECK_EQ(task.enqueue_order(), work_queue_.rbegin()->enqueue_order())
60 << task_queue_->GetName() << " : " 68 << task_queue_->GetName() << " : "
61 << work_queue_sets_->name() << " : " << name_ 69 << work_queue_sets_->name() << " : " << name_
62 << "task [scheduled_run_time_" << task.delayed_run_time << ", " 70 << "task [scheduled_run_time_" << task.delayed_run_time << ", "
63 << task.sequence_num << 71 << task.sequence_num <<
64 "] rbegin() [" << work_queue_.rbegin()->delayed_run_time << ", " 72 "] rbegin() [" << work_queue_.rbegin()->delayed_run_time << ", "
65 << work_queue_.rbegin()->sequence_num << "]"; 73 << work_queue_.rbegin()->sequence_num << "]";
66 74
67 if (was_empty && work_queue_sets_) { 75 if (was_empty && work_queue_sets_ && !fence_hit_) {
68 work_queue_sets_->OnPushQueue(this); 76 work_queue_sets_->OnPushQueue(this);
69 } 77 }
70 } 78 }
71 79
72 bool WorkQueue::CancelTask(const TaskQueueImpl::Task& key) { 80 bool WorkQueue::CancelTask(const TaskQueueImpl::Task& key) {
73 TaskQueueImpl::ComparatorQueue::iterator it = work_queue_.find(key); 81 TaskQueueImpl::ComparatorQueue::iterator it = work_queue_.find(key);
74 if (it == work_queue_.end()) 82 if (it == work_queue_.end())
75 return false; 83 return false;
76 84
77 if (it == work_queue_.begin()) { 85 if (it == work_queue_.begin()) {
78 EnqueueOrder erased_task_enqueue_order = it->enqueue_order(); 86 EnqueueOrder erased_task_enqueue_order = it->enqueue_order();
79 work_queue_.erase(it); 87 work_queue_.erase(it);
80 // We can't guarantee this WorkQueue is the lowest value in the WorkQueueSet 88 // We can't guarantee this WorkQueue is the lowest value in the WorkQueueSet
81 // so we need to use OnQueueHeadChanged instead of OnPopQueue for 89 // so we need to use OnQueueHeadChanged instead of OnPopQueue for
82 // correctness. 90 // correctness.
83 work_queue_sets_->OnQueueHeadChanged(this, erased_task_enqueue_order); 91 if (!fence_hit_)
92 work_queue_sets_->OnQueueHeadChanged(this, erased_task_enqueue_order);
84 } else { 93 } else {
85 work_queue_.erase(it); 94 work_queue_.erase(it);
86 } 95 }
87 task_queue_->TraceQueueSize(false); 96 task_queue_->TraceQueueSize(false);
88 return true; 97 return true;
89 } 98 }
90 99
91 bool WorkQueue::IsTaskPending(const TaskQueueImpl::Task& key) const { 100 bool WorkQueue::IsTaskPending(const TaskQueueImpl::Task& key) const {
92 return work_queue_.find(key) != work_queue_.end(); 101 return work_queue_.find(key) != work_queue_.end();
93 } 102 }
94 103
95 void WorkQueue::PopTaskForTest() { 104 void WorkQueue::PopTaskForTest() {
96 if (work_queue_.empty()) 105 if (work_queue_.empty())
97 return; 106 return;
98 work_queue_.erase(work_queue_.begin()); 107 work_queue_.erase(work_queue_.begin());
99 } 108 }
100 109
101 void WorkQueue::SwapLocked(TaskQueueImpl::ComparatorQueue& incoming_queue) { 110 void WorkQueue::SwapLocked(TaskQueueImpl::ComparatorQueue& incoming_queue) {
102 DCHECK(work_queue_.empty()); 111 DCHECK(work_queue_.empty());
103 std::swap(work_queue_, incoming_queue); 112 std::swap(work_queue_, incoming_queue);
104 if (!work_queue_.empty() && work_queue_sets_) 113 if (!work_queue_.empty() && work_queue_sets_ && !fence_hit_)
105 work_queue_sets_->OnPushQueue(this); 114 work_queue_sets_->OnPushQueue(this);
106 task_queue_->TraceQueueSize(true);
Sami 2016/08/26 14:37:02 Did you mean to remove this?
alex clarke (OOO till 29th) 2016/08/26 16:33:14 Yes it's not useful to call it here since Swap doe
107 } 115 }
108 116
109 TaskQueueImpl::Task WorkQueue::TakeTaskFromWorkQueue() { 117 TaskQueueImpl::Task WorkQueue::TakeTaskFromWorkQueue() {
110 DCHECK(work_queue_sets_); 118 DCHECK(work_queue_sets_);
111 DCHECK(!work_queue_.empty()); 119 DCHECK(!work_queue_.empty());
112 TaskQueueImpl::ComparatorQueue::iterator it = work_queue_.begin(); 120 TaskQueueImpl::ComparatorQueue::iterator it = work_queue_.begin();
113 TaskQueueImpl::Task pending_task = 121 TaskQueueImpl::Task pending_task =
114 std::move(const_cast<TaskQueueImpl::Task&>(*it)); 122 std::move(const_cast<TaskQueueImpl::Task&>(*it));
115 work_queue_.erase(it); 123 work_queue_.erase(it);
124 // If we hit the fence, pretend to WorkQueueSets that we're empty until the
125 // fence is removed.
126 if (fence_ && pending_task.enqueue_order() >= fence_)
127 fence_hit_ = true;
116 work_queue_sets_->OnPopQueue(this); 128 work_queue_sets_->OnPopQueue(this);
117 task_queue_->TraceQueueSize(false); 129 task_queue_->TraceQueueSize(false);
118 return pending_task; 130 return pending_task;
119 } 131 }
120 132
121 void WorkQueue::AssignToWorkQueueSets(WorkQueueSets* work_queue_sets) { 133 void WorkQueue::AssignToWorkQueueSets(WorkQueueSets* work_queue_sets) {
122 work_queue_sets_ = work_queue_sets; 134 work_queue_sets_ = work_queue_sets;
123 } 135 }
124 136
125 void WorkQueue::AssignSetIndex(size_t work_queue_set_index) { 137 void WorkQueue::AssignSetIndex(size_t work_queue_set_index) {
126 work_queue_set_index_ = work_queue_set_index; 138 work_queue_set_index_ = work_queue_set_index;
127 } 139 }
128 140
141 bool WorkQueue::InsertFence(EnqueueOrder fence) {
142 bool task_unblocked = false;
143 if (fence) {
144 DCHECK_GE(fence, fence_);
145 if (fence > fence_)
146 task_unblocked = RemoveFence();
147 } else {
148 DCHECK(work_queue_.empty());
149 // Until the fence is removed we should pretend to remain empty even after a
150 // push or a swap.
151 fence_hit_ = true;
152 }
153
154 fence_ = fence;
155 return task_unblocked;
156 }
157
158 bool WorkQueue::RemoveFence() {
159 fence_ = 0;
160 bool fence_was_hit = fence_hit_;
161 fence_hit_ = false;
162 if (work_queue_sets_ && fence_was_hit && !work_queue_.empty()) {
163 work_queue_sets_->OnPushQueue(this);
164 return true;
165 }
166 return false;
167 }
168
129 bool WorkQueue::ShouldRunBefore(const WorkQueue* other_queue) const { 169 bool WorkQueue::ShouldRunBefore(const WorkQueue* other_queue) const {
130 DCHECK(!work_queue_.empty()); 170 DCHECK(!work_queue_.empty());
131 DCHECK(!other_queue->work_queue_.empty()); 171 DCHECK(!other_queue->work_queue_.empty());
132 EnqueueOrder enqueue_order = 0; 172 EnqueueOrder enqueue_order = 0;
133 EnqueueOrder other_enqueue_order = 0; 173 EnqueueOrder other_enqueue_order = 0;
134 bool have_task = GetFrontTaskEnqueueOrder(&enqueue_order); 174 bool have_task = GetFrontTaskEnqueueOrder(&enqueue_order);
135 bool have_other_task = 175 bool have_other_task =
136 other_queue->GetFrontTaskEnqueueOrder(&other_enqueue_order); 176 other_queue->GetFrontTaskEnqueueOrder(&other_enqueue_order);
137 DCHECK(have_task); 177 DCHECK(have_task);
138 DCHECK(have_other_task); 178 DCHECK(have_other_task);
139 return enqueue_order < other_enqueue_order; 179 return enqueue_order < other_enqueue_order;
140 } 180 }
141 181
142 } // namespace internal 182 } // namespace internal
143 } // namespace scheduler 183 } // namespace scheduler
144 } // namespace blink 184 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698