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