1 // Copyright 2022 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_THREAD_POOL_DELAYED_PRIORITY_QUEUE_H_ 6 #define BASE_TASK_THREAD_POOL_DELAYED_PRIORITY_QUEUE_H_ 7 8 #include "base/base_export.h" 9 #include "base/containers/intrusive_heap.h" 10 #include "base/stl_util.h" 11 #include "base/task/thread_pool/task_source.h" 12 #include "base/time/time.h" 13 14 namespace base::internal { 15 16 // A DelayedPriorityQueue holds TaskSources not ready to run yet. TaskSources 17 // are ordered by delayed runtime. This class is not thread-safe (requires 18 // external synchronization). 19 class BASE_EXPORT DelayedPriorityQueue { 20 public: 21 DelayedPriorityQueue(); 22 DelayedPriorityQueue(const DelayedPriorityQueue&) = delete; 23 DelayedPriorityQueue& operator=(const DelayedPriorityQueue&) = delete; 24 ~DelayedPriorityQueue(); 25 26 DelayedPriorityQueue& operator=(DelayedPriorityQueue&& other); 27 28 // Inserts |task_source| in the DelayedPriorityQueue with |delayed_sort_key|. 29 void Push(scoped_refptr<TaskSource> task_source, TimeTicks delayed_sort_key); 30 31 // Returns a delayed sort key representing the priority of the highest pending 32 // task in this DelayedPriorityQueue. Cannot be called on an empty 33 // DelayedPriorityQueue. 34 const TimeTicks PeekDelayedSortKey() const; 35 36 // Returns a pointer to the earliest-to-run TaskSource in this 37 // DelayedPriorityQueue. Cannot be called on an empty DelayedPriorityQueue. 38 scoped_refptr<TaskSource> PeekTaskSource() const; 39 40 // Removes and returns the highest priority TaskSource in this 41 // DelayedPriorityQueue. Cannot be called on an empty DelayedPriorityQueue. 42 scoped_refptr<TaskSource> PopTaskSource(); 43 44 // Removes |task_source| from the DelayedPriorityQueue. Returns a TaskSource 45 // which evaluates to true if successful, or false if |task_source| is not 46 // currently in the DelayedPriorityQueue or the DelayedPriorityQueue is empty. 47 scoped_refptr<TaskSource> RemoveTaskSource( 48 scoped_refptr<TaskSource> task_source); 49 50 // Updates the delayed sort key of |task_source| to |delayed_sort_key|, 51 // reordering |task_source| in the queue if necessary. No-ops if the 52 // TaskSource is not in the DelayedPriorityQueue or the DelayedPriorityQueue 53 // is empty. 54 void UpdateDelayedSortKey(scoped_refptr<TaskSource> task_source); 55 56 // Returns true if the DelayedPriorityQueue is empty. 57 bool IsEmpty() const; 58 59 // Returns the number of TaskSources in the DelayedPriorityQueue. 60 size_t Size() const; 61 62 // Set the DelayedPriorityQueue to empty all its TaskSources of Tasks when it 63 // is destroyed; needed to prevent memory leaks caused by a reference cycle 64 // (TaskSource -> Task -> TaskRunner -> TaskSource...) during test teardown. 65 void EnableFlushTaskSourcesOnDestroyForTesting(); 66 67 private: 68 // A class combining a TaskSource and the delayed_sort_key that determines 69 // its position in a PriorityQueue. 70 class TaskSourceAndDelayedSortKey; 71 72 struct DelayedPriorityQueueComparisonOperator { 73 bool operator()(const TaskSourceAndDelayedSortKey& lhs, 74 const TaskSourceAndDelayedSortKey& rhs) const; 75 }; 76 77 using ContainerType = IntrusiveHeap<TaskSourceAndDelayedSortKey, 78 DelayedPriorityQueueComparisonOperator>; 79 80 ContainerType container_; 81 82 // Should only be enabled by EnableFlushTaskSourcesOnDestroyForTesting(). 83 bool is_flush_task_sources_on_destroy_enabled_ = false; 84 }; 85 86 } // namespace base::internal 87 88 #endif // BASE_TASK_THREAD_POOL_DELAYED_PRIORITY_QUEUE_H_ 89