| // 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::MutexGuard 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::MutexGuard&) { |
| if (terminated_) return; |
| task_queue_.push(std::move(task)); |
| event_loop_control_.NotifyOne(); |
| } |
| |
| void DefaultForegroundTaskRunner::PostTask(std::unique_ptr<Task> task) { |
| base::MutexGuard 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::MutexGuard 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::MutexGuard 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::MutexGuard 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::MutexGuard&) { |
| 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::MutexGuard 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::MutexGuard&) { |
| event_loop_control_.Wait(&lock_); |
| } |
| |
| } // namespace platform |
| } // namespace v8 |