v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
default-foreground-task-runner.cc
Go to the documentation of this file.
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
6
9
10namespace v8 {
11namespace platform {
12
14 std::shared_ptr<DefaultForegroundTaskRunner> task_runner)
15 : task_runner_(task_runner) {
16 DCHECK_GE(task_runner->nesting_depth_, 0);
17 task_runner->nesting_depth_++;
18}
19
21 DCHECK_GT(task_runner_->nesting_depth_, 0);
22 task_runner_->nesting_depth_--;
23}
24
26 IdleTaskSupport idle_task_support, TimeFunction time_function)
27 : idle_task_support_(idle_task_support), time_function_(time_function) {}
28
30 // Drain the task queues.
31 // We make sure to delete tasks outside the TaskRunner lock, to avoid
32 // potential deadlocks.
33 std::deque<TaskQueueEntry> obsolete_tasks;
34 std::priority_queue<DelayedEntry, std::vector<DelayedEntry>,
36 obsolete_delayed_tasks;
37 std::queue<std::unique_ptr<IdleTask>> obsolete_idle_tasks;
38 {
40 terminated_ = true;
41 task_queue_.swap(obsolete_tasks);
42 delayed_task_queue_.swap(obsolete_delayed_tasks);
43 idle_task_queue_.swap(obsolete_idle_tasks);
44 }
45 while (!obsolete_tasks.empty()) obsolete_tasks.pop_front();
46 while (!obsolete_delayed_tasks.empty()) obsolete_delayed_tasks.pop();
47 while (!obsolete_idle_tasks.empty()) obsolete_idle_tasks.pop();
48}
49
51 std::unique_ptr<Task> task, Nestability nestability) {
53 if (terminated_) return task;
54 task_queue_.push_back(std::make_pair(nestability, std::move(task)));
56 return {};
57}
58
59void DefaultForegroundTaskRunner::PostTaskImpl(std::unique_ptr<Task> task,
60 const SourceLocation& location) {
62 task = PostTaskLocked(std::move(task), kNestable);
63}
64
68
70 std::unique_ptr<Task> task, double delay_in_seconds,
71 Nestability nestability) {
73 DCHECK_GE(delay_in_seconds, 0.0);
74 if (terminated_) return;
75 double deadline = MonotonicallyIncreasingTime() + delay_in_seconds;
76 delayed_task_queue_.push({deadline, nestability, std::move(task)});
78}
79
81 std::unique_ptr<Task> task, double delay_in_seconds,
82 const SourceLocation& location) {
84 PostDelayedTaskLocked(std::move(task), delay_in_seconds, kNestable);
85}
86
88 std::unique_ptr<Task> task, double delay_in_seconds,
89 const SourceLocation& location) {
91 PostDelayedTaskLocked(std::move(task), delay_in_seconds, kNonNestable);
92}
93
95 std::unique_ptr<IdleTask> task, const SourceLocation& location) {
98 if (terminated_) return;
99 idle_task_queue_.push(std::move(task));
100}
101
105
107 std::unique_ptr<Task> task, const SourceLocation& location) {
108 base::MutexGuard guard(&mutex_);
109 task = PostTaskLocked(std::move(task), kNonNestable);
110}
111
113 return true;
114}
115
119
121 if (nesting_depth_ == 0) return !task_queue_.empty();
122 for (auto it = task_queue_.cbegin(); it != task_queue_.cend(); it++) {
123 if (it->first == kNestable) return true;
124 }
125 return false;
126}
127
128std::vector<std::unique_ptr<Task>>
130 Nestability nestability;
131 std::vector<std::unique_ptr<Task>> expired_tasks_to_delete;
132 while (std::unique_ptr<Task> task =
133 PopTaskFromDelayedQueueLocked(&nestability)) {
134 auto to_delete = PostTaskLocked(std::move(task), nestability);
135 if (to_delete) expired_tasks_to_delete.emplace_back(std::move(to_delete));
136 }
137 return expired_tasks_to_delete;
138}
139
141 MessageLoopBehavior wait_for_work) {
142 std::vector<std::unique_ptr<Task>> tasks_to_delete;
143 base::MutexGuard guard(&mutex_);
144 tasks_to_delete = MoveExpiredDelayedTasksLocked();
145
146 while (!HasPoppableTaskInQueue()) {
147 if (wait_for_work == MessageLoopBehavior::kDoNotWait) return {};
149 auto new_tasks_to_delete = MoveExpiredDelayedTasksLocked();
150 tasks_to_delete.insert(tasks_to_delete.end(),
151 std::make_move_iterator(new_tasks_to_delete.begin()),
152 std::make_move_iterator(new_tasks_to_delete.end()));
153 }
154
155 auto it = task_queue_.begin();
156 for (; it != task_queue_.end(); it++) {
157 // When the task queue is nested (i.e. popping a task from the queue from
158 // within a task), only nestable tasks may run. Otherwise, any task may run.
159 if (nesting_depth_ == 0 || it->first == kNestable) break;
160 }
161 DCHECK(it != task_queue_.end());
162 std::unique_ptr<Task> task = std::move(it->second);
163 task_queue_.erase(it);
164
165 return task;
166}
167
168std::unique_ptr<Task>
170 Nestability* nestability) {
172 if (delayed_task_queue_.empty()) return {};
173
174 double now = MonotonicallyIncreasingTime();
175 const DelayedEntry& entry = delayed_task_queue_.top();
176 if (entry.timeout_time > now) return {};
177 // The const_cast here is necessary because there does not exist a clean way
178 // to get a unique_ptr out of the priority queue. We provide the priority
179 // queue with a custom comparison operator to make sure that the priority
180 // queue does not access the unique_ptr. Therefore it should be safe to reset
181 // the unique_ptr in the priority queue here. Note that the DelayedEntry is
182 // removed from the priority_queue immediately afterwards.
183 std::unique_ptr<Task> task = std::move(const_cast<DelayedEntry&>(entry).task);
184 *nestability = entry.nestability;
186 return task;
187}
188
190 base::MutexGuard guard(&mutex_);
191 if (idle_task_queue_.empty()) return {};
192
193 std::unique_ptr<IdleTask> task = std::move(idle_task_queue_.front());
194 idle_task_queue_.pop();
195
196 return task;
197}
198
201 if (!delayed_task_queue_.empty()) {
202 double now = MonotonicallyIncreasingTime();
203 const DelayedEntry& entry = delayed_task_queue_.top();
204 double time_until_task = entry.timeout_time - now;
205 if (time_until_task > 0) {
206 bool woken_up = event_loop_control_.WaitFor(
207 &mutex_,
210 USE(woken_up);
211 }
212 } else {
214 }
215}
216
217} // namespace platform
218} // namespace v8
bool WaitFor(Mutex *mutex, const TimeDelta &rel_time) V8_WARN_UNUSED_RESULT
V8_INLINE void AssertHeld() const
Definition mutex.h:58
static constexpr int64_t kMicrosecondsPerSecond
Definition time.h:49
static constexpr TimeDelta FromMicroseconds(int64_t microseconds)
Definition time.h:87
RunTaskScope(std::shared_ptr< DefaultForegroundTaskRunner > task_runner)
void PostNonNestableTaskImpl(std::unique_ptr< Task > task, const SourceLocation &location) override
std::unique_ptr< Task > PopTaskFromQueue(MessageLoopBehavior wait_for_work)
std::unique_ptr< Task > PostTaskLocked(std::unique_ptr< Task > task, Nestability nestability)
void PostDelayedTaskLocked(std::unique_ptr< Task > task, double delay_in_seconds, Nestability nestability)
void PostTaskImpl(std::unique_ptr< Task > task, const SourceLocation &location) override
std::queue< std::unique_ptr< IdleTask > > idle_task_queue_
void PostIdleTaskImpl(std::unique_ptr< IdleTask > task, const SourceLocation &location) override
DefaultForegroundTaskRunner(IdleTaskSupport idle_task_support, TimeFunction time_function)
void PostDelayedTaskImpl(std::unique_ptr< Task > task, double delay_in_seconds, const SourceLocation &location) override
std::unique_ptr< Task > PopTaskFromDelayedQueueLocked(Nestability *nestability)
void PostNonNestableDelayedTaskImpl(std::unique_ptr< Task > task, double delay_in_seconds, const SourceLocation &location) override
std::vector< std::unique_ptr< Task > > MoveExpiredDelayedTasksLocked()
std::priority_queue< DelayedEntry, std::vector< DelayedEntry >, DelayedEntryCompare > delayed_task_queue_
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define USE(...)
Definition macros.h:293