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

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

Issue 2258713004: Make tasks cancellable inside the blink scheduler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Various comment nits addressed 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
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, const char* name) 13 WorkQueue::WorkQueue(TaskQueueImpl* task_queue,
14 : work_queue_sets_(nullptr), 14 const char* name,
15 TaskQueueImpl::Task::ComparatorFn comparator)
16 : work_queue_(comparator),
17 work_queue_sets_(nullptr),
15 task_queue_(task_queue), 18 task_queue_(task_queue),
16 work_queue_set_index_(0), 19 work_queue_set_index_(0),
17 name_(name) {} 20 name_(name) {}
18 21
19 void WorkQueue::AsValueInto(base::trace_event::TracedValue* state) const { 22 void WorkQueue::AsValueInto(base::trace_event::TracedValue* state) const {
20 // Remove const to search |work_queue_| in the destructive manner. Restore the 23 for (const TaskQueueImpl::Task& task : work_queue_) {
21 // content from |visited| later. 24 TaskQueueImpl::TaskAsValueInto(task, state);
22 std::queue<TaskQueueImpl::Task>* mutable_queue =
23 const_cast<std::queue<TaskQueueImpl::Task>*>(&work_queue_);
24 std::queue<TaskQueueImpl::Task> visited;
25 while (!mutable_queue->empty()) {
26 TaskQueueImpl::TaskAsValueInto(mutable_queue->front(), state);
27 visited.push(std::move(mutable_queue->front()));
28 mutable_queue->pop();
29 } 25 }
30 *mutable_queue = std::move(visited);
31 } 26 }
32 27
33 WorkQueue::~WorkQueue() { 28 WorkQueue::~WorkQueue() {
34 DCHECK(!work_queue_sets_) << task_queue_->GetName() << " : " 29 DCHECK(!work_queue_sets_) << task_queue_->GetName() << " : "
35 << work_queue_sets_->name() << " : " << name_; 30 << work_queue_sets_->name() << " : " << name_;
36 } 31 }
37 32
38 const TaskQueueImpl::Task* WorkQueue::GetFrontTask() const { 33 const TaskQueueImpl::Task* WorkQueue::GetFrontTask() const {
39 if (work_queue_.empty()) 34 if (work_queue_.empty())
40 return nullptr; 35 return nullptr;
41 return &work_queue_.front(); 36 return &*work_queue_.begin();
42 } 37 }
43 38
44 bool WorkQueue::GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const { 39 bool WorkQueue::GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const {
45 if (work_queue_.empty()) 40 if (work_queue_.empty())
46 return false; 41 return false;
47 *enqueue_order = work_queue_.front().enqueue_order(); 42 // Quick sanity check.
43 DCHECK_LE(work_queue_.begin()->enqueue_order(),
44 work_queue_.rbegin()->enqueue_order())
45 << task_queue_->GetName() << " : "
46 << work_queue_sets_->name() << " : " << name_;
47 *enqueue_order = work_queue_.begin()->enqueue_order();
48 return true; 48 return true;
49 } 49 }
50 50
51 void WorkQueue::Push(TaskQueueImpl::Task task) { 51 void WorkQueue::Push(TaskQueueImpl::Task task) {
52 bool was_empty = work_queue_.empty(); 52 bool was_empty = work_queue_.empty();
53 work_queue_.push(std::move(task)); 53 #ifndef NDEBUG
54 if (was_empty && work_queue_sets_) 54 DCHECK(task.enqueue_order_set());
55 #endif
56
57 // We expect |task| to be inserted at the end. Amoritized O(1).
58 work_queue_.insert(work_queue_.end(), std::move(task));
59 DCHECK_EQ(task.enqueue_order(), work_queue_.rbegin()->enqueue_order())
60 << task_queue_->GetName() << " : "
61 << work_queue_sets_->name() << " : " << name_
62 << "task [scheduled_run_time_" << task.delayed_run_time << ", "
63 << task.sequence_num <<
64 "] rbegin() [" << work_queue_.rbegin()->delayed_run_time << ", "
65 << work_queue_.rbegin()->sequence_num << "]";
66
67 if (was_empty && work_queue_sets_) {
55 work_queue_sets_->OnPushQueue(this); 68 work_queue_sets_->OnPushQueue(this);
69 }
56 } 70 }
57 71
58 void WorkQueue::PushAndSetEnqueueOrder(TaskQueueImpl::Task task, 72 bool WorkQueue::CancelTask(const TaskQueueImpl::Task& key) {
59 EnqueueOrder enqueue_order) { 73 TaskQueueImpl::ComparatorQueue::iterator it = work_queue_.find(key);
60 bool was_empty = work_queue_.empty(); 74 if (it == work_queue_.end())
61 work_queue_.push(std::move(task)); 75 return false;
62 work_queue_.back().set_enqueue_order(enqueue_order);
63 76
64 if (was_empty && work_queue_sets_) 77 if (it == work_queue_.begin()) {
65 work_queue_sets_->OnPushQueue(this); 78 EnqueueOrder erased_task_enqueue_order = it->enqueue_order();
79 work_queue_.erase(it);
80 // We can't guarantee this WorkQueue is the lowest value in the WorkQueueSet
81 // so we need to use OnQueueHeadChanged instead of OnPopQueue for
82 // correctness.
83 work_queue_sets_->OnQueueHeadChanged(this, erased_task_enqueue_order);
84 } else {
85 work_queue_.erase(it);
86 }
87 task_queue_->TraceQueueSize(false);
88 return true;
89 }
90
91 bool WorkQueue::IsTaskPending(const TaskQueueImpl::Task& key) const {
92 return work_queue_.find(key) != work_queue_.end();
66 } 93 }
67 94
68 void WorkQueue::PopTaskForTest() { 95 void WorkQueue::PopTaskForTest() {
69 work_queue_.pop(); 96 if (work_queue_.empty())
97 return;
98 work_queue_.erase(work_queue_.begin());
70 } 99 }
71 100
72 void WorkQueue::SwapLocked(std::queue<TaskQueueImpl::Task>& incoming_queue) { 101 void WorkQueue::SwapLocked(TaskQueueImpl::ComparatorQueue& incoming_queue) {
102 DCHECK(work_queue_.empty());
73 std::swap(work_queue_, incoming_queue); 103 std::swap(work_queue_, incoming_queue);
74
75 if (!work_queue_.empty() && work_queue_sets_) 104 if (!work_queue_.empty() && work_queue_sets_)
76 work_queue_sets_->OnPushQueue(this); 105 work_queue_sets_->OnPushQueue(this);
77 task_queue_->TraceQueueSize(true); 106 task_queue_->TraceQueueSize(true);
78 } 107 }
79 108
80 TaskQueueImpl::Task WorkQueue::TakeTaskFromWorkQueue() { 109 TaskQueueImpl::Task WorkQueue::TakeTaskFromWorkQueue() {
81 DCHECK(work_queue_sets_); 110 DCHECK(work_queue_sets_);
82 DCHECK(!work_queue_.empty()); 111 DCHECK(!work_queue_.empty());
83 TaskQueueImpl::Task pending_task = std::move(work_queue_.front()); 112 TaskQueueImpl::ComparatorQueue::iterator it = work_queue_.begin();
84 work_queue_.pop(); 113 TaskQueueImpl::Task pending_task =
114 std::move(const_cast<TaskQueueImpl::Task&>(*it));
115 work_queue_.erase(it);
85 work_queue_sets_->OnPopQueue(this); 116 work_queue_sets_->OnPopQueue(this);
86 task_queue_->TraceQueueSize(false); 117 task_queue_->TraceQueueSize(false);
87 return pending_task; 118 return pending_task;
88 } 119 }
89 120
90 void WorkQueue::AssignToWorkQueueSets(WorkQueueSets* work_queue_sets) { 121 void WorkQueue::AssignToWorkQueueSets(WorkQueueSets* work_queue_sets) {
91 work_queue_sets_ = work_queue_sets; 122 work_queue_sets_ = work_queue_sets;
92 } 123 }
93 124
94 void WorkQueue::AssignSetIndex(size_t work_queue_set_index) { 125 void WorkQueue::AssignSetIndex(size_t work_queue_set_index) {
95 work_queue_set_index_ = work_queue_set_index; 126 work_queue_set_index_ = work_queue_set_index;
96 } 127 }
97 128
98 bool WorkQueue::ShouldRunBefore(const WorkQueue* other_queue) const { 129 bool WorkQueue::ShouldRunBefore(const WorkQueue* other_queue) const {
99 DCHECK(!work_queue_.empty()); 130 DCHECK(!work_queue_.empty());
100 DCHECK(!other_queue->work_queue_.empty()); 131 DCHECK(!other_queue->work_queue_.empty());
101 EnqueueOrder enqueue_order = 0; 132 EnqueueOrder enqueue_order = 0;
102 EnqueueOrder other_enqueue_order = 0; 133 EnqueueOrder other_enqueue_order = 0;
103 bool have_task = GetFrontTaskEnqueueOrder(&enqueue_order); 134 bool have_task = GetFrontTaskEnqueueOrder(&enqueue_order);
104 bool have_other_task = 135 bool have_other_task =
105 other_queue->GetFrontTaskEnqueueOrder(&other_enqueue_order); 136 other_queue->GetFrontTaskEnqueueOrder(&other_enqueue_order);
106 DCHECK(have_task); 137 DCHECK(have_task);
107 DCHECK(have_other_task); 138 DCHECK(have_other_task);
108 return enqueue_order < other_enqueue_order; 139 return enqueue_order < other_enqueue_order;
109 } 140 }
110 141
111 } // namespace internal 142 } // namespace internal
112 } // namespace scheduler 143 } // namespace scheduler
113 } // namespace blink 144 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698