• 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 "base/base_export.h"
11 #include "base/containers/queue.h"
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/optional.h"
15 #include "base/sequence_token.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/threading/sequence_local_storage_map.h"
20 
21 namespace base {
22 namespace internal {
23 
24 // A Sequence holds slots each containing up to a single Task that must be
25 // executed in posting order.
26 //
27 // In comments below, an "empty Sequence" is a Sequence with no slot.
28 //
29 // Note: there is a known refcounted-ownership cycle in the Scheduler
30 // architecture: Sequence -> Task -> TaskRunner -> Sequence -> ...
31 // This is okay so long as the other owners of Sequence (PriorityQueue and
32 // SchedulerWorker in alternation and
33 // SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetWork()
34 // temporarily) keep running it (and taking Tasks from it as a result). A
35 // dangling reference cycle would only occur should they release their reference
36 // to it while it's not empty. In other words, it is only correct for them to
37 // release it after PopTask() returns false to indicate it was made empty by
38 // that call (in which case the next PushTask() will return true to indicate to
39 // the caller that the Sequence should be re-enqueued for execution).
40 //
41 // This class is thread-safe.
42 class BASE_EXPORT Sequence : public RefCountedThreadSafe<Sequence> {
43  public:
44   Sequence();
45 
46   // Adds |task| in a new slot at the end of the Sequence. Returns true if the
47   // Sequence was empty before this operation.
48   bool PushTask(Task task);
49 
50   // Transfers ownership of the Task in the front slot of the Sequence to the
51   // caller. The front slot of the Sequence will be nullptr and remain until
52   // Pop(). Cannot be called on an empty Sequence or a Sequence whose front slot
53   // is already nullptr.
54   //
55   // Because this method cannot be called on an empty Sequence, the returned
56   // Optional<Task> is never nullptr. An Optional is used in preparation for the
57   // merge between TaskScheduler and TaskQueueManager (in Blink).
58   // https://crbug.com/783309
59   Optional<Task> TakeTask();
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 
sequence_local_storage()73   SequenceLocalStorageMap* sequence_local_storage() {
74     return &sequence_local_storage_;
75   }
76 
77  private:
78   friend class RefCountedThreadSafe<Sequence>;
79   ~Sequence();
80 
81   const SequenceToken token_ = SequenceToken::Create();
82 
83   // Synchronizes access to all members.
84   mutable SchedulerLock lock_;
85 
86   // Queue of tasks to execute.
87   base::queue<Task> queue_;
88 
89   // Number of tasks contained in the Sequence for each priority.
90   size_t num_tasks_per_priority_[static_cast<int>(TaskPriority::HIGHEST) + 1] =
91       {};
92 
93   // Holds data stored through the SequenceLocalStorageSlot API.
94   SequenceLocalStorageMap sequence_local_storage_;
95 
96   DISALLOW_COPY_AND_ASSIGN(Sequence);
97 };
98 
99 }  // namespace internal
100 }  // namespace base
101 
102 #endif  // BASE_TASK_SCHEDULER_SEQUENCE_H_
103