• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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