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