|  | // 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. | 
|  |  | 
|  | #ifndef BASE_TASK_TASK_SCHEDULER_PRIORITY_QUEUE_H_ | 
|  | #define BASE_TASK_TASK_SCHEDULER_PRIORITY_QUEUE_H_ | 
|  |  | 
|  | #include <memory> | 
|  | #include <queue> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/base_export.h" | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/ref_counted.h" | 
|  | #include "base/task/task_scheduler/scheduler_lock.h" | 
|  | #include "base/task/task_scheduler/sequence.h" | 
|  | #include "base/task/task_scheduler/sequence_sort_key.h" | 
|  |  | 
|  | namespace base { | 
|  | namespace internal { | 
|  |  | 
|  | // A PriorityQueue holds Sequences of Tasks. This class is thread-safe. | 
|  | class BASE_EXPORT PriorityQueue { | 
|  | public: | 
|  | // A Transaction can perform multiple operations atomically on a | 
|  | // PriorityQueue. While a Transaction is alive, it is guaranteed that nothing | 
|  | // else will access the PriorityQueue. | 
|  | // | 
|  | // A Worker needs to be able to Peek sequences from both its PriorityQueues | 
|  | // (single-threaded and shared) and then Pop the sequence with the highest | 
|  | // priority. If the Peek and the Pop are done through the same Transaction, it | 
|  | // is guaranteed that the PriorityQueue hasn't changed between the 2 | 
|  | // operations. | 
|  | class BASE_EXPORT Transaction { | 
|  | public: | 
|  | ~Transaction(); | 
|  |  | 
|  | // Inserts |sequence| in the PriorityQueue with |sequence_sort_key|. | 
|  | // Note: |sequence_sort_key| is required as a parameter instead of being | 
|  | // extracted from |sequence| in Push() to avoid this Transaction having a | 
|  | // lock interdependency with |sequence|. | 
|  | void Push(scoped_refptr<Sequence> sequence, | 
|  | const SequenceSortKey& sequence_sort_key); | 
|  |  | 
|  | // Returns a reference to the SequenceSortKey representing the priority of | 
|  | // the highest pending task in this PriorityQueue. The reference becomes | 
|  | // invalid the next time that this PriorityQueue is modified. | 
|  | // Cannot be called on an empty PriorityQueue. | 
|  | const SequenceSortKey& PeekSortKey() const; | 
|  |  | 
|  | // Removes and returns the highest priority Sequence in this PriorityQueue. | 
|  | // Cannot be called on an empty PriorityQueue. | 
|  | scoped_refptr<Sequence> PopSequence(); | 
|  |  | 
|  | // Returns true if the PriorityQueue is empty. | 
|  | bool IsEmpty() const; | 
|  |  | 
|  | // Returns the number of Sequences in the PriorityQueue. | 
|  | size_t Size() const; | 
|  |  | 
|  | private: | 
|  | friend class PriorityQueue; | 
|  |  | 
|  | explicit Transaction(PriorityQueue* outer_queue); | 
|  |  | 
|  | // Holds the lock of |outer_queue_| for the lifetime of this Transaction. | 
|  | AutoSchedulerLock auto_lock_; | 
|  |  | 
|  | PriorityQueue* const outer_queue_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(Transaction); | 
|  | }; | 
|  |  | 
|  | PriorityQueue(); | 
|  |  | 
|  | ~PriorityQueue(); | 
|  |  | 
|  | // Begins a Transaction. This method cannot be called on a thread which has an | 
|  | // active Transaction unless the last Transaction created on the thread was | 
|  | // for the allowed predecessor specified in the constructor of this | 
|  | // PriorityQueue. | 
|  | std::unique_ptr<Transaction> BeginTransaction(); | 
|  |  | 
|  | const SchedulerLock* container_lock() const { return &container_lock_; } | 
|  |  | 
|  | private: | 
|  | // A class combining a Sequence and the SequenceSortKey that determines its | 
|  | // position in a PriorityQueue. | 
|  | class SequenceAndSortKey; | 
|  |  | 
|  | using ContainerType = std::priority_queue<SequenceAndSortKey>; | 
|  |  | 
|  | // Synchronizes access to |container_|. | 
|  | SchedulerLock container_lock_; | 
|  |  | 
|  | ContainerType container_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(PriorityQueue); | 
|  | }; | 
|  |  | 
|  | }  // namespace internal | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_TASK_TASK_SCHEDULER_PRIORITY_QUEUE_H_ |