1 // Copyright 2016 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_TASK_MANAGER_H_ 6 #define BASE_TASK_THREAD_POOL_DELAYED_TASK_MANAGER_H_ 7 8 #include <functional> 9 10 #include "base/base_export.h" 11 #include "base/containers/intrusive_heap.h" 12 #include "base/functional/callback.h" 13 #include "base/memory/ptr_util.h" 14 #include "base/memory/raw_ptr.h" 15 #include "base/synchronization/atomic_flag.h" 16 #include "base/task/common/checked_lock.h" 17 #include "base/task/delay_policy.h" 18 #include "base/task/task_features.h" 19 #include "base/task/thread_pool/task.h" 20 #include "base/thread_annotations.h" 21 #include "base/time/default_tick_clock.h" 22 #include "base/time/tick_clock.h" 23 #include "third_party/abseil-cpp/absl/types/optional.h" 24 25 namespace base { 26 27 class SequencedTaskRunner; 28 29 namespace internal { 30 31 // The DelayedTaskManager forwards tasks to post task callbacks when they become 32 // ripe for execution. Tasks are not forwarded before Start() is called. This 33 // class is thread-safe. 34 class BASE_EXPORT DelayedTaskManager { 35 public: 36 // Posts |task| for execution immediately. 37 using PostTaskNowCallback = OnceCallback<void(Task task)>; 38 39 // |tick_clock| can be specified for testing. 40 DelayedTaskManager( 41 const TickClock* tick_clock = DefaultTickClock::GetInstance()); 42 DelayedTaskManager(const DelayedTaskManager&) = delete; 43 DelayedTaskManager& operator=(const DelayedTaskManager&) = delete; 44 ~DelayedTaskManager(); 45 46 // Starts the delayed task manager, allowing past and future tasks to be 47 // forwarded to their callbacks as they become ripe for execution. 48 // |service_thread_task_runner| posts tasks to the ThreadPool service 49 // thread. 50 void Start(scoped_refptr<SequencedTaskRunner> service_thread_task_runner); 51 52 // Schedules a call to |post_task_now_callback| with |task| as argument when 53 // |task| is ripe for execution. |task_runner| is passed to retain a 54 // reference until |task| is ripe. 55 void AddDelayedTask(Task task, 56 PostTaskNowCallback post_task_now_callback, 57 scoped_refptr<TaskRunner> task_runner); 58 59 // Pop and post all the ripe tasks in the delayed task queue. 60 void ProcessRipeTasks(); 61 62 // Returns the |delayed_run_time| of the next scheduled task, if any. 63 absl::optional<TimeTicks> NextScheduledRunTime() const; 64 65 // Returns the DelayPolicy for the next delayed task. 66 subtle::DelayPolicy TopTaskDelayPolicyForTesting() const; 67 68 // Must be invoked before deleting the delayed task manager. The caller must 69 // flush tasks posted to the service thread by this before deleting the 70 // delayed task manager. 71 void Shutdown(); 72 73 private: 74 struct DelayedTask { 75 DelayedTask(); 76 DelayedTask(Task task, 77 PostTaskNowCallback callback, 78 scoped_refptr<TaskRunner> task_runner); 79 DelayedTask(DelayedTask&& other); 80 DelayedTask(const DelayedTask&) = delete; 81 DelayedTask& operator=(const DelayedTask&) = delete; 82 ~DelayedTask(); 83 84 // Required by IntrusiveHeap::insert(). 85 DelayedTask& operator=(DelayedTask&& other); 86 87 // Used for a min-heap. 88 bool operator>(const DelayedTask& other) const; 89 90 Task task; 91 PostTaskNowCallback callback; 92 scoped_refptr<TaskRunner> task_runner; 93 94 // Mark the delayed task as scheduled. Since the sort key is 95 // |task.delayed_run_time|, it does not alter sort order when it is called. 96 void SetScheduled(); 97 98 // Required by IntrusiveHeap. SetHeapHandleDelayedTask99 void SetHeapHandle(const HeapHandle& handle) {} 100 101 // Required by IntrusiveHeap. ClearHeapHandleDelayedTask102 void ClearHeapHandle() {} 103 104 // Required by IntrusiveHeap. GetHeapHandleDelayedTask105 HeapHandle GetHeapHandle() const { return HeapHandle::Invalid(); } 106 }; 107 108 // Get the time at which to schedule the next |ProcessRipeTasks()| execution, 109 // or TimeTicks::Max() if none needs to be scheduled (i.e. no task, or next 110 // task already scheduled). 111 std::pair<TimeTicks, subtle::DelayPolicy> 112 GetTimeAndDelayPolicyToScheduleProcessRipeTasksLockRequired() 113 EXCLUSIVE_LOCKS_REQUIRED(queue_lock_); 114 115 // Schedule |ProcessRipeTasks()| on the service thread to be executed when 116 // the next task is ripe. 117 void ScheduleProcessRipeTasksOnServiceThread(); 118 119 const RepeatingClosure process_ripe_tasks_closure_; 120 const RepeatingClosure schedule_process_ripe_tasks_closure_; 121 122 const raw_ptr<const TickClock> tick_clock_; 123 124 // Synchronizes access to |delayed_task_queue_| and the setting of 125 // |service_thread_task_runner_|. Once |service_thread_task_runner_| is set, 126 // it is never modified. It is therefore safe to access 127 // |service_thread_task_runner_| without synchronization once it is observed 128 // that it is non-null. 129 mutable CheckedLock queue_lock_{UniversalSuccessor()}; 130 131 scoped_refptr<SequencedTaskRunner> service_thread_task_runner_; 132 133 DelayedTaskHandle delayed_task_handle_ GUARDED_BY_CONTEXT(sequence_checker_); 134 135 IntrusiveHeap<DelayedTask, std::greater<>> delayed_task_queue_ 136 GUARDED_BY(queue_lock_); 137 138 bool align_wake_ups_ GUARDED_BY(queue_lock_) = false; 139 base::TimeDelta max_precise_delay GUARDED_BY(queue_lock_) = 140 kDefaultMaxPreciseDelay; 141 142 SEQUENCE_CHECKER(sequence_checker_); 143 }; 144 145 } // namespace internal 146 } // namespace base 147 148 #endif // BASE_TASK_THREAD_POOL_DELAYED_TASK_MANAGER_H_ 149