| // 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()); | 
 | } | 
 |  | 
 | TaskTraits Sequence::PeekTaskTraits() const { | 
 |   AutoSchedulerLock auto_lock(lock_); | 
 |   DCHECK(!queue_.empty()); | 
 |   DCHECK(queue_.front().task); | 
 |   return queue_.front().traits; | 
 | } | 
 |  | 
 | 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 |