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

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

Issue 2786083005: scheduler: Maintain a constant enqueue order for every task (Closed)
Patch Set: Update VirtualTimeTest Created 3 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
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 {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 return &work_queue_.back(); 43 return &work_queue_.back();
44 } 44 }
45 45
46 bool WorkQueue::BlockedByFence() const { 46 bool WorkQueue::BlockedByFence() const {
47 if (!fence_) 47 if (!fence_)
48 return false; 48 return false;
49 49
50 // If the queue is empty then any future tasks will have a higher enqueue 50 // If the queue is empty then any future tasks will have a higher enqueue
51 // order and will be blocked. The queue is also blocked if the head is past 51 // order and will be blocked. The queue is also blocked if the head is past
52 // the fence. 52 // the fence.
53 return work_queue_.empty() || work_queue_.front().enqueue_order() > fence_; 53 return work_queue_.empty() ||
54 work_queue_.front().enqueue_order().sequence_num > fence_;
54 } 55 }
55 56
56 bool WorkQueue::GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const { 57 bool WorkQueue::GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const {
57 if (work_queue_.empty() || BlockedByFence()) 58 if (work_queue_.empty() || BlockedByFence())
58 return false; 59 return false;
59 // Quick sanity check. 60 // Quick sanity check.
60 DCHECK_LE(work_queue_.front().enqueue_order(), 61 DCHECK_LE(work_queue_.front().enqueue_order(),
61 work_queue_.back().enqueue_order()) 62 work_queue_.back().enqueue_order())
62 << task_queue_->GetName() << " : " << work_queue_sets_->GetName() << " : " 63 << task_queue_->GetName() << " : " << work_queue_sets_->GetName() << " : "
63 << name_; 64 << name_;
64 *enqueue_order = work_queue_.front().enqueue_order(); 65 *enqueue_order = work_queue_.front().enqueue_order();
65 return true; 66 return true;
66 } 67 }
67 68
68 void WorkQueue::Push(TaskQueueImpl::Task task) { 69 void WorkQueue::Push(TaskQueueImpl::Task task) {
69 bool was_empty = work_queue_.empty(); 70 bool was_empty = work_queue_.empty();
70 #ifndef NDEBUG
71 DCHECK(task.enqueue_order_set());
72 #endif
73 71
74 // Amoritized O(1). 72 // Amoritized O(1).
75 work_queue_.push_back(std::move(task)); 73 work_queue_.push_back(std::move(task));
76 74
77 if (!was_empty) 75 if (!was_empty)
78 return; 76 return;
79 77
80 // If we hit the fence, pretend to WorkQueueSets that we're empty. 78 // If we hit the fence, pretend to WorkQueueSets that we're empty.
81 if (work_queue_sets_ && !BlockedByFence()) 79 if (work_queue_sets_ && !BlockedByFence())
82 work_queue_sets_->OnTaskPushedToEmptyQueue(this); 80 work_queue_sets_->OnTaskPushedToEmptyQueue(this);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 } 122 }
125 123
126 void WorkQueue::AssignToWorkQueueSets(WorkQueueSets* work_queue_sets) { 124 void WorkQueue::AssignToWorkQueueSets(WorkQueueSets* work_queue_sets) {
127 work_queue_sets_ = work_queue_sets; 125 work_queue_sets_ = work_queue_sets;
128 } 126 }
129 127
130 void WorkQueue::AssignSetIndex(size_t work_queue_set_index) { 128 void WorkQueue::AssignSetIndex(size_t work_queue_set_index) {
131 work_queue_set_index_ = work_queue_set_index; 129 work_queue_set_index_ = work_queue_set_index;
132 } 130 }
133 131
134 bool WorkQueue::InsertFence(EnqueueOrder fence) { 132 bool WorkQueue::InsertFence(uint64_t fence) {
135 DCHECK_NE(fence, 0u); 133 DCHECK_NE(fence, 0u);
136 DCHECK(fence >= fence_ || fence == 1u); 134 DCHECK(fence >= fence_ ||
135 fence == static_cast<uint64_t>(
136 EnqueueOrderSequenceNumberValues::BLOCKING_FENCE));
137 bool was_blocked_by_fence = BlockedByFence(); 137 bool was_blocked_by_fence = BlockedByFence();
138 fence_ = fence; 138 fence_ = fence;
139 // Moving the fence forward may unblock some tasks. 139 // Moving the fence forward may unblock some tasks.
140 if (work_queue_sets_ && !work_queue_.empty() && was_blocked_by_fence && 140 if (work_queue_sets_ && !work_queue_.empty() && was_blocked_by_fence &&
141 !BlockedByFence()) { 141 !BlockedByFence()) {
142 work_queue_sets_->OnTaskPushedToEmptyQueue(this); 142 work_queue_sets_->OnTaskPushedToEmptyQueue(this);
143 return true; 143 return true;
144 } 144 }
145 // Fence insertion may have blocked all tasks in this work queue. 145 // Fence insertion may have blocked all tasks in this work queue.
146 if (BlockedByFence()) 146 if (BlockedByFence())
147 work_queue_sets_->OnQueueBlocked(this); 147 work_queue_sets_->OnQueueBlocked(this);
148 return false; 148 return false;
149 } 149 }
150 150
151 bool WorkQueue::RemoveFence() { 151 bool WorkQueue::RemoveFence() {
152 bool was_blocked_by_fence = BlockedByFence(); 152 bool was_blocked_by_fence = BlockedByFence();
153 fence_ = 0; 153 fence_ = 0;
154 if (work_queue_sets_ && !work_queue_.empty() && was_blocked_by_fence) { 154 if (work_queue_sets_ && !work_queue_.empty() && was_blocked_by_fence) {
155 work_queue_sets_->OnTaskPushedToEmptyQueue(this); 155 work_queue_sets_->OnTaskPushedToEmptyQueue(this);
156 return true; 156 return true;
157 } 157 }
158 return false; 158 return false;
159 } 159 }
160 160
161 bool WorkQueue::ShouldRunBefore(const WorkQueue* other_queue) const { 161 bool WorkQueue::ShouldRunBefore(const WorkQueue* other_queue) const {
162 DCHECK(!work_queue_.empty()); 162 DCHECK(!work_queue_.empty());
163 DCHECK(!other_queue->work_queue_.empty()); 163 DCHECK(!other_queue->work_queue_.empty());
164 EnqueueOrder enqueue_order = 0; 164 EnqueueOrder enqueue_order = {base::TimeTicks(), 0};
alex clarke (OOO till 29th) 2017/04/13 07:46:00 Can we have a default constructor?
Sami 2017/04/18 10:47:49 Done.
165 EnqueueOrder other_enqueue_order = 0; 165 EnqueueOrder other_enqueue_order = {base::TimeTicks(), 0};
166 bool have_task = GetFrontTaskEnqueueOrder(&enqueue_order); 166 bool have_task = GetFrontTaskEnqueueOrder(&enqueue_order);
167 bool have_other_task = 167 bool have_other_task =
168 other_queue->GetFrontTaskEnqueueOrder(&other_enqueue_order); 168 other_queue->GetFrontTaskEnqueueOrder(&other_enqueue_order);
169 DCHECK(have_task); 169 DCHECK(have_task);
170 DCHECK(have_other_task); 170 DCHECK(have_other_task);
171 return enqueue_order < other_enqueue_order; 171 return enqueue_order < other_enqueue_order;
172 } 172 }
173 173
174 } // namespace internal 174 } // namespace internal
175 } // namespace scheduler 175 } // namespace scheduler
176 } // namespace blink 176 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698