summaryrefslogtreecommitdiff
path: root/deps/v8/src/libplatform/default-foreground-task-runner.cc
blob: 140dd404ec6eff87b70d4292040198c23544b537 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// 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