• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Chromium Authors
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 BASE_TASK_SEQUENCE_MANAGER_WAKE_UP_QUEUE_H_
6 #define BASE_TASK_SEQUENCE_MANAGER_WAKE_UP_QUEUE_H_
7 
8 #include <optional>
9 
10 #include "base/base_export.h"
11 #include "base/check.h"
12 #include "base/containers/intrusive_heap.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/memory/raw_ptr_exclusion.h"
15 #include "base/task/common/lazy_now.h"
16 #include "base/task/sequence_manager/task_queue_impl.h"
17 #include "base/time/time.h"
18 #include "base/values.h"
19 
20 namespace base {
21 namespace sequence_manager {
22 
23 class EnqueueOrder;
24 
25 namespace internal {
26 
27 class AssociatedThreadId;
28 class SequenceManagerImpl;
29 class TaskQueueImpl;
30 
31 // WakeUpQueue is a queue of (wake_up, TaskQueueImpl*) pairs which
32 // aggregates wake-ups from multiple TaskQueueImpl into a single wake-up, and
33 // notifies TaskQueueImpls when wake-up times are reached.
34 class BASE_EXPORT WakeUpQueue {
35  public:
36   WakeUpQueue(const WakeUpQueue&) = delete;
37   WakeUpQueue& operator=(const WakeUpQueue&) = delete;
38   virtual ~WakeUpQueue();
39 
40   // Returns a wake-up for the next pending delayed task (pending delayed tasks
41   // that are ripe may be ignored). If there are no such tasks (immediate tasks
42   // don't count) or queues are disabled it returns nullopt.
43   std::optional<WakeUp> GetNextDelayedWakeUp() const;
44 
45   // Debug info.
46   Value::Dict AsValue(TimeTicks now) const;
47 
has_pending_high_resolution_tasks()48   bool has_pending_high_resolution_tasks() const {
49     return pending_high_res_wake_up_count_;
50   }
51 
52   // Returns true if there are no pending delayed tasks.
empty()53   bool empty() const { return wake_up_queue_.empty(); }
54 
55   // Moves ready delayed tasks in TaskQueues to delayed WorkQueues, consuming
56   // expired wake-ups in the process.
57   void MoveReadyDelayedTasksToWorkQueues(LazyNow* lazy_now,
58                                          EnqueueOrder enqueue_order);
59 
60   // Schedule `queue` to wake up at certain time. Repeating calls with the same
61   // `queue` invalidate previous requests. Nullopt `wake_up` cancels a
62   // previously set wake up for `queue`.
63   void SetNextWakeUpForQueue(internal::TaskQueueImpl* queue,
64                              LazyNow* lazy_now,
65                              std::optional<WakeUp> wake_up);
66 
67   // Remove the TaskQueue from any internal data structures.
68   virtual void UnregisterQueue(internal::TaskQueueImpl* queue) = 0;
69 
70   // Removes all canceled delayed tasks from the front of the queue. After
71   // calling this, GetNextDelayedWakeUp() is guaranteed to return a wake up time
72   // for a non-canceled task.
73   void RemoveAllCanceledDelayedTasksFromFront(LazyNow* lazy_now);
74 
75  protected:
76   explicit WakeUpQueue(
77       scoped_refptr<const internal::AssociatedThreadId> associated_thread);
78 
79   // Called every time the next `next_wake_up` changes. std::nullopt is used to
80   // cancel the next wake-up. Subclasses may use this to tell SequenceManager to
81   // schedule the next wake-up at the given time.
82   virtual void OnNextWakeUpChanged(LazyNow* lazy_now,
83                                    std::optional<WakeUp> next_wake_up) = 0;
84 
85   virtual const char* GetName() const = 0;
86 
87  private:
88   friend class MockWakeUpQueue;
89 
90   struct ScheduledWakeUp {
91     WakeUp wake_up;
92     // RAW_PTR_EXCLUSION: Performance reasons (based on analysis of
93     // speedometer3).
94     RAW_PTR_EXCLUSION internal::TaskQueueImpl* queue = nullptr;
95 
96     bool operator>(const ScheduledWakeUp& other) const {
97       return wake_up.latest_time() > other.wake_up.latest_time();
98     }
99 
SetHeapHandleScheduledWakeUp100     void SetHeapHandle(HeapHandle handle) {
101       DCHECK(handle.IsValid());
102       queue->set_heap_handle(handle);
103     }
104 
ClearHeapHandleScheduledWakeUp105     void ClearHeapHandle() {
106       DCHECK(queue->heap_handle().IsValid());
107       queue->set_heap_handle(HeapHandle());
108     }
109 
GetHeapHandleScheduledWakeUp110     HeapHandle GetHeapHandle() const { return queue->heap_handle(); }
111   };
112 
113   IntrusiveHeap<ScheduledWakeUp, std::greater<>> wake_up_queue_;
114   int pending_high_res_wake_up_count_ = 0;
115 
116   const scoped_refptr<const internal::AssociatedThreadId> associated_thread_;
117 };
118 
119 // Default WakeUpQueue implementation that forwards wake-ups to
120 // `sequence_manager_`.
121 class BASE_EXPORT DefaultWakeUpQueue : public WakeUpQueue {
122  public:
123   DefaultWakeUpQueue(
124       scoped_refptr<internal::AssociatedThreadId> associated_thread,
125       internal::SequenceManagerImpl* sequence_manager);
126   ~DefaultWakeUpQueue() override;
127 
128  private:
129   // WakeUpQueue implementation:
130   void OnNextWakeUpChanged(LazyNow* lazy_now,
131                            std::optional<WakeUp> wake_up) override;
132   const char* GetName() const override;
133   void UnregisterQueue(internal::TaskQueueImpl* queue) override;
134 
135   raw_ptr<internal::SequenceManagerImpl> sequence_manager_;  // Not owned.
136 };
137 
138 // WakeUpQueue implementation that doesn't sends wake-ups to
139 // any SequenceManager, such that task queues don't cause wake-ups.
140 class BASE_EXPORT NonWakingWakeUpQueue : public WakeUpQueue {
141  public:
142   explicit NonWakingWakeUpQueue(
143       scoped_refptr<internal::AssociatedThreadId> associated_thread);
144   ~NonWakingWakeUpQueue() override;
145 
146  private:
147   // WakeUpQueue implementation:
148   void OnNextWakeUpChanged(LazyNow* lazy_now,
149                            std::optional<WakeUp> wake_up) override;
150   const char* GetName() const override;
151   void UnregisterQueue(internal::TaskQueueImpl* queue) override;
152 };
153 
154 }  // namespace internal
155 }  // namespace sequence_manager
156 }  // namespace base
157 
158 #endif  // BASE_TASK_SEQUENCE_MANAGER_WAKE_UP_QUEUE_H_
159