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 DefaultForegroundTaskRunner::DefaultForegroundTaskRunner( 14 IdleTaskSupport idle_task_support, TimeFunction time_function) 15 : idle_task_support_(idle_task_support), time_function_(time_function) {} 16 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 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 34 void DefaultForegroundTaskRunner::PostTask(std::unique_ptr<Task> task) { 35 base::LockGuard<base::Mutex> guard(&lock_); 36 PostTaskLocked(std::move(task), guard); 37 } 38 39 double DefaultForegroundTaskRunner::MonotonicallyIncreasingTime() { 40 return time_function_(); 41 } 42 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 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 59 bool DefaultForegroundTaskRunner::IdleTasksEnabled() { 60 return idle_task_support_ == IdleTaskSupport::kEnabled; 61 } 62 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> 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 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 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