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