xref: /aosp_15_r20/external/cronet/base/task/thread_pool/sequence.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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