• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DefaultForegroundTaskRunner(IdleTaskSupport idle_task_support,TimeFunction time_function)13 DefaultForegroundTaskRunner::DefaultForegroundTaskRunner(
14     IdleTaskSupport idle_task_support, TimeFunction time_function)
15     : idle_task_support_(idle_task_support), time_function_(time_function) {}
16 
Terminate()17 void DefaultForegroundTaskRunner::Terminate() {
18   base::LockGuard<base::Mutex> guard(&lock_);
19   terminated_ = true;
20 
21   // Drain the task queues.
22   while (!task_queue_.empty()) task_queue_.pop();
23   while (!delayed_task_queue_.empty()) delayed_task_queue_.pop();
24   while (!idle_task_queue_.empty()) idle_task_queue_.pop();
25 }
26 
PostTaskLocked(std::unique_ptr<Task> task,const base::LockGuard<base::Mutex> &)27 void DefaultForegroundTaskRunner::PostTaskLocked(
28     std::unique_ptr<Task> task, const base::LockGuard<base::Mutex>&) {
29   if (terminated_) return;
30   task_queue_.push(std::move(task));
31   event_loop_control_.NotifyOne();
32 }
33 
PostTask(std::unique_ptr<Task> task)34 void DefaultForegroundTaskRunner::PostTask(std::unique_ptr<Task> task) {
35   base::LockGuard<base::Mutex> guard(&lock_);
36   PostTaskLocked(std::move(task), guard);
37 }
38 
MonotonicallyIncreasingTime()39 double DefaultForegroundTaskRunner::MonotonicallyIncreasingTime() {
40   return time_function_();
41 }
42 
PostDelayedTask(std::unique_ptr<Task> task,double delay_in_seconds)43 void DefaultForegroundTaskRunner::PostDelayedTask(std::unique_ptr<Task> task,
44                                                   double delay_in_seconds) {
45   DCHECK_GE(delay_in_seconds, 0.0);
46   base::LockGuard<base::Mutex> guard(&lock_);
47   if (terminated_) return;
48   double deadline = MonotonicallyIncreasingTime() + delay_in_seconds;
49   delayed_task_queue_.push(std::make_pair(deadline, std::move(task)));
50 }
51 
PostIdleTask(std::unique_ptr<IdleTask> task)52 void DefaultForegroundTaskRunner::PostIdleTask(std::unique_ptr<IdleTask> task) {
53   CHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_);
54   base::LockGuard<base::Mutex> guard(&lock_);
55   if (terminated_) return;
56   idle_task_queue_.push(std::move(task));
57 }
58 
IdleTasksEnabled()59 bool DefaultForegroundTaskRunner::IdleTasksEnabled() {
60   return idle_task_support_ == IdleTaskSupport::kEnabled;
61 }
62 
PopTaskFromQueue(MessageLoopBehavior wait_for_work)63 std::unique_ptr<Task> DefaultForegroundTaskRunner::PopTaskFromQueue(
64     MessageLoopBehavior wait_for_work) {
65   base::LockGuard<base::Mutex> guard(&lock_);
66   // Move delayed tasks that hit their deadline to the main queue.
67   std::unique_ptr<Task> task = PopTaskFromDelayedQueueLocked(guard);
68   while (task) {
69     PostTaskLocked(std::move(task), guard);
70     task = PopTaskFromDelayedQueueLocked(guard);
71   }
72 
73   while (task_queue_.empty()) {
74     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>
PopTaskFromDelayedQueueLocked(const base::LockGuard<base::Mutex> &)85 DefaultForegroundTaskRunner::PopTaskFromDelayedQueueLocked(
86     const base::LockGuard<base::Mutex>&) {
87   if (delayed_task_queue_.empty()) return {};
88 
89   double now = MonotonicallyIncreasingTime();
90   const DelayedEntry& deadline_and_task = delayed_task_queue_.top();
91   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   delayed_task_queue_.pop();
101   return result;
102 }
103 
PopTaskFromIdleQueue()104 std::unique_ptr<IdleTask> DefaultForegroundTaskRunner::PopTaskFromIdleQueue() {
105   base::LockGuard<base::Mutex> guard(&lock_);
106   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 
WaitForTaskLocked(const base::LockGuard<base::Mutex> &)114 void DefaultForegroundTaskRunner::WaitForTaskLocked(
115     const base::LockGuard<base::Mutex>&) {
116   event_loop_control_.Wait(&lock_);
117 }
118 
119 }  // namespace platform
120 }  // namespace v8
121