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 #ifndef V8_LIBPLATFORM_DEFAULT_FOREGROUND_TASK_RUNNER_H_ 6 #define V8_LIBPLATFORM_DEFAULT_FOREGROUND_TASK_RUNNER_H_ 7 8 #include <memory> 9 #include <queue> 10 11 #include "include/libplatform/libplatform.h" 12 #include "include/v8-platform.h" 13 #include "src/base/platform/condition-variable.h" 14 #include "src/base/platform/mutex.h" 15 16 namespace v8 { 17 namespace platform { 18 19 class V8_PLATFORM_EXPORT DefaultForegroundTaskRunner NON_EXPORTED_BASE(TaskRunner)20 : public NON_EXPORTED_BASE(TaskRunner) { 21 public: 22 using TimeFunction = double (*)(); 23 class V8_NODISCARD RunTaskScope { 24 public: 25 explicit RunTaskScope( 26 std::shared_ptr<DefaultForegroundTaskRunner> task_runner); 27 ~RunTaskScope(); 28 RunTaskScope(const RunTaskScope&) = delete; 29 RunTaskScope& operator=(const RunTaskScope&) = delete; 30 31 private: 32 std::shared_ptr<DefaultForegroundTaskRunner> task_runner_; 33 }; 34 35 DefaultForegroundTaskRunner(IdleTaskSupport idle_task_support, 36 TimeFunction time_function); 37 38 void Terminate(); 39 40 std::unique_ptr<Task> PopTaskFromQueue(MessageLoopBehavior wait_for_work); 41 42 std::unique_ptr<IdleTask> PopTaskFromIdleQueue(); 43 44 double MonotonicallyIncreasingTime(); 45 46 // v8::TaskRunner implementation. 47 void PostTask(std::unique_ptr<Task> task) override; 48 void PostDelayedTask(std::unique_ptr<Task> task, 49 double delay_in_seconds) override; 50 51 void PostIdleTask(std::unique_ptr<IdleTask> task) override; 52 bool IdleTasksEnabled() override; 53 54 void PostNonNestableTask(std::unique_ptr<Task> task) override; 55 void PostNonNestableDelayedTask(std::unique_ptr<Task> task, 56 double delay_in_seconds) override; 57 bool NonNestableTasksEnabled() const override; 58 59 private: 60 enum Nestability { kNestable, kNonNestable }; 61 62 void WaitForTaskLocked(const base::MutexGuard&); 63 64 // The same as PostTask or PostNonNestableTask, but the lock is already held 65 // by the caller. The {guard} parameter should make sure that the caller is 66 // holding the lock. 67 void PostTaskLocked(std::unique_ptr<Task> task, Nestability nestability, 68 const base::MutexGuard&); 69 70 // The same as PostDelayedTask or PostNonNestableDelayedTask, but the lock is 71 // already held by the caller. The {guard} parameter should make sure that the 72 // caller is holding the lock. 73 void PostDelayedTaskLocked(std::unique_ptr<Task> task, 74 double delay_in_seconds, Nestability nestability, 75 const base::MutexGuard&); 76 77 // A caller of this function has to hold {lock_}. The {guard} parameter should 78 // make sure that the caller is holding the lock. 79 std::unique_ptr<Task> PopTaskFromDelayedQueueLocked(const base::MutexGuard&, 80 Nestability* nestability); 81 82 // A non-nestable task is poppable only if the task runner is not nested, 83 // i.e. if a task is not being run from within a task. A nestable task is 84 // always poppable. 85 bool HasPoppableTaskInQueue() const; 86 87 // Move delayed tasks that hit their deadline to the main queue. 88 void MoveExpiredDelayedTasks(const base::MutexGuard& guard); 89 90 bool terminated_ = false; 91 base::Mutex lock_; 92 base::ConditionVariable event_loop_control_; 93 int nesting_depth_ = 0; 94 95 using TaskQueueEntry = std::pair<Nestability, std::unique_ptr<Task>>; 96 std::deque<TaskQueueEntry> task_queue_; 97 98 IdleTaskSupport idle_task_support_; 99 std::queue<std::unique_ptr<IdleTask>> idle_task_queue_; 100 101 // Some helper constructs for the {delayed_task_queue_}. 102 struct DelayedEntry { 103 double timeout_time; 104 Nestability nestability; 105 std::unique_ptr<Task> task; 106 }; 107 108 // Define a comparison operator for the delayed_task_queue_ to make sure 109 // that the unique_ptr in the DelayedEntry is not accessed in the priority 110 // queue. This is necessary because we have to reset the unique_ptr when we 111 // remove a DelayedEntry from the priority queue. 112 struct DelayedEntryCompare { 113 bool operator()(const DelayedEntry& left, const DelayedEntry& right) const { 114 return left.timeout_time > right.timeout_time; 115 } 116 }; 117 std::priority_queue<DelayedEntry, std::vector<DelayedEntry>, 118 DelayedEntryCompare> 119 delayed_task_queue_; 120 121 TimeFunction time_function_; 122 }; 123 124 } // namespace platform 125 } // namespace v8 126 #endif // V8_LIBPLATFORM_DEFAULT_FOREGROUND_TASK_RUNNER_H_ 127