| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/task_scheduler/sequence.h" |
| |
| #include <utility> |
| |
| #include "base/logging.h" |
| #include "base/time/time.h" |
| |
| namespace base { |
| namespace internal { |
| |
| Sequence::Sequence() = default; |
| |
| bool Sequence::PushTask(Task task) { |
| // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 |
| // for details. |
| CHECK(task.task); |
| DCHECK(task.sequenced_time.is_null()); |
| task.sequenced_time = base::TimeTicks::Now(); |
| |
| AutoSchedulerLock auto_lock(lock_); |
| ++num_tasks_per_priority_[static_cast<int>(task.traits.priority())]; |
| queue_.push(std::move(task)); |
| |
| // Return true if the sequence was empty before the push. |
| return queue_.size() == 1; |
| } |
| |
| Optional<Task> Sequence::TakeTask() { |
| AutoSchedulerLock auto_lock(lock_); |
| DCHECK(!queue_.empty()); |
| DCHECK(queue_.front().task); |
| |
| const int priority_index = static_cast<int>(queue_.front().traits.priority()); |
| DCHECK_GT(num_tasks_per_priority_[priority_index], 0U); |
| --num_tasks_per_priority_[priority_index]; |
| |
| return std::move(queue_.front()); |
| } |
| |
| bool Sequence::Pop() { |
| AutoSchedulerLock auto_lock(lock_); |
| DCHECK(!queue_.empty()); |
| DCHECK(!queue_.front().task); |
| queue_.pop(); |
| return queue_.empty(); |
| } |
| |
| SequenceSortKey Sequence::GetSortKey() const { |
| TaskPriority priority = TaskPriority::LOWEST; |
| base::TimeTicks next_task_sequenced_time; |
| |
| { |
| AutoSchedulerLock auto_lock(lock_); |
| DCHECK(!queue_.empty()); |
| |
| // Find the highest task priority in the sequence. |
| const int highest_priority_index = static_cast<int>(TaskPriority::HIGHEST); |
| const int lowest_priority_index = static_cast<int>(TaskPriority::LOWEST); |
| for (int i = highest_priority_index; i > lowest_priority_index; --i) { |
| if (num_tasks_per_priority_[i] > 0) { |
| priority = static_cast<TaskPriority>(i); |
| break; |
| } |
| } |
| |
| // Save the sequenced time of the next task in the sequence. |
| next_task_sequenced_time = queue_.front().sequenced_time; |
| } |
| |
| return SequenceSortKey(priority, next_task_sequenced_time); |
| } |
| |
| Sequence::~Sequence() = default; |
| |
| } // namespace internal |
| } // namespace base |