xref: /aosp_15_r20/external/cronet/base/task/thread_pool/delayed_task_manager.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #include <optional>
10 
11 #include "base/base_export.h"
12 #include "base/containers/intrusive_heap.h"
13 #include "base/functional/callback.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/synchronization/atomic_flag.h"
17 #include "base/task/common/checked_lock.h"
18 #include "base/task/delay_policy.h"
19 #include "base/task/task_features.h"
20 #include "base/task/thread_pool/task.h"
21 #include "base/thread_annotations.h"
22 #include "base/time/default_tick_clock.h"
23 #include "base/time/tick_clock.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.
54   void AddDelayedTask(Task task, PostTaskNowCallback post_task_now_callback);
55 
56   // Pop and post all the ripe tasks in the delayed task queue.
57   void ProcessRipeTasks();
58 
59   // Returns the |delayed_run_time| of the next scheduled task, if any.
60   std::optional<TimeTicks> NextScheduledRunTime() const;
61 
62   // Returns the DelayPolicy for the next delayed task.
63   subtle::DelayPolicy TopTaskDelayPolicyForTesting() const;
64 
65   // Must be invoked before deleting the delayed task manager. The caller must
66   // flush tasks posted to the service thread by this before deleting the
67   // delayed task manager.
68   void Shutdown();
69 
70  private:
71   struct DelayedTask {
72     DelayedTask();
73     DelayedTask(Task task, PostTaskNowCallback callback);
74     DelayedTask(DelayedTask&& other);
75     DelayedTask(const DelayedTask&) = delete;
76     DelayedTask& operator=(const DelayedTask&) = delete;
77     ~DelayedTask();
78 
79     // Required by IntrusiveHeap::insert().
80     DelayedTask& operator=(DelayedTask&& other);
81 
82     // Used for a min-heap.
83     bool operator>(const DelayedTask& other) const;
84 
85     Task task;
86     PostTaskNowCallback callback;
87 
88     // Mark the delayed task as scheduled. Since the sort key is
89     // |task.delayed_run_time|, it does not alter sort order when it is called.
90     void SetScheduled();
91 
92     // Required by IntrusiveHeap.
SetHeapHandleDelayedTask93     void SetHeapHandle(const HeapHandle& handle) {}
94 
95     // Required by IntrusiveHeap.
ClearHeapHandleDelayedTask96     void ClearHeapHandle() {}
97 
98     // Required by IntrusiveHeap.
GetHeapHandleDelayedTask99     HeapHandle GetHeapHandle() const { return HeapHandle::Invalid(); }
100   };
101 
102   // Get the time at which to schedule the next |ProcessRipeTasks()| execution,
103   // or TimeTicks::Max() if none needs to be scheduled (i.e. no task, or next
104   // task already scheduled).
105   std::pair<TimeTicks, subtle::DelayPolicy>
106   GetTimeAndDelayPolicyToScheduleProcessRipeTasksLockRequired()
107       EXCLUSIVE_LOCKS_REQUIRED(queue_lock_);
108 
109   // Schedule |ProcessRipeTasks()| on the service thread to be executed when
110   // the next task is ripe.
111   void ScheduleProcessRipeTasksOnServiceThread();
112 
113   const RepeatingClosure process_ripe_tasks_closure_;
114   const RepeatingClosure schedule_process_ripe_tasks_closure_;
115 
116   const raw_ptr<const TickClock> tick_clock_;
117 
118   // Synchronizes access to |delayed_task_queue_| and the setting of
119   // |service_thread_task_runner_|. Once |service_thread_task_runner_| is set,
120   // it is never modified. It is therefore safe to access
121   // |service_thread_task_runner_| without synchronization once it is observed
122   // that it is non-null.
123   mutable CheckedLock queue_lock_{UniversalSuccessor()};
124 
125   scoped_refptr<SequencedTaskRunner> service_thread_task_runner_;
126 
127   DelayedTaskHandle delayed_task_handle_ GUARDED_BY_CONTEXT(sequence_checker_);
128 
129   IntrusiveHeap<DelayedTask, std::greater<>> delayed_task_queue_
130       GUARDED_BY(queue_lock_);
131 
132   base::TimeDelta max_precise_delay GUARDED_BY(queue_lock_) =
133       kDefaultMaxPreciseDelay;
134 
135   SEQUENCE_CHECKER(sequence_checker_);
136 };
137 
138 }  // namespace internal
139 }  // namespace base
140 
141 #endif  // BASE_TASK_THREAD_POOL_DELAYED_TASK_MANAGER_H_
142