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

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

Issue 2319053004: [Reland] Make canceling Timers fast. (Closed)
Patch Set: Getting printf to work with size_t cross platform is too hard, use C++ io streams instead 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, const char* name)
14 const char* name, 14 : work_queue_sets_(nullptr),
15 TaskQueueImpl::Task::ComparatorFn comparator)
16 : work_queue_(comparator),
17 work_queue_sets_(nullptr),
18 task_queue_(task_queue), 15 task_queue_(task_queue),
19 work_queue_set_index_(0), 16 work_queue_set_index_(0),
20 name_(name), 17 name_(name),
21 fence_(0) {} 18 fence_(0) {}
22 19
23 void WorkQueue::AsValueInto(base::trace_event::TracedValue* state) const { 20 void WorkQueue::AsValueInto(base::trace_event::TracedValue* state) const {
24 for (const TaskQueueImpl::Task& task : work_queue_) { 21 /*for (const TaskQueueImpl::Task& task : work_queue_) {
25 TaskQueueImpl::TaskAsValueInto(task, state); 22 TaskQueueImpl::TaskAsValueInto(task, state);
26 } 23 }*/
haraken 2016/09/09 02:34:07 Can we remove this code?
alex clarke (OOO till 29th) 2016/09/09 09:40:59 Ah I forgot about that. I've restored the origina
27 } 24 }
28 25
29 WorkQueue::~WorkQueue() { 26 WorkQueue::~WorkQueue() {
30 DCHECK(!work_queue_sets_) << task_queue_->GetName() << " : " 27 DCHECK(!work_queue_sets_) << task_queue_->GetName() << " : "
31 << work_queue_sets_->name() << " : " << name_; 28 << work_queue_sets_->name() << " : " << name_;
32 } 29 }
33 30
34 const TaskQueueImpl::Task* WorkQueue::GetFrontTask() const { 31 const TaskQueueImpl::Task* WorkQueue::GetFrontTask() const {
35 if (work_queue_.empty()) 32 if (work_queue_.empty())
36 return nullptr; 33 return nullptr;
37 return &*work_queue_.begin(); 34 return &work_queue_.front();
38 } 35 }
39 36
40 const TaskQueueImpl::Task* WorkQueue::GetBackTask() const { 37 const TaskQueueImpl::Task* WorkQueue::GetBackTask() const {
41 if (work_queue_.empty()) 38 if (work_queue_.empty())
42 return nullptr; 39 return nullptr;
43 return &*work_queue_.rbegin(); 40 return &work_queue_.back();
44 } 41 }
45 42
46 bool WorkQueue::BlockedByFence() const { 43 bool WorkQueue::BlockedByFence() const {
47 if (!fence_) 44 if (!fence_)
48 return false; 45 return false;
49 46
50 // If the queue is empty then any future tasks will have a higher enqueue 47 // 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 48 // order and will be blocked. The queue is also blocked if the head is past
52 // the fence. 49 // the fence.
53 return work_queue_.empty() || work_queue_.begin()->enqueue_order() > fence_; 50 return work_queue_.empty() || work_queue_.front().enqueue_order() > fence_;
54 } 51 }
55 52
56 bool WorkQueue::GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const { 53 bool WorkQueue::GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const {
57 if (work_queue_.empty() || BlockedByFence()) 54 if (work_queue_.empty() || BlockedByFence())
58 return false; 55 return false;
59 // Quick sanity check. 56 // Quick sanity check.
60 DCHECK_LE(work_queue_.begin()->enqueue_order(), 57 DCHECK_LE(work_queue_.front().enqueue_order(),
61 work_queue_.rbegin()->enqueue_order()) 58 work_queue_.back().enqueue_order())
62 << task_queue_->GetName() << " : " 59 << task_queue_->GetName() << " : " << work_queue_sets_->name() << " : "
63 << work_queue_sets_->name() << " : " << name_; 60 << name_;
64 *enqueue_order = work_queue_.begin()->enqueue_order(); 61 *enqueue_order = work_queue_.front().enqueue_order();
65 return true; 62 return true;
66 } 63 }
67 64
68 void WorkQueue::Push(TaskQueueImpl::Task task) { 65 void WorkQueue::Push(TaskQueueImpl::Task task) {
69 bool was_empty = work_queue_.empty(); 66 bool was_empty = work_queue_.empty();
70 #ifndef NDEBUG 67 #ifndef NDEBUG
71 DCHECK(task.enqueue_order_set()); 68 DCHECK(task.enqueue_order_set());
72 #endif 69 #endif
73 70
74 // We expect |task| to be inserted at the end. Amoritized O(1). 71 // Amoritized O(1).
75 work_queue_.insert(work_queue_.end(), std::move(task)); 72 work_queue_.push(std::move(task));
76 DCHECK_EQ(task.enqueue_order(), work_queue_.rbegin()->enqueue_order())
77 << task_queue_->GetName() << " : "
78 << work_queue_sets_->name() << " : " << name_
79 << "task [scheduled_run_time_" << task.delayed_run_time << ", "
80 << task.sequence_num <<
81 "] rbegin() [" << work_queue_.rbegin()->delayed_run_time << ", "
82 << work_queue_.rbegin()->sequence_num << "]";
83 73
84 if (!was_empty) 74 if (!was_empty)
85 return; 75 return;
86 76
87 // If we hit the fence, pretend to WorkQueueSets that we're empty. 77 // If we hit the fence, pretend to WorkQueueSets that we're empty.
88 if (work_queue_sets_ && !BlockedByFence()) 78 if (work_queue_sets_ && !BlockedByFence())
89 work_queue_sets_->OnPushQueue(this); 79 work_queue_sets_->OnPushQueue(this);
90 } 80 }
91 81
92 bool WorkQueue::CancelTask(const TaskQueueImpl::Task& key) {
93 TaskQueueImpl::ComparatorQueue::iterator it = work_queue_.find(key);
94 if (it == work_queue_.end())
95 return false;
96
97 if (it == work_queue_.begin()) {
98 EnqueueOrder erased_task_enqueue_order = it->enqueue_order();
99 work_queue_.erase(it);
100 // We can't guarantee this WorkQueue is the lowest value in the WorkQueueSet
101 // so we need to use OnQueueHeadChanged instead of OnPopQueue for
102 // correctness.
103 if (!BlockedByFence())
104 work_queue_sets_->OnQueueHeadChanged(this, erased_task_enqueue_order);
105 } else {
106 work_queue_.erase(it);
107 }
108 task_queue_->TraceQueueSize(false);
109 return true;
110 }
111
112 bool WorkQueue::IsTaskPending(const TaskQueueImpl::Task& key) const {
113 return work_queue_.find(key) != work_queue_.end();
114 }
115
116 void WorkQueue::PopTaskForTest() { 82 void WorkQueue::PopTaskForTest() {
117 if (work_queue_.empty()) 83 if (work_queue_.empty())
118 return; 84 return;
119 work_queue_.erase(work_queue_.begin()); 85 work_queue_.pop();
120 } 86 }
121 87
122 void WorkQueue::SwapLocked(TaskQueueImpl::ComparatorQueue& incoming_queue) { 88 void WorkQueue::SwapLocked(std::queue<TaskQueueImpl::Task>& incoming_queue) {
123 DCHECK(work_queue_.empty()); 89 DCHECK(work_queue_.empty());
124 std::swap(work_queue_, incoming_queue); 90 std::swap(work_queue_, incoming_queue);
125 if (work_queue_.empty()) 91 if (work_queue_.empty())
126 return; 92 return;
127 // If we hit the fence, pretend to WorkQueueSets that we're empty. 93 // If we hit the fence, pretend to WorkQueueSets that we're empty.
128 if (work_queue_sets_ && !BlockedByFence()) 94 if (work_queue_sets_ && !BlockedByFence())
129 work_queue_sets_->OnPushQueue(this); 95 work_queue_sets_->OnPushQueue(this);
130 } 96 }
131 97
132 TaskQueueImpl::Task WorkQueue::TakeTaskFromWorkQueue() { 98 TaskQueueImpl::Task WorkQueue::TakeTaskFromWorkQueue() {
133 DCHECK(work_queue_sets_); 99 DCHECK(work_queue_sets_);
134 DCHECK(!work_queue_.empty()); 100 DCHECK(!work_queue_.empty());
135 TaskQueueImpl::ComparatorQueue::iterator it = work_queue_.begin(); 101
102 // Skip over canceled tasks, except for the last one since we always return
103 // something.
104 while (work_queue_.size() > 1u && work_queue_.front().task.IsCancelled()) {
105 work_queue_.pop();
106 }
107
136 TaskQueueImpl::Task pending_task = 108 TaskQueueImpl::Task pending_task =
137 std::move(const_cast<TaskQueueImpl::Task&>(*it)); 109 std::move(const_cast<TaskQueueImpl::Task&>(work_queue_.front()));
138 work_queue_.erase(it); 110 work_queue_.pop();
139 work_queue_sets_->OnPopQueue(this); 111 work_queue_sets_->OnPopQueue(this);
140 task_queue_->TraceQueueSize(false); 112 task_queue_->TraceQueueSize(false);
141 return pending_task; 113 return pending_task;
142 } 114 }
143 115
144 void WorkQueue::AssignToWorkQueueSets(WorkQueueSets* work_queue_sets) { 116 void WorkQueue::AssignToWorkQueueSets(WorkQueueSets* work_queue_sets) {
145 work_queue_sets_ = work_queue_sets; 117 work_queue_sets_ = work_queue_sets;
146 } 118 }
147 119
148 void WorkQueue::AssignSetIndex(size_t work_queue_set_index) { 120 void WorkQueue::AssignSetIndex(size_t work_queue_set_index) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 bool have_other_task = 154 bool have_other_task =
183 other_queue->GetFrontTaskEnqueueOrder(&other_enqueue_order); 155 other_queue->GetFrontTaskEnqueueOrder(&other_enqueue_order);
184 DCHECK(have_task); 156 DCHECK(have_task);
185 DCHECK(have_other_task); 157 DCHECK(have_other_task);
186 return enqueue_order < other_enqueue_order; 158 return enqueue_order < other_enqueue_order;
187 } 159 }
188 160
189 } // namespace internal 161 } // namespace internal
190 } // namespace scheduler 162 } // namespace scheduler
191 } // namespace blink 163 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698