Line data Source code
1 : // Copyright 2017 the V8 project 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 "src/libplatform/default-foreground-task-runner.h"
6 :
7 : #include "src/base/platform/mutex.h"
8 : #include "src/libplatform/default-platform.h"
9 :
10 : namespace v8 {
11 : namespace platform {
12 :
13 60369 : DefaultForegroundTaskRunner::DefaultForegroundTaskRunner(
14 : IdleTaskSupport idle_task_support, TimeFunction time_function)
15 241476 : : idle_task_support_(idle_task_support), time_function_(time_function) {}
16 :
17 59106 : void DefaultForegroundTaskRunner::Terminate() {
18 59106 : base::MutexGuard guard(&lock_);
19 59106 : terminated_ = true;
20 :
21 : // Drain the task queues.
22 120051 : while (!task_queue_.empty()) task_queue_.pop();
23 73908 : while (!delayed_task_queue_.empty()) delayed_task_queue_.pop();
24 59108 : while (!idle_task_queue_.empty()) idle_task_queue_.pop();
25 59106 : }
26 :
27 60289 : void DefaultForegroundTaskRunner::PostTaskLocked(std::unique_ptr<Task> task,
28 : const base::MutexGuard&) {
29 120578 : if (terminated_) return;
30 : task_queue_.push(std::move(task));
31 60288 : event_loop_control_.NotifyOne();
32 : }
33 :
34 59641 : void DefaultForegroundTaskRunner::PostTask(std::unique_ptr<Task> task) {
35 59641 : base::MutexGuard guard(&lock_);
36 119282 : PostTaskLocked(std::move(task), guard);
37 59641 : }
38 :
39 0 : double DefaultForegroundTaskRunner::MonotonicallyIncreasingTime() {
40 35821 : return time_function_();
41 : }
42 :
43 8054 : void DefaultForegroundTaskRunner::PostDelayedTask(std::unique_ptr<Task> task,
44 : double delay_in_seconds) {
45 : DCHECK_GE(delay_in_seconds, 0.0);
46 8054 : base::MutexGuard guard(&lock_);
47 16108 : if (terminated_) return;
48 8053 : double deadline = MonotonicallyIncreasingTime() + delay_in_seconds;
49 16106 : delayed_task_queue_.push(std::make_pair(deadline, std::move(task)));
50 : }
51 :
52 3959 : void DefaultForegroundTaskRunner::PostIdleTask(std::unique_ptr<IdleTask> task) {
53 3959 : CHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_);
54 3959 : base::MutexGuard guard(&lock_);
55 7918 : if (terminated_) return;
56 : idle_task_queue_.push(std::move(task));
57 : }
58 :
59 34 : bool DefaultForegroundTaskRunner::IdleTasksEnabled() {
60 34 : return idle_task_support_ == IdleTaskSupport::kEnabled;
61 : }
62 :
63 244487 : std::unique_ptr<Task> DefaultForegroundTaskRunner::PopTaskFromQueue(
64 : MessageLoopBehavior wait_for_work) {
65 244487 : base::MutexGuard guard(&lock_);
66 : // Move delayed tasks that hit their deadline to the main queue.
67 244487 : std::unique_ptr<Task> task = PopTaskFromDelayedQueueLocked(guard);
68 489622 : while (task) {
69 1296 : PostTaskLocked(std::move(task), guard);
70 1296 : task = PopTaskFromDelayedQueueLocked(guard);
71 : }
72 :
73 245275 : while (task_queue_.empty()) {
74 186826 : if (wait_for_work == MessageLoopBehavior::kDoNotWait) return {};
75 : WaitForTaskLocked(guard);
76 : }
77 :
78 : task = std::move(task_queue_.front());
79 : task_queue_.pop();
80 :
81 : return task;
82 : }
83 :
84 : std::unique_ptr<Task>
85 245135 : DefaultForegroundTaskRunner::PopTaskFromDelayedQueueLocked(
86 : const base::MutexGuard&) {
87 245135 : if (delayed_task_queue_.empty()) return {};
88 :
89 : double now = MonotonicallyIncreasingTime();
90 : const DelayedEntry& deadline_and_task = delayed_task_queue_.top();
91 27768 : if (deadline_and_task.first > now) return {};
92 : // The const_cast here is necessary because there does not exist a clean way
93 : // to get a unique_ptr out of the priority queue. We provide the priority
94 : // queue with a custom comparison operator to make sure that the priority
95 : // queue does not access the unique_ptr. Therefore it should be safe to reset
96 : // the unique_ptr in the priority queue here. Note that the DelayedEntry is
97 : // removed from the priority_queue immediately afterwards.
98 : std::unique_ptr<Task> result =
99 : std::move(const_cast<DelayedEntry&>(deadline_and_task).second);
100 648 : delayed_task_queue_.pop();
101 : return result;
102 : }
103 :
104 163152 : std::unique_ptr<IdleTask> DefaultForegroundTaskRunner::PopTaskFromIdleQueue() {
105 163152 : base::MutexGuard guard(&lock_);
106 163152 : if (idle_task_queue_.empty()) return {};
107 :
108 : std::unique_ptr<IdleTask> task = std::move(idle_task_queue_.front());
109 : idle_task_queue_.pop();
110 :
111 : return task;
112 : }
113 :
114 0 : void DefaultForegroundTaskRunner::WaitForTaskLocked(const base::MutexGuard&) {
115 788 : event_loop_control_.Wait(&lock_);
116 0 : }
117 :
118 : } // namespace platform
119 : } // namespace v8
|