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