• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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_SEQUENCE_MANAGER_TASKS_H_
6 #define BASE_TASK_SEQUENCE_MANAGER_TASKS_H_
7 
8 #include "base/base_export.h"
9 #include "base/check.h"
10 #include "base/containers/intrusive_heap.h"
11 #include "base/dcheck_is_on.h"
12 #include "base/pending_task.h"
13 #include "base/task/delay_policy.h"
14 #include "base/task/sequence_manager/delayed_task_handle_delegate.h"
15 #include "base/task/sequence_manager/enqueue_order.h"
16 #include "base/task/sequenced_task_runner.h"
17 #include "third_party/abseil-cpp/absl/types/optional.h"
18 #include "third_party/abseil-cpp/absl/types/variant.h"
19 
20 namespace base {
21 namespace sequence_manager {
22 
23 using TaskType = uint8_t;
24 constexpr TaskType kTaskTypeNone = 0;
25 
26 class TaskOrder;
27 
28 namespace internal {
29 
30 // Wrapper around PostTask method arguments and the assigned task type.
31 // Eventually it becomes a PendingTask once accepted by a TaskQueueImpl.
32 struct BASE_EXPORT PostedTask {
33   explicit PostedTask(scoped_refptr<SequencedTaskRunner> task_runner,
34                       OnceClosure callback,
35                       Location location,
36                       TimeDelta delay = base::TimeDelta(),
37                       Nestable nestable = Nestable::kNestable,
38                       TaskType task_type = kTaskTypeNone,
39                       WeakPtr<DelayedTaskHandleDelegate>
40                           delayed_task_handle_delegate = nullptr);
41   explicit PostedTask(scoped_refptr<SequencedTaskRunner> task_runner,
42                       OnceClosure callback,
43                       Location location,
44                       TimeTicks delayed_run_time,
45                       subtle::DelayPolicy delay_policy,
46                       Nestable nestable = Nestable::kNestable,
47                       TaskType task_type = kTaskTypeNone,
48                       WeakPtr<DelayedTaskHandleDelegate>
49                           delayed_task_handle_delegate = nullptr);
50   PostedTask(PostedTask&& move_from) noexcept;
51   PostedTask(const PostedTask&) = delete;
52   PostedTask& operator=(const PostedTask&) = delete;
53   ~PostedTask();
54 
is_delayedPostedTask55   bool is_delayed() const {
56     return absl::holds_alternative<TimeTicks>(delay_or_delayed_run_time)
57                ? !absl::get<TimeTicks>(delay_or_delayed_run_time).is_null()
58                : !absl::get<TimeDelta>(delay_or_delayed_run_time).is_zero();
59   }
60 
61   OnceClosure callback;
62   Location location;
63   Nestable nestable = Nestable::kNestable;
64   TaskType task_type = kTaskTypeNone;
65   absl::variant<TimeDelta, TimeTicks> delay_or_delayed_run_time;
66   subtle::DelayPolicy delay_policy = subtle::DelayPolicy::kFlexibleNoSooner;
67   // The task runner this task is running on. Can be used by task runners that
68   // support posting back to the "current sequence".
69   scoped_refptr<SequencedTaskRunner> task_runner;
70   // The delegate for the DelayedTaskHandle, if this task was posted through
71   // PostCancelableDelayedTask(), nullptr otherwise.
72   WeakPtr<DelayedTaskHandleDelegate> delayed_task_handle_delegate;
73 };
74 
75 }  // namespace internal
76 
77 enum class WakeUpResolution { kLow, kHigh };
78 
79 // Represents a time at which a task wants to run.
80 struct WakeUp {
81   // is_null() for immediate wake up.
82   TimeTicks time;
83   // These are meaningless if is_immediate().
84   TimeDelta leeway;
85   WakeUpResolution resolution = WakeUpResolution::kLow;
86   subtle::DelayPolicy delay_policy = subtle::DelayPolicy::kFlexibleNoSooner;
87 
88   bool operator!=(const WakeUp& other) const {
89     return time != other.time || leeway != other.leeway ||
90            resolution != other.resolution || delay_policy != other.delay_policy;
91   }
92 
93   bool operator==(const WakeUp& other) const { return !(*this != other); }
94 
is_immediateWakeUp95   bool is_immediate() const { return time.is_null(); }
96 
97   TimeTicks earliest_time() const;
98   TimeTicks latest_time() const;
99 };
100 
101 // PendingTask with extra metadata for SequenceManager.
102 struct BASE_EXPORT Task : public PendingTask {
103   Task(internal::PostedTask posted_task,
104        EnqueueOrder sequence_order,
105        EnqueueOrder enqueue_order = EnqueueOrder(),
106        TimeTicks queue_time = TimeTicks(),
107        WakeUpResolution wake_up_resolution = WakeUpResolution::kLow,
108        TimeDelta leeway = TimeDelta());
109   Task(Task&& move_from);
110   ~Task();
111   Task& operator=(Task&& other);
112 
113   // SequenceManager is particularly sensitive to enqueue order,
114   // so we have accessors for safety.
enqueue_orderTask115   EnqueueOrder enqueue_order() const {
116     DCHECK(enqueue_order_);
117     return enqueue_order_;
118   }
119 
set_enqueue_orderTask120   void set_enqueue_order(EnqueueOrder enqueue_order) {
121     DCHECK(!enqueue_order_);
122     enqueue_order_ = enqueue_order;
123   }
124 
enqueue_order_setTask125   bool enqueue_order_set() const { return enqueue_order_; }
126 
127   TaskOrder task_order() const;
128 
129   // OK to dispatch from a nested loop.
130   Nestable nestable = Nestable::kNonNestable;
131 
132   // Needs high resolution timers.
133   bool is_high_res = false;
134 
135   TaskType task_type;
136 
137   // The task runner this task is running on. Can be used by task runners that
138   // support posting back to the "current sequence".
139   scoped_refptr<SequencedTaskRunner> task_runner;
140 
141 #if DCHECK_IS_ON()
142   bool cross_thread_;
143 #endif
144 
145   // Implement the intrusive heap contract.
146   void SetHeapHandle(HeapHandle heap_handle);
147   void ClearHeapHandle();
148   HeapHandle GetHeapHandle() const;
149 
150   // Returns true if this task was canceled, either through weak pointer
151   // invalidation or through |delayed_task_handle_delegate_|.
152   bool IsCanceled() const;
153 
154   // Must be invoked before running the task. Returns true if the task must run
155   // (any delayed task handle will have been invalidated by this method), false
156   // if it mustn't run (e.g. delayed task handle was invalidated prior to
157   // calling this method).
158   bool WillRunTask();
159 
160  private:
161   // `enqueue_order_` is the primary component used to order tasks (see
162   // `TaskOrder`). For immediate tasks, `enqueue_order` is set when posted, but
163   // for delayed tasks it's not defined until they are enqueued. This is because
164   // otherwise delayed tasks could run before an immediate task posted after the
165   // delayed task.
166   EnqueueOrder enqueue_order_;
167 
168   // The delegate for the DelayedTaskHandle, if this task was posted through
169   // `PostCancelableDelayedTask()`, not set otherwise. The task is canceled if
170   // `WeakPtr::WasInvalidated` is true. Note: if the task was not posted via
171   // `PostCancelableDelayedTask()`. the weak pointer won't be valid, but
172   // `WeakPtr::WasInvalidated` will be false.
173   WeakPtr<internal::DelayedTaskHandleDelegate> delayed_task_handle_delegate_;
174 };
175 
176 }  // namespace sequence_manager
177 }  // namespace base
178 
179 #endif  // BASE_TASK_SEQUENCE_MANAGER_TASKS_H_
180