1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/task/thread_pool/sequence.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <utility>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/critical_closure.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/memory/stack_allocated.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/task/task_features.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker namespace base {
19*6777b538SAndroid Build Coastguard Worker namespace internal {
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace {
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker // Asserts that a lock is acquired and annotates the scope such that
24*6777b538SAndroid Build Coastguard Worker // base/thread_annotations.h can recognize that the lock is acquired.
25*6777b538SAndroid Build Coastguard Worker class SCOPED_LOCKABLE AnnotateLockAcquired {
26*6777b538SAndroid Build Coastguard Worker STACK_ALLOCATED();
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker public:
29*6777b538SAndroid Build Coastguard Worker explicit AnnotateLockAcquired(const CheckedLock& lock)
EXCLUSIVE_LOCK_FUNCTION(lock)30*6777b538SAndroid Build Coastguard Worker EXCLUSIVE_LOCK_FUNCTION(lock)
31*6777b538SAndroid Build Coastguard Worker : acquired_lock_(lock) {
32*6777b538SAndroid Build Coastguard Worker acquired_lock_.AssertAcquired();
33*6777b538SAndroid Build Coastguard Worker }
34*6777b538SAndroid Build Coastguard Worker
UNLOCK_FUNCTION()35*6777b538SAndroid Build Coastguard Worker ~AnnotateLockAcquired() UNLOCK_FUNCTION() { acquired_lock_.AssertAcquired(); }
36*6777b538SAndroid Build Coastguard Worker
37*6777b538SAndroid Build Coastguard Worker private:
38*6777b538SAndroid Build Coastguard Worker const CheckedLock& acquired_lock_;
39*6777b538SAndroid Build Coastguard Worker };
40*6777b538SAndroid Build Coastguard Worker
MaybeMakeCriticalClosure(TaskShutdownBehavior shutdown_behavior,Task & task)41*6777b538SAndroid Build Coastguard Worker void MaybeMakeCriticalClosure(TaskShutdownBehavior shutdown_behavior,
42*6777b538SAndroid Build Coastguard Worker Task& task) {
43*6777b538SAndroid Build Coastguard Worker switch (shutdown_behavior) {
44*6777b538SAndroid Build Coastguard Worker case TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN:
45*6777b538SAndroid Build Coastguard Worker // Nothing to do.
46*6777b538SAndroid Build Coastguard Worker break;
47*6777b538SAndroid Build Coastguard Worker case TaskShutdownBehavior::SKIP_ON_SHUTDOWN:
48*6777b538SAndroid Build Coastguard Worker // MakeCriticalClosure() is arguably useful for SKIP_ON_SHUTDOWN, possibly
49*6777b538SAndroid Build Coastguard Worker // in combination with is_immediate=false. However, SKIP_ON_SHUTDOWN is
50*6777b538SAndroid Build Coastguard Worker // the default and hence the theoretical benefits don't warrant the
51*6777b538SAndroid Build Coastguard Worker // performance implications.
52*6777b538SAndroid Build Coastguard Worker break;
53*6777b538SAndroid Build Coastguard Worker case TaskShutdownBehavior::BLOCK_SHUTDOWN:
54*6777b538SAndroid Build Coastguard Worker task.task =
55*6777b538SAndroid Build Coastguard Worker MakeCriticalClosure(task.posted_from, std::move(task.task),
56*6777b538SAndroid Build Coastguard Worker /*is_immediate=*/task.delayed_run_time.is_null());
57*6777b538SAndroid Build Coastguard Worker break;
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker } // namespace
62*6777b538SAndroid Build Coastguard Worker
Transaction(Sequence * sequence)63*6777b538SAndroid Build Coastguard Worker Sequence::Transaction::Transaction(Sequence* sequence)
64*6777b538SAndroid Build Coastguard Worker : TaskSource::Transaction(sequence) {}
65*6777b538SAndroid Build Coastguard Worker
66*6777b538SAndroid Build Coastguard Worker Sequence::Transaction::Transaction(Sequence::Transaction&& other) = default;
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker Sequence::Transaction::~Transaction() = default;
69*6777b538SAndroid Build Coastguard Worker
WillPushImmediateTask()70*6777b538SAndroid Build Coastguard Worker bool Sequence::Transaction::WillPushImmediateTask() {
71*6777b538SAndroid Build Coastguard Worker // In a Transaction.
72*6777b538SAndroid Build Coastguard Worker AnnotateLockAcquired annotate(sequence()->lock_);
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker bool was_immediate =
75*6777b538SAndroid Build Coastguard Worker sequence()->is_immediate_.exchange(true, std::memory_order_relaxed);
76*6777b538SAndroid Build Coastguard Worker return !was_immediate;
77*6777b538SAndroid Build Coastguard Worker }
78*6777b538SAndroid Build Coastguard Worker
PushImmediateTask(Task task)79*6777b538SAndroid Build Coastguard Worker void Sequence::Transaction::PushImmediateTask(Task task) {
80*6777b538SAndroid Build Coastguard Worker // In a Transaction.
81*6777b538SAndroid Build Coastguard Worker AnnotateLockAcquired annotate(sequence()->lock_);
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Worker // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167
84*6777b538SAndroid Build Coastguard Worker // for details.
85*6777b538SAndroid Build Coastguard Worker CHECK(task.task);
86*6777b538SAndroid Build Coastguard Worker DCHECK(!task.queue_time.is_null());
87*6777b538SAndroid Build Coastguard Worker DCHECK(sequence()->is_immediate_.load(std::memory_order_relaxed));
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker bool was_unretained = sequence()->IsEmpty() && !sequence()->has_worker_;
90*6777b538SAndroid Build Coastguard Worker bool queue_was_empty = sequence()->queue_.empty();
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker MaybeMakeCriticalClosure(sequence()->traits_.shutdown_behavior(), task);
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker sequence()->queue_.push(std::move(task));
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker if (queue_was_empty)
97*6777b538SAndroid Build Coastguard Worker sequence()->UpdateReadyTimes();
98*6777b538SAndroid Build Coastguard Worker
99*6777b538SAndroid Build Coastguard Worker // AddRef() matched by manual Release() when the sequence has no more tasks
100*6777b538SAndroid Build Coastguard Worker // to run (in DidProcessTask() or Clear()).
101*6777b538SAndroid Build Coastguard Worker if (was_unretained && sequence()->task_runner())
102*6777b538SAndroid Build Coastguard Worker sequence()->task_runner()->AddRef();
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker
PushDelayedTask(Task task)105*6777b538SAndroid Build Coastguard Worker bool Sequence::Transaction::PushDelayedTask(Task task) {
106*6777b538SAndroid Build Coastguard Worker // In a Transaction.
107*6777b538SAndroid Build Coastguard Worker AnnotateLockAcquired annotate(sequence()->lock_);
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167
110*6777b538SAndroid Build Coastguard Worker // for details.
111*6777b538SAndroid Build Coastguard Worker CHECK(task.task);
112*6777b538SAndroid Build Coastguard Worker DCHECK(!task.queue_time.is_null());
113*6777b538SAndroid Build Coastguard Worker DCHECK(!task.delayed_run_time.is_null());
114*6777b538SAndroid Build Coastguard Worker
115*6777b538SAndroid Build Coastguard Worker bool top_will_change = sequence()->DelayedSortKeyWillChange(task);
116*6777b538SAndroid Build Coastguard Worker bool was_empty = sequence()->IsEmpty();
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker MaybeMakeCriticalClosure(sequence()->traits_.shutdown_behavior(), task);
119*6777b538SAndroid Build Coastguard Worker
120*6777b538SAndroid Build Coastguard Worker sequence()->delayed_queue_.insert(std::move(task));
121*6777b538SAndroid Build Coastguard Worker
122*6777b538SAndroid Build Coastguard Worker if (sequence()->queue_.empty())
123*6777b538SAndroid Build Coastguard Worker sequence()->UpdateReadyTimes();
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker // AddRef() matched by manual Release() when the sequence has no more tasks
126*6777b538SAndroid Build Coastguard Worker // to run (in DidProcessTask() or Clear()).
127*6777b538SAndroid Build Coastguard Worker if (was_empty && !sequence()->has_worker_ && sequence()->task_runner())
128*6777b538SAndroid Build Coastguard Worker sequence()->task_runner()->AddRef();
129*6777b538SAndroid Build Coastguard Worker
130*6777b538SAndroid Build Coastguard Worker return top_will_change;
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker
133*6777b538SAndroid Build Coastguard Worker // Delayed tasks are ordered by latest_delayed_run_time(). The top task may
134*6777b538SAndroid Build Coastguard Worker // not be the first task eligible to run, but tasks will always become ripe
135*6777b538SAndroid Build Coastguard Worker // before their latest_delayed_run_time().
operator ()(const Task & lhs,const Task & rhs) const136*6777b538SAndroid Build Coastguard Worker bool Sequence::DelayedTaskGreater::operator()(const Task& lhs,
137*6777b538SAndroid Build Coastguard Worker const Task& rhs) const {
138*6777b538SAndroid Build Coastguard Worker TimeTicks lhs_latest_delayed_run_time = lhs.latest_delayed_run_time();
139*6777b538SAndroid Build Coastguard Worker TimeTicks rhs_latest_delayed_run_time = rhs.latest_delayed_run_time();
140*6777b538SAndroid Build Coastguard Worker return std::tie(lhs_latest_delayed_run_time, lhs.sequence_num) >
141*6777b538SAndroid Build Coastguard Worker std::tie(rhs_latest_delayed_run_time, rhs.sequence_num);
142*6777b538SAndroid Build Coastguard Worker }
143*6777b538SAndroid Build Coastguard Worker
WillRunTask()144*6777b538SAndroid Build Coastguard Worker TaskSource::RunStatus Sequence::WillRunTask() {
145*6777b538SAndroid Build Coastguard Worker // There should never be a second call to WillRunTask() before DidProcessTask
146*6777b538SAndroid Build Coastguard Worker // since the RunStatus is always marked a saturated.
147*6777b538SAndroid Build Coastguard Worker DCHECK(!has_worker_);
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker // It's ok to access |has_worker_| outside of a Transaction since
150*6777b538SAndroid Build Coastguard Worker // WillRunTask() is externally synchronized, always called in sequence with
151*6777b538SAndroid Build Coastguard Worker // TakeTask() and DidProcessTask() and only called if HasReadyTasks(), which
152*6777b538SAndroid Build Coastguard Worker // means it won't race with Push[Immediate/Delayed]Task().
153*6777b538SAndroid Build Coastguard Worker has_worker_ = true;
154*6777b538SAndroid Build Coastguard Worker return RunStatus::kAllowedSaturated;
155*6777b538SAndroid Build Coastguard Worker }
156*6777b538SAndroid Build Coastguard Worker
OnBecomeReady()157*6777b538SAndroid Build Coastguard Worker bool Sequence::OnBecomeReady() {
158*6777b538SAndroid Build Coastguard Worker DCHECK(!has_worker_);
159*6777b538SAndroid Build Coastguard Worker // std::memory_order_relaxed is sufficient because no other state is
160*6777b538SAndroid Build Coastguard Worker // synchronized with |is_immediate_| outside of |lock_|.
161*6777b538SAndroid Build Coastguard Worker return !is_immediate_.exchange(true, std::memory_order_relaxed);
162*6777b538SAndroid Build Coastguard Worker }
163*6777b538SAndroid Build Coastguard Worker
GetRemainingConcurrency() const164*6777b538SAndroid Build Coastguard Worker size_t Sequence::GetRemainingConcurrency() const {
165*6777b538SAndroid Build Coastguard Worker return 1;
166*6777b538SAndroid Build Coastguard Worker }
167*6777b538SAndroid Build Coastguard Worker
TakeNextImmediateTask()168*6777b538SAndroid Build Coastguard Worker Task Sequence::TakeNextImmediateTask() {
169*6777b538SAndroid Build Coastguard Worker Task next_task = std::move(queue_.front());
170*6777b538SAndroid Build Coastguard Worker queue_.pop();
171*6777b538SAndroid Build Coastguard Worker return next_task;
172*6777b538SAndroid Build Coastguard Worker }
173*6777b538SAndroid Build Coastguard Worker
TakeEarliestTask()174*6777b538SAndroid Build Coastguard Worker Task Sequence::TakeEarliestTask() {
175*6777b538SAndroid Build Coastguard Worker if (queue_.empty())
176*6777b538SAndroid Build Coastguard Worker return delayed_queue_.take_top();
177*6777b538SAndroid Build Coastguard Worker
178*6777b538SAndroid Build Coastguard Worker if (delayed_queue_.empty())
179*6777b538SAndroid Build Coastguard Worker return TakeNextImmediateTask();
180*6777b538SAndroid Build Coastguard Worker
181*6777b538SAndroid Build Coastguard Worker // Both queues contain at least a task. Decide from which one the task should
182*6777b538SAndroid Build Coastguard Worker // be taken.
183*6777b538SAndroid Build Coastguard Worker if (queue_.front().queue_time <=
184*6777b538SAndroid Build Coastguard Worker delayed_queue_.top().latest_delayed_run_time())
185*6777b538SAndroid Build Coastguard Worker return TakeNextImmediateTask();
186*6777b538SAndroid Build Coastguard Worker
187*6777b538SAndroid Build Coastguard Worker return delayed_queue_.take_top();
188*6777b538SAndroid Build Coastguard Worker }
189*6777b538SAndroid Build Coastguard Worker
UpdateReadyTimes()190*6777b538SAndroid Build Coastguard Worker void Sequence::UpdateReadyTimes() {
191*6777b538SAndroid Build Coastguard Worker DCHECK(!IsEmpty());
192*6777b538SAndroid Build Coastguard Worker if (queue_.empty()) {
193*6777b538SAndroid Build Coastguard Worker latest_ready_time_.store(delayed_queue_.top().latest_delayed_run_time(),
194*6777b538SAndroid Build Coastguard Worker std::memory_order_relaxed);
195*6777b538SAndroid Build Coastguard Worker earliest_ready_time_.store(delayed_queue_.top().earliest_delayed_run_time(),
196*6777b538SAndroid Build Coastguard Worker std::memory_order_relaxed);
197*6777b538SAndroid Build Coastguard Worker return;
198*6777b538SAndroid Build Coastguard Worker }
199*6777b538SAndroid Build Coastguard Worker
200*6777b538SAndroid Build Coastguard Worker if (delayed_queue_.empty()) {
201*6777b538SAndroid Build Coastguard Worker latest_ready_time_.store(queue_.front().queue_time,
202*6777b538SAndroid Build Coastguard Worker std::memory_order_relaxed);
203*6777b538SAndroid Build Coastguard Worker } else {
204*6777b538SAndroid Build Coastguard Worker latest_ready_time_.store(
205*6777b538SAndroid Build Coastguard Worker std::min(queue_.front().queue_time,
206*6777b538SAndroid Build Coastguard Worker delayed_queue_.top().latest_delayed_run_time()),
207*6777b538SAndroid Build Coastguard Worker std::memory_order_relaxed);
208*6777b538SAndroid Build Coastguard Worker }
209*6777b538SAndroid Build Coastguard Worker earliest_ready_time_.store(TimeTicks(), std::memory_order_relaxed);
210*6777b538SAndroid Build Coastguard Worker }
211*6777b538SAndroid Build Coastguard Worker
TakeTask(TaskSource::Transaction * transaction)212*6777b538SAndroid Build Coastguard Worker Task Sequence::TakeTask(TaskSource::Transaction* transaction) {
213*6777b538SAndroid Build Coastguard Worker CheckedAutoLockMaybe auto_lock(transaction ? nullptr : &lock_);
214*6777b538SAndroid Build Coastguard Worker AnnotateLockAcquired annotate(lock_);
215*6777b538SAndroid Build Coastguard Worker
216*6777b538SAndroid Build Coastguard Worker DCHECK(has_worker_);
217*6777b538SAndroid Build Coastguard Worker DCHECK(is_immediate_.load(std::memory_order_relaxed));
218*6777b538SAndroid Build Coastguard Worker DCHECK(!queue_.empty() || !delayed_queue_.empty());
219*6777b538SAndroid Build Coastguard Worker
220*6777b538SAndroid Build Coastguard Worker auto next_task = TakeEarliestTask();
221*6777b538SAndroid Build Coastguard Worker
222*6777b538SAndroid Build Coastguard Worker if (!IsEmpty())
223*6777b538SAndroid Build Coastguard Worker UpdateReadyTimes();
224*6777b538SAndroid Build Coastguard Worker
225*6777b538SAndroid Build Coastguard Worker return next_task;
226*6777b538SAndroid Build Coastguard Worker }
227*6777b538SAndroid Build Coastguard Worker
DidProcessTask(TaskSource::Transaction * transaction)228*6777b538SAndroid Build Coastguard Worker bool Sequence::DidProcessTask(TaskSource::Transaction* transaction) {
229*6777b538SAndroid Build Coastguard Worker CheckedAutoLockMaybe auto_lock(transaction ? nullptr : &lock_);
230*6777b538SAndroid Build Coastguard Worker AnnotateLockAcquired annotate(lock_);
231*6777b538SAndroid Build Coastguard Worker
232*6777b538SAndroid Build Coastguard Worker // There should never be a call to DidProcessTask without an associated
233*6777b538SAndroid Build Coastguard Worker // WillRunTask().
234*6777b538SAndroid Build Coastguard Worker DCHECK(has_worker_);
235*6777b538SAndroid Build Coastguard Worker has_worker_ = false;
236*6777b538SAndroid Build Coastguard Worker
237*6777b538SAndroid Build Coastguard Worker // See comment on TaskSource::task_runner_ for lifetime management details.
238*6777b538SAndroid Build Coastguard Worker if (IsEmpty()) {
239*6777b538SAndroid Build Coastguard Worker is_immediate_.store(false, std::memory_order_relaxed);
240*6777b538SAndroid Build Coastguard Worker ReleaseTaskRunner();
241*6777b538SAndroid Build Coastguard Worker return false;
242*6777b538SAndroid Build Coastguard Worker }
243*6777b538SAndroid Build Coastguard Worker
244*6777b538SAndroid Build Coastguard Worker // Let the caller re-enqueue this non-empty Sequence regardless of
245*6777b538SAndroid Build Coastguard Worker // |run_result| so it can continue churning through this Sequence's tasks and
246*6777b538SAndroid Build Coastguard Worker // skip/delete them in the proper scope.
247*6777b538SAndroid Build Coastguard Worker return true;
248*6777b538SAndroid Build Coastguard Worker }
249*6777b538SAndroid Build Coastguard Worker
WillReEnqueue(TimeTicks now,TaskSource::Transaction * transaction)250*6777b538SAndroid Build Coastguard Worker bool Sequence::WillReEnqueue(TimeTicks now,
251*6777b538SAndroid Build Coastguard Worker TaskSource::Transaction* transaction) {
252*6777b538SAndroid Build Coastguard Worker CheckedAutoLockMaybe auto_lock(transaction ? nullptr : &lock_);
253*6777b538SAndroid Build Coastguard Worker AnnotateLockAcquired annotate(lock_);
254*6777b538SAndroid Build Coastguard Worker
255*6777b538SAndroid Build Coastguard Worker // This should always be called from a worker thread and it will be
256*6777b538SAndroid Build Coastguard Worker // called after DidProcessTask().
257*6777b538SAndroid Build Coastguard Worker DCHECK(is_immediate_.load(std::memory_order_relaxed));
258*6777b538SAndroid Build Coastguard Worker
259*6777b538SAndroid Build Coastguard Worker bool has_ready_tasks = HasReadyTasks(now);
260*6777b538SAndroid Build Coastguard Worker if (!has_ready_tasks)
261*6777b538SAndroid Build Coastguard Worker is_immediate_.store(false, std::memory_order_relaxed);
262*6777b538SAndroid Build Coastguard Worker
263*6777b538SAndroid Build Coastguard Worker return has_ready_tasks;
264*6777b538SAndroid Build Coastguard Worker }
265*6777b538SAndroid Build Coastguard Worker
DelayedSortKeyWillChange(const Task & delayed_task) const266*6777b538SAndroid Build Coastguard Worker bool Sequence::DelayedSortKeyWillChange(const Task& delayed_task) const {
267*6777b538SAndroid Build Coastguard Worker // If sequence has already been picked up by a worker or moved, no need to
268*6777b538SAndroid Build Coastguard Worker // proceed further here.
269*6777b538SAndroid Build Coastguard Worker if (is_immediate_.load(std::memory_order_relaxed)) {
270*6777b538SAndroid Build Coastguard Worker return false;
271*6777b538SAndroid Build Coastguard Worker }
272*6777b538SAndroid Build Coastguard Worker
273*6777b538SAndroid Build Coastguard Worker if (IsEmpty()) {
274*6777b538SAndroid Build Coastguard Worker return true;
275*6777b538SAndroid Build Coastguard Worker }
276*6777b538SAndroid Build Coastguard Worker
277*6777b538SAndroid Build Coastguard Worker return delayed_task.latest_delayed_run_time() <
278*6777b538SAndroid Build Coastguard Worker delayed_queue_.top().latest_delayed_run_time();
279*6777b538SAndroid Build Coastguard Worker }
280*6777b538SAndroid Build Coastguard Worker
HasReadyTasks(TimeTicks now) const281*6777b538SAndroid Build Coastguard Worker bool Sequence::HasReadyTasks(TimeTicks now) const {
282*6777b538SAndroid Build Coastguard Worker return now >= TS_UNCHECKED_READ(earliest_ready_time_)
283*6777b538SAndroid Build Coastguard Worker .load(std::memory_order_relaxed);
284*6777b538SAndroid Build Coastguard Worker }
285*6777b538SAndroid Build Coastguard Worker
HasImmediateTasks() const286*6777b538SAndroid Build Coastguard Worker bool Sequence::HasImmediateTasks() const {
287*6777b538SAndroid Build Coastguard Worker return !queue_.empty();
288*6777b538SAndroid Build Coastguard Worker }
289*6777b538SAndroid Build Coastguard Worker
GetSortKey() const290*6777b538SAndroid Build Coastguard Worker TaskSourceSortKey Sequence::GetSortKey() const {
291*6777b538SAndroid Build Coastguard Worker return TaskSourceSortKey(
292*6777b538SAndroid Build Coastguard Worker priority_racy(),
293*6777b538SAndroid Build Coastguard Worker TS_UNCHECKED_READ(latest_ready_time_).load(std::memory_order_relaxed));
294*6777b538SAndroid Build Coastguard Worker }
295*6777b538SAndroid Build Coastguard Worker
GetDelayedSortKey() const296*6777b538SAndroid Build Coastguard Worker TimeTicks Sequence::GetDelayedSortKey() const {
297*6777b538SAndroid Build Coastguard Worker return TS_UNCHECKED_READ(latest_ready_time_).load(std::memory_order_relaxed);
298*6777b538SAndroid Build Coastguard Worker }
299*6777b538SAndroid Build Coastguard Worker
Clear(TaskSource::Transaction * transaction)300*6777b538SAndroid Build Coastguard Worker std::optional<Task> Sequence::Clear(TaskSource::Transaction* transaction) {
301*6777b538SAndroid Build Coastguard Worker CheckedAutoLockMaybe auto_lock(transaction ? nullptr : &lock_);
302*6777b538SAndroid Build Coastguard Worker AnnotateLockAcquired annotate(lock_);
303*6777b538SAndroid Build Coastguard Worker
304*6777b538SAndroid Build Coastguard Worker // See comment on TaskSource::task_runner_ for lifetime management details.
305*6777b538SAndroid Build Coastguard Worker if (!IsEmpty() && !has_worker_) {
306*6777b538SAndroid Build Coastguard Worker ReleaseTaskRunner();
307*6777b538SAndroid Build Coastguard Worker }
308*6777b538SAndroid Build Coastguard Worker
309*6777b538SAndroid Build Coastguard Worker return Task(
310*6777b538SAndroid Build Coastguard Worker FROM_HERE,
311*6777b538SAndroid Build Coastguard Worker base::BindOnce(
312*6777b538SAndroid Build Coastguard Worker [](base::queue<Task> queue,
313*6777b538SAndroid Build Coastguard Worker base::IntrusiveHeap<Task, DelayedTaskGreater> delayed_queue) {
314*6777b538SAndroid Build Coastguard Worker while (!queue.empty())
315*6777b538SAndroid Build Coastguard Worker queue.pop();
316*6777b538SAndroid Build Coastguard Worker
317*6777b538SAndroid Build Coastguard Worker while (!delayed_queue.empty())
318*6777b538SAndroid Build Coastguard Worker delayed_queue.pop();
319*6777b538SAndroid Build Coastguard Worker },
320*6777b538SAndroid Build Coastguard Worker std::move(queue_), std::move(delayed_queue_)),
321*6777b538SAndroid Build Coastguard Worker TimeTicks(), TimeDelta(), TimeDelta(),
322*6777b538SAndroid Build Coastguard Worker static_cast<int>(reinterpret_cast<intptr_t>(this)));
323*6777b538SAndroid Build Coastguard Worker }
324*6777b538SAndroid Build Coastguard Worker
ReleaseTaskRunner()325*6777b538SAndroid Build Coastguard Worker void Sequence::ReleaseTaskRunner() {
326*6777b538SAndroid Build Coastguard Worker if (!task_runner())
327*6777b538SAndroid Build Coastguard Worker return;
328*6777b538SAndroid Build Coastguard Worker // No member access after this point, releasing |task_runner()| might delete
329*6777b538SAndroid Build Coastguard Worker // |this|.
330*6777b538SAndroid Build Coastguard Worker task_runner()->Release();
331*6777b538SAndroid Build Coastguard Worker }
332*6777b538SAndroid Build Coastguard Worker
Sequence(const TaskTraits & traits,SequencedTaskRunner * task_runner,TaskSourceExecutionMode execution_mode)333*6777b538SAndroid Build Coastguard Worker Sequence::Sequence(const TaskTraits& traits,
334*6777b538SAndroid Build Coastguard Worker SequencedTaskRunner* task_runner,
335*6777b538SAndroid Build Coastguard Worker TaskSourceExecutionMode execution_mode)
336*6777b538SAndroid Build Coastguard Worker : TaskSource(traits, execution_mode), task_runner_(task_runner) {}
337*6777b538SAndroid Build Coastguard Worker
338*6777b538SAndroid Build Coastguard Worker Sequence::~Sequence() = default;
339*6777b538SAndroid Build Coastguard Worker
BeginTransaction()340*6777b538SAndroid Build Coastguard Worker Sequence::Transaction Sequence::BeginTransaction() {
341*6777b538SAndroid Build Coastguard Worker return Transaction(this);
342*6777b538SAndroid Build Coastguard Worker }
343*6777b538SAndroid Build Coastguard Worker
GetExecutionEnvironment()344*6777b538SAndroid Build Coastguard Worker ExecutionEnvironment Sequence::GetExecutionEnvironment() {
345*6777b538SAndroid Build Coastguard Worker if (execution_mode() == TaskSourceExecutionMode::kSingleThread) {
346*6777b538SAndroid Build Coastguard Worker return {token_, &sequence_local_storage_,
347*6777b538SAndroid Build Coastguard Worker static_cast<SingleThreadTaskRunner*>(task_runner())};
348*6777b538SAndroid Build Coastguard Worker }
349*6777b538SAndroid Build Coastguard Worker return {token_, &sequence_local_storage_, task_runner()};
350*6777b538SAndroid Build Coastguard Worker }
351*6777b538SAndroid Build Coastguard Worker
IsEmpty() const352*6777b538SAndroid Build Coastguard Worker bool Sequence::IsEmpty() const {
353*6777b538SAndroid Build Coastguard Worker return queue_.empty() && delayed_queue_.empty();
354*6777b538SAndroid Build Coastguard Worker }
355*6777b538SAndroid Build Coastguard Worker
356*6777b538SAndroid Build Coastguard Worker } // namespace internal
357*6777b538SAndroid Build Coastguard Worker } // namespace base
358