11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/libplatform/default-foreground-task-runner.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/base/platform/mutex.h" 81cb0ef41Sopenharmony_ci#include "src/libplatform/default-platform.h" 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_cinamespace v8 { 111cb0ef41Sopenharmony_cinamespace platform { 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ciDefaultForegroundTaskRunner::RunTaskScope::RunTaskScope( 141cb0ef41Sopenharmony_ci std::shared_ptr<DefaultForegroundTaskRunner> task_runner) 151cb0ef41Sopenharmony_ci : task_runner_(task_runner) { 161cb0ef41Sopenharmony_ci DCHECK_GE(task_runner->nesting_depth_, 0); 171cb0ef41Sopenharmony_ci task_runner->nesting_depth_++; 181cb0ef41Sopenharmony_ci} 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ciDefaultForegroundTaskRunner::RunTaskScope::~RunTaskScope() { 211cb0ef41Sopenharmony_ci DCHECK_GT(task_runner_->nesting_depth_, 0); 221cb0ef41Sopenharmony_ci task_runner_->nesting_depth_--; 231cb0ef41Sopenharmony_ci} 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ciDefaultForegroundTaskRunner::DefaultForegroundTaskRunner( 261cb0ef41Sopenharmony_ci IdleTaskSupport idle_task_support, TimeFunction time_function) 271cb0ef41Sopenharmony_ci : idle_task_support_(idle_task_support), time_function_(time_function) {} 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_civoid DefaultForegroundTaskRunner::Terminate() { 301cb0ef41Sopenharmony_ci base::MutexGuard guard(&lock_); 311cb0ef41Sopenharmony_ci terminated_ = true; 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci // Drain the task queues. 341cb0ef41Sopenharmony_ci while (!task_queue_.empty()) task_queue_.pop_front(); 351cb0ef41Sopenharmony_ci while (!delayed_task_queue_.empty()) delayed_task_queue_.pop(); 361cb0ef41Sopenharmony_ci while (!idle_task_queue_.empty()) idle_task_queue_.pop(); 371cb0ef41Sopenharmony_ci} 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_civoid DefaultForegroundTaskRunner::PostTaskLocked(std::unique_ptr<Task> task, 401cb0ef41Sopenharmony_ci Nestability nestability, 411cb0ef41Sopenharmony_ci const base::MutexGuard&) { 421cb0ef41Sopenharmony_ci if (terminated_) return; 431cb0ef41Sopenharmony_ci task_queue_.push_back(std::make_pair(nestability, std::move(task))); 441cb0ef41Sopenharmony_ci event_loop_control_.NotifyOne(); 451cb0ef41Sopenharmony_ci} 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_civoid DefaultForegroundTaskRunner::PostTask(std::unique_ptr<Task> task) { 481cb0ef41Sopenharmony_ci base::MutexGuard guard(&lock_); 491cb0ef41Sopenharmony_ci PostTaskLocked(std::move(task), kNestable, guard); 501cb0ef41Sopenharmony_ci} 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_cidouble DefaultForegroundTaskRunner::MonotonicallyIncreasingTime() { 531cb0ef41Sopenharmony_ci return time_function_(); 541cb0ef41Sopenharmony_ci} 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_civoid DefaultForegroundTaskRunner::PostDelayedTaskLocked( 571cb0ef41Sopenharmony_ci std::unique_ptr<Task> task, double delay_in_seconds, 581cb0ef41Sopenharmony_ci Nestability nestability, const base::MutexGuard&) { 591cb0ef41Sopenharmony_ci DCHECK_GE(delay_in_seconds, 0.0); 601cb0ef41Sopenharmony_ci if (terminated_) return; 611cb0ef41Sopenharmony_ci double deadline = MonotonicallyIncreasingTime() + delay_in_seconds; 621cb0ef41Sopenharmony_ci delayed_task_queue_.push({deadline, nestability, std::move(task)}); 631cb0ef41Sopenharmony_ci event_loop_control_.NotifyOne(); 641cb0ef41Sopenharmony_ci} 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_civoid DefaultForegroundTaskRunner::PostDelayedTask(std::unique_ptr<Task> task, 671cb0ef41Sopenharmony_ci double delay_in_seconds) { 681cb0ef41Sopenharmony_ci base::MutexGuard guard(&lock_); 691cb0ef41Sopenharmony_ci PostDelayedTaskLocked(std::move(task), delay_in_seconds, kNestable, guard); 701cb0ef41Sopenharmony_ci} 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_civoid DefaultForegroundTaskRunner::PostNonNestableDelayedTask( 731cb0ef41Sopenharmony_ci std::unique_ptr<Task> task, double delay_in_seconds) { 741cb0ef41Sopenharmony_ci base::MutexGuard guard(&lock_); 751cb0ef41Sopenharmony_ci PostDelayedTaskLocked(std::move(task), delay_in_seconds, kNonNestable, guard); 761cb0ef41Sopenharmony_ci} 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_civoid DefaultForegroundTaskRunner::PostIdleTask(std::unique_ptr<IdleTask> task) { 791cb0ef41Sopenharmony_ci CHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_); 801cb0ef41Sopenharmony_ci base::MutexGuard guard(&lock_); 811cb0ef41Sopenharmony_ci if (terminated_) return; 821cb0ef41Sopenharmony_ci idle_task_queue_.push(std::move(task)); 831cb0ef41Sopenharmony_ci} 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_cibool DefaultForegroundTaskRunner::IdleTasksEnabled() { 861cb0ef41Sopenharmony_ci return idle_task_support_ == IdleTaskSupport::kEnabled; 871cb0ef41Sopenharmony_ci} 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_civoid DefaultForegroundTaskRunner::PostNonNestableTask( 901cb0ef41Sopenharmony_ci std::unique_ptr<Task> task) { 911cb0ef41Sopenharmony_ci base::MutexGuard guard(&lock_); 921cb0ef41Sopenharmony_ci PostTaskLocked(std::move(task), kNonNestable, guard); 931cb0ef41Sopenharmony_ci} 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_cibool DefaultForegroundTaskRunner::NonNestableTasksEnabled() const { 961cb0ef41Sopenharmony_ci return true; 971cb0ef41Sopenharmony_ci} 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_cibool DefaultForegroundTaskRunner::HasPoppableTaskInQueue() const { 1001cb0ef41Sopenharmony_ci if (nesting_depth_ == 0) return !task_queue_.empty(); 1011cb0ef41Sopenharmony_ci for (auto it = task_queue_.cbegin(); it != task_queue_.cend(); it++) { 1021cb0ef41Sopenharmony_ci if (it->first == kNestable) return true; 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci return false; 1051cb0ef41Sopenharmony_ci} 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_civoid DefaultForegroundTaskRunner::MoveExpiredDelayedTasks( 1081cb0ef41Sopenharmony_ci const base::MutexGuard& guard) { 1091cb0ef41Sopenharmony_ci Nestability nestability; 1101cb0ef41Sopenharmony_ci std::unique_ptr<Task> task = 1111cb0ef41Sopenharmony_ci PopTaskFromDelayedQueueLocked(guard, &nestability); 1121cb0ef41Sopenharmony_ci while (task) { 1131cb0ef41Sopenharmony_ci PostTaskLocked(std::move(task), nestability, guard); 1141cb0ef41Sopenharmony_ci task = PopTaskFromDelayedQueueLocked(guard, &nestability); 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci} 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_cistd::unique_ptr<Task> DefaultForegroundTaskRunner::PopTaskFromQueue( 1191cb0ef41Sopenharmony_ci MessageLoopBehavior wait_for_work) { 1201cb0ef41Sopenharmony_ci base::MutexGuard guard(&lock_); 1211cb0ef41Sopenharmony_ci MoveExpiredDelayedTasks(guard); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci while (!HasPoppableTaskInQueue()) { 1241cb0ef41Sopenharmony_ci if (wait_for_work == MessageLoopBehavior::kDoNotWait) return {}; 1251cb0ef41Sopenharmony_ci WaitForTaskLocked(guard); 1261cb0ef41Sopenharmony_ci MoveExpiredDelayedTasks(guard); 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci auto it = task_queue_.begin(); 1301cb0ef41Sopenharmony_ci for (; it != task_queue_.end(); it++) { 1311cb0ef41Sopenharmony_ci // When the task queue is nested (i.e. popping a task from the queue from 1321cb0ef41Sopenharmony_ci // within a task), only nestable tasks may run. Otherwise, any task may run. 1331cb0ef41Sopenharmony_ci if (nesting_depth_ == 0 || it->first == kNestable) break; 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci DCHECK(it != task_queue_.end()); 1361cb0ef41Sopenharmony_ci std::unique_ptr<Task> task = std::move(it->second); 1371cb0ef41Sopenharmony_ci task_queue_.erase(it); 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci return task; 1401cb0ef41Sopenharmony_ci} 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_cistd::unique_ptr<Task> 1431cb0ef41Sopenharmony_ciDefaultForegroundTaskRunner::PopTaskFromDelayedQueueLocked( 1441cb0ef41Sopenharmony_ci const base::MutexGuard&, Nestability* nestability) { 1451cb0ef41Sopenharmony_ci if (delayed_task_queue_.empty()) return {}; 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci double now = MonotonicallyIncreasingTime(); 1481cb0ef41Sopenharmony_ci const DelayedEntry& entry = delayed_task_queue_.top(); 1491cb0ef41Sopenharmony_ci if (entry.timeout_time > now) return {}; 1501cb0ef41Sopenharmony_ci // The const_cast here is necessary because there does not exist a clean way 1511cb0ef41Sopenharmony_ci // to get a unique_ptr out of the priority queue. We provide the priority 1521cb0ef41Sopenharmony_ci // queue with a custom comparison operator to make sure that the priority 1531cb0ef41Sopenharmony_ci // queue does not access the unique_ptr. Therefore it should be safe to reset 1541cb0ef41Sopenharmony_ci // the unique_ptr in the priority queue here. Note that the DelayedEntry is 1551cb0ef41Sopenharmony_ci // removed from the priority_queue immediately afterwards. 1561cb0ef41Sopenharmony_ci std::unique_ptr<Task> task = std::move(const_cast<DelayedEntry&>(entry).task); 1571cb0ef41Sopenharmony_ci *nestability = entry.nestability; 1581cb0ef41Sopenharmony_ci delayed_task_queue_.pop(); 1591cb0ef41Sopenharmony_ci return task; 1601cb0ef41Sopenharmony_ci} 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_cistd::unique_ptr<IdleTask> DefaultForegroundTaskRunner::PopTaskFromIdleQueue() { 1631cb0ef41Sopenharmony_ci base::MutexGuard guard(&lock_); 1641cb0ef41Sopenharmony_ci if (idle_task_queue_.empty()) return {}; 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci std::unique_ptr<IdleTask> task = std::move(idle_task_queue_.front()); 1671cb0ef41Sopenharmony_ci idle_task_queue_.pop(); 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci return task; 1701cb0ef41Sopenharmony_ci} 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_civoid DefaultForegroundTaskRunner::WaitForTaskLocked(const base::MutexGuard&) { 1731cb0ef41Sopenharmony_ci if (!delayed_task_queue_.empty()) { 1741cb0ef41Sopenharmony_ci double now = MonotonicallyIncreasingTime(); 1751cb0ef41Sopenharmony_ci const DelayedEntry& entry = delayed_task_queue_.top(); 1761cb0ef41Sopenharmony_ci double time_until_task = entry.timeout_time - now; 1771cb0ef41Sopenharmony_ci if (time_until_task > 0) { 1781cb0ef41Sopenharmony_ci bool woken_up = event_loop_control_.WaitFor( 1791cb0ef41Sopenharmony_ci &lock_, 1801cb0ef41Sopenharmony_ci base::TimeDelta::FromMicroseconds( 1811cb0ef41Sopenharmony_ci time_until_task * base::TimeConstants::kMicrosecondsPerSecond)); 1821cb0ef41Sopenharmony_ci USE(woken_up); 1831cb0ef41Sopenharmony_ci } 1841cb0ef41Sopenharmony_ci } else { 1851cb0ef41Sopenharmony_ci event_loop_control_.Wait(&lock_); 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci} 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci} // namespace platform 1901cb0ef41Sopenharmony_ci} // namespace v8 191