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