| // Copyright 2017 the V8 project authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/libplatform/default-foreground-task-runner.h" | |
| #include "src/base/platform/mutex.h" | |
| #include "src/libplatform/default-platform.h" | |
| namespace v8 { | |
| namespace platform { | |
| DefaultForegroundTaskRunner::DefaultForegroundTaskRunner( | |
| IdleTaskSupport idle_task_support, TimeFunction time_function) | |
| : idle_task_support_(idle_task_support), time_function_(time_function) {} | |
| void DefaultForegroundTaskRunner::Terminate() { | |
| base::LockGuard<base::Mutex> guard(&lock_); | |
| terminated_ = true; | |
| // Drain the task queues. | |
| while (!task_queue_.empty()) task_queue_.pop(); | |
| while (!delayed_task_queue_.empty()) delayed_task_queue_.pop(); | |
| while (!idle_task_queue_.empty()) idle_task_queue_.pop(); | |
| } | |
| void DefaultForegroundTaskRunner::PostTaskLocked( | |
| std::unique_ptr<Task> task, const base::LockGuard<base::Mutex>&) { | |
| if (terminated_) return; | |
| task_queue_.push(std::move(task)); | |
| event_loop_control_.NotifyOne(); | |
| } | |
| void DefaultForegroundTaskRunner::PostTask(std::unique_ptr<Task> task) { | |
| base::LockGuard<base::Mutex> guard(&lock_); | |
| PostTaskLocked(std::move(task), guard); | |
| } | |
| double DefaultForegroundTaskRunner::MonotonicallyIncreasingTime() { | |
| return time_function_(); | |
| } | |
| void DefaultForegroundTaskRunner::PostDelayedTask(std::unique_ptr<Task> task, | |
| double delay_in_seconds) { | |
| DCHECK_GE(delay_in_seconds, 0.0); | |
| base::LockGuard<base::Mutex> guard(&lock_); | |
| if (terminated_) return; | |
| double deadline = MonotonicallyIncreasingTime() + delay_in_seconds; | |
| delayed_task_queue_.push(std::make_pair(deadline, std::move(task))); | |
| } | |
| void DefaultForegroundTaskRunner::PostIdleTask(std::unique_ptr<IdleTask> task) { | |
| CHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_); | |
| base::LockGuard<base::Mutex> guard(&lock_); | |
| if (terminated_) return; | |
| idle_task_queue_.push(std::move(task)); | |
| } | |
| bool DefaultForegroundTaskRunner::IdleTasksEnabled() { | |
| return idle_task_support_ == IdleTaskSupport::kEnabled; | |
| } | |
| std::unique_ptr<Task> DefaultForegroundTaskRunner::PopTaskFromQueue( | |
| MessageLoopBehavior wait_for_work) { | |
| base::LockGuard<base::Mutex> guard(&lock_); | |
| // Move delayed tasks that hit their deadline to the main queue. | |
| std::unique_ptr<Task> task = PopTaskFromDelayedQueueLocked(guard); | |
| while (task) { | |
| PostTaskLocked(std::move(task), guard); | |
| task = PopTaskFromDelayedQueueLocked(guard); | |
| } | |
| while (task_queue_.empty()) { | |
| if (wait_for_work == MessageLoopBehavior::kDoNotWait) return {}; | |
| WaitForTaskLocked(guard); | |
| } | |
| task = std::move(task_queue_.front()); | |
| task_queue_.pop(); | |
| return task; | |
| } | |
| std::unique_ptr<Task> | |
| DefaultForegroundTaskRunner::PopTaskFromDelayedQueueLocked( | |
| const base::LockGuard<base::Mutex>&) { | |
| if (delayed_task_queue_.empty()) return {}; | |
| double now = MonotonicallyIncreasingTime(); | |
| const DelayedEntry& deadline_and_task = delayed_task_queue_.top(); | |
| if (deadline_and_task.first > now) return {}; | |
| // The const_cast here is necessary because there does not exist a clean way | |
| // to get a unique_ptr out of the priority queue. We provide the priority | |
| // queue with a custom comparison operator to make sure that the priority | |
| // queue does not access the unique_ptr. Therefore it should be safe to reset | |
| // the unique_ptr in the priority queue here. Note that the DelayedEntry is | |
| // removed from the priority_queue immediately afterwards. | |
| std::unique_ptr<Task> result = | |
| std::move(const_cast<DelayedEntry&>(deadline_and_task).second); | |
| delayed_task_queue_.pop(); | |
| return result; | |
| } | |
| std::unique_ptr<IdleTask> DefaultForegroundTaskRunner::PopTaskFromIdleQueue() { | |
| base::LockGuard<base::Mutex> guard(&lock_); | |
| if (idle_task_queue_.empty()) return {}; | |
| std::unique_ptr<IdleTask> task = std::move(idle_task_queue_.front()); | |
| idle_task_queue_.pop(); | |
| return task; | |
| } | |
| void DefaultForegroundTaskRunner::WaitForTaskLocked( | |
| const base::LockGuard<base::Mutex>&) { | |
| event_loop_control_.Wait(&lock_); | |
| } | |
| } // namespace platform | |
| } // namespace v8 |