1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TASK_SCHEDULER_SEQUENCE_H_
6 #define BASE_TASK_SCHEDULER_SEQUENCE_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 #include <queue>
12 
13 #include "base/base_export.h"
14 #include "base/macros.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/task_scheduler/scheduler_lock.h"
17 #include "base/task_scheduler/sequence_sort_key.h"
18 #include "base/task_scheduler/task.h"
19 #include "base/task_scheduler/task_traits.h"
20 
21 namespace base {
22 namespace internal {
23 
24 // A sequence holds tasks that must be executed in posting order.
25 //
26 // Note: there is a known refcounted-ownership cycle in the Scheduler
27 // architecture: Sequence -> Task -> TaskRunner -> Sequence -> ...
28 // This is okay so long as the other owners of Sequence (PriorityQueue and
29 // SchedulerWorker in alternation and
30 // SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetWork()
31 // temporarily) keep running it (and taking Tasks from it as a result). A
32 // dangling reference cycle would only occur should they release their reference
33 // to it while it's not empty. In other words, it is only correct for them to
34 // release it after PopTask() returns false to indicate it was made empty by
35 // that call (in which case the next PushTask() will return true to indicate to
36 // the caller that the Sequence should be re-enqueued for execution).
37 //
38 // This class is thread-safe.
39 class BASE_EXPORT Sequence : public RefCountedThreadSafe<Sequence> {
40  public:
41   Sequence();
42 
43   // Adds |task| at the end of the sequence's queue. Returns true if the
44   // sequence was empty before this operation.
45   bool PushTask(std::unique_ptr<Task> task);
46 
47   // Returns the task in front of the sequence's queue, if any.
48   const Task* PeekTask() const;
49 
50   // Removes the task in front of the sequence's queue. Returns true if the
51   // sequence is empty after this operation. Cannot be called on an empty
52   // sequence.
53   bool PopTask();
54 
55   // Returns a SequenceSortKey representing the priority of the sequence. Cannot
56   // be called on an empty sequence.
57   SequenceSortKey GetSortKey() const;
58 
59  private:
60   friend class RefCountedThreadSafe<Sequence>;
61   ~Sequence();
62 
63   // Synchronizes access to all members.
64   mutable SchedulerLock lock_;
65 
66   // Queue of tasks to execute.
67   std::queue<std::unique_ptr<Task>> queue_;
68 
69   // Number of tasks contained in the sequence for each priority.
70   size_t num_tasks_per_priority_[static_cast<int>(TaskPriority::HIGHEST) + 1] =
71       {};
72 
73   DISALLOW_COPY_AND_ASSIGN(Sequence);
74 };
75 
76 }  // namespace internal
77 }  // namespace base
78 
79 #endif  // BASE_TASK_SCHEDULER_SEQUENCE_H_
80