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