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