• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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