Home | History | Annotate | Download | only in libplatform
      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