// 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. #ifndef V8_LIBPLATFORM_DEFAULT_FOREGROUND_TASK_RUNNER_H_ #define V8_LIBPLATFORM_DEFAULT_FOREGROUND_TASK_RUNNER_H_ #include #include #include "include/libplatform/libplatform.h" #include "include/v8-platform.h" #include "src/base/platform/condition-variable.h" #include "src/base/platform/mutex.h" namespace v8 { namespace platform { class V8_PLATFORM_EXPORT DefaultForegroundTaskRunner : public NON_EXPORTED_BASE(TaskRunner) { public: using TimeFunction = double (*)(); class RunTaskScope { public: explicit RunTaskScope( std::shared_ptr task_runner); ~RunTaskScope(); RunTaskScope(const RunTaskScope&) = delete; RunTaskScope& operator=(const RunTaskScope&) = delete; private: std::shared_ptr task_runner_; }; DefaultForegroundTaskRunner(IdleTaskSupport idle_task_support, TimeFunction time_function); void Terminate(); std::unique_ptr PopTaskFromQueue(MessageLoopBehavior wait_for_work); std::unique_ptr PopTaskFromIdleQueue(); double MonotonicallyIncreasingTime(); // v8::TaskRunner implementation. void PostTask(std::unique_ptr task) override; void PostDelayedTask(std::unique_ptr task, double delay_in_seconds) override; void PostIdleTask(std::unique_ptr task) override; bool IdleTasksEnabled() override; void PostNonNestableTask(std::unique_ptr task) override; void PostNonNestableDelayedTask(std::unique_ptr task, double delay_in_seconds) override; bool NonNestableTasksEnabled() const override; private: enum Nestability { kNestable, kNonNestable }; void WaitForTaskLocked(const base::MutexGuard&); // The same as PostTask or PostNonNestableTask, but the lock is already held // by the caller. The {guard} parameter should make sure that the caller is // holding the lock. void PostTaskLocked(std::unique_ptr task, Nestability nestability, const base::MutexGuard&); // The same as PostDelayedTask or PostNonNestableDelayedTask, but the lock is // already held by the caller. The {guard} parameter should make sure that the // caller is holding the lock. void PostDelayedTaskLocked(std::unique_ptr task, double delay_in_seconds, Nestability nestability, const base::MutexGuard&); // A caller of this function has to hold {lock_}. The {guard} parameter should // make sure that the caller is holding the lock. std::unique_ptr PopTaskFromDelayedQueueLocked(const base::MutexGuard&, Nestability* nestability); // A non-nestable task is poppable only if the task runner is not nested, // i.e. if a task is not being run from within a task. A nestable task is // always poppable. bool HasPoppableTaskInQueue() const; // Move delayed tasks that hit their deadline to the main queue. void MoveExpiredDelayedTasks(const base::MutexGuard& guard); bool terminated_ = false; base::Mutex lock_; base::ConditionVariable event_loop_control_; int nesting_depth_ = 0; using TaskQueueEntry = std::pair>; std::deque task_queue_; IdleTaskSupport idle_task_support_; std::queue> idle_task_queue_; // Some helper constructs for the {delayed_task_queue_}. struct DelayedEntry { double timeout_time; Nestability nestability; std::unique_ptr task; }; // Define a comparison operator for the delayed_task_queue_ to make sure // that the unique_ptr in the DelayedEntry is not accessed in the priority // queue. This is necessary because we have to reset the unique_ptr when we // remove a DelayedEntry from the priority queue. struct DelayedEntryCompare { bool operator()(const DelayedEntry& left, const DelayedEntry& right) const { return left.timeout_time > right.timeout_time; } }; std::priority_queue, DelayedEntryCompare> delayed_task_queue_; TimeFunction time_function_; }; } // namespace platform } // namespace v8 #endif // V8_LIBPLATFORM_DEFAULT_FOREGROUND_TASK_RUNNER_H_