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