• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/sequence_token.h"
17 #include "base/task_scheduler/scheduler_lock.h"
18 #include "base/task_scheduler/sequence_sort_key.h"
19 #include "base/task_scheduler/task.h"
20 #include "base/task_scheduler/task_traits.h"
21 
22 namespace base {
23 namespace internal {
24 
25 // A Sequence holds slots each containing up to a single Task that must be
26 // executed in posting order.
27 //
28 // In comments below, an "empty Sequence" is a Sequence with no slot.
29 //
30 // Note: there is a known refcounted-ownership cycle in the Scheduler
31 // architecture: Sequence -> Task -> TaskRunner -> Sequence -> ...
32 // This is okay so long as the other owners of Sequence (PriorityQueue and
33 // SchedulerWorker in alternation and
34 // SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetWork()
35 // temporarily) keep running it (and taking Tasks from it as a result). A
36 // dangling reference cycle would only occur should they release their reference
37 // to it while it's not empty. In other words, it is only correct for them to
38 // release it after PopTask() returns false to indicate it was made empty by
39 // that call (in which case the next PushTask() will return true to indicate to
40 // the caller that the Sequence should be re-enqueued for execution).
41 //
42 // This class is thread-safe.
43 class BASE_EXPORT Sequence : public RefCountedThreadSafe<Sequence> {
44  public:
45   Sequence();
46 
47   // Adds |task| in a new slot at the end of the Sequence. Returns true if the
48   // Sequence was empty before this operation.
49   bool PushTask(std::unique_ptr<Task> task);
50 
51   // Transfers ownership of the Task in the front slot of the Sequence to the
52   // caller. The front slot of the Sequence will be nullptr and remain until
53   // Pop(). Cannot be called on an empty Sequence or a Sequence whose front slot
54   // is already nullptr.
55   std::unique_ptr<Task> TakeTask();
56 
57   // Returns the TaskTraits of the Task in front of the Sequence. Cannot be
58   // called on an empty Sequence or on a Sequence whose front slot is empty.
59   TaskTraits PeekTaskTraits() const;
60 
61   // Removes the front slot of the Sequence. The front slot must have been
62   // emptied by TakeTask() before this is called. Cannot be called on an empty
63   // Sequence. Returns true if the Sequence is empty after this operation.
64   bool Pop();
65 
66   // Returns a SequenceSortKey representing the priority of the Sequence. Cannot
67   // be called on an empty Sequence.
68   SequenceSortKey GetSortKey() const;
69 
70   // Returns a token that uniquely identifies this Sequence.
token()71   const SequenceToken& token() const { return token_; }
72 
73  private:
74   friend class RefCountedThreadSafe<Sequence>;
75   ~Sequence();
76 
77   const SequenceToken token_ = SequenceToken::Create();
78 
79   // Synchronizes access to all members.
80   mutable SchedulerLock lock_;
81 
82   // Queue of tasks to execute.
83   std::queue<std::unique_ptr<Task>> queue_;
84 
85   // Number of tasks contained in the Sequence for each priority.
86   size_t num_tasks_per_priority_[static_cast<int>(TaskPriority::HIGHEST) + 1] =
87       {};
88 
89   DISALLOW_COPY_AND_ASSIGN(Sequence);
90 };
91 
92 }  // namespace internal
93 }  // namespace base
94 
95 #endif  // BASE_TASK_SCHEDULER_SEQUENCE_H_
96