blob: edb1b9359fde5bb613b947e0a4a81b9510c50581 [file] [log] [blame]
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:381// Copyright 2019 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_TASK_SCHEDULER_TASK_SOURCE_H_
6#define BASE_TASK_TASK_SCHEDULER_TASK_SOURCE_H_
7
8#include <stddef.h>
9
10#include "base/base_export.h"
11#include "base/macros.h"
12#include "base/memory/ref_counted.h"
13#include "base/optional.h"
Etienne Pierre-doray312462152019-03-19 16:10:1714#include "base/sequence_token.h"
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:3815#include "base/task/common/intrusive_heap.h"
16#include "base/task/task_scheduler/scheduler_lock.h"
17#include "base/task/task_scheduler/sequence_sort_key.h"
18#include "base/task/task_scheduler/task.h"
19#include "base/task/task_traits.h"
Etienne Pierre-doray312462152019-03-19 16:10:1720#include "base/threading/sequence_local_storage_map.h"
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:3821
22namespace base {
23namespace internal {
24
Etienne Pierre-doray45fd5d52019-03-28 15:19:5525enum class TaskSourceExecutionMode {
26 kParallel,
27 kSequenced,
28 kSingleThread,
29 kMax = kSingleThread,
30};
31
Etienne Pierre-doray312462152019-03-19 16:10:1732struct BASE_EXPORT ExecutionEnvironment {
33 SequenceToken token;
34 SequenceLocalStorageMap* sequence_local_storage;
35};
36
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:3837// A TaskSource is a virtual class that provides a series of Tasks that must be
38// executed.
39//
40// In order to execute a task from this TaskSource, a worker should first make
41// sure that it can take up an additional worker with NeedsWorker(). TakeTask()
42// can then be called to access the next Task, and Pop() must be called after
43// the task executed and before accessing any subsequent Tasks. This ensure that
44// the number of workers concurrently running tasks never go over the intended
45// concurrency.
46//
47// In comments below, an "empty TaskSource" is a TaskSource with no Task.
48//
49// Note: there is a known refcounted-ownership cycle in the Scheduler
50// architecture: TaskSource -> Task -> TaskRunner -> TaskSource -> ...
51// This is okay so long as the other owners of TaskSource (PriorityQueue and
52// SchedulerWorker in alternation and
53// SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetWork()
54// temporarily) keep running it (and taking Tasks from it as a result). A
55// dangling reference cycle would only occur should they release their reference
56// to it while it's not empty. In other words, it is only correct for them to
57// release it after IsEmpty() returns true.
58// TODO(etiennep): Break ownership cycle by moving TaskRunner reference from
59// Task to TaskSource.
60//
61// This class is thread-safe.
62class BASE_EXPORT TaskSource : public RefCountedThreadSafe<TaskSource> {
63 public:
64 // A Transaction can perform multiple operations atomically on a
65 // TaskSource. While a Transaction is alive, it is guaranteed that nothing
66 // else will access the TaskSource; the TaskSource's lock is held for the
67 // lifetime of the Transaction.
68 class BASE_EXPORT Transaction {
69 public:
70 Transaction(Transaction&& other);
71 ~Transaction();
72
73 // Returns the next task to run from this TaskSource. This should be called
74 // only if NeedsWorker returns true. Cannot be called on an empty
75 // TaskSource.
76 //
77 // Because this method cannot be called on an empty TaskSource, the returned
78 // Optional<Task> is never nullptr. An Optional is used in preparation for
79 // the merge between TaskScheduler and TaskQueueManager (in Blink).
80 // https://crbug.com/783309
81 Optional<Task> TakeTask();
82
83 // Must be called once the task was executed. Cannot be called on an empty
84 // TaskSource. Returns true if the TaskSource should be queued after this
85 // operation.
86 bool DidRunTask();
87
88 // Returns a SequenceSortKey representing the priority of the TaskSource.
89 // Cannot be called on an empty TaskSource.
90 SequenceSortKey GetSortKey() const;
91
92 // Returns true if additional workers should run tasks from this TaskSource.
93 bool NeedsWorker() const;
94
95 // Sets TaskSource priority to |priority|.
96 void UpdatePriority(TaskPriority priority);
97
98 // Deletes all tasks contained in this TaskSource.
99 void Clear();
100
101 // Returns the traits of all Tasks in the TaskSource.
102 TaskTraits traits() const { return task_source_->traits_; }
103
104 TaskSource* task_source() const { return task_source_; }
105
106 protected:
107 explicit Transaction(TaskSource* task_source);
108
109 private:
110 friend class TaskSource;
111
112 TaskSource* task_source_;
113
114 DISALLOW_COPY_AND_ASSIGN(Transaction);
115 };
116
117 // |traits| is metadata that applies to all Tasks in the TaskSource.
Etienne Pierre-doray45fd5d52019-03-28 15:19:55118 // |task_runner| is a reference to the TaskRunner feeding this TaskSource.
119 // |task_runner| can be nullptr only for tasks with no TaskRunner, in which
120 // case |execution_mode| must be kParallel. Otherwise, |execution_mode| is the
121 // execution mode of |task_runner|.
122 TaskSource(const TaskTraits& traits,
123 TaskRunner* task_runner,
124 TaskSourceExecutionMode execution_mode);
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38125
126 // Begins a Transaction. This method cannot be called on a thread which has an
127 // active TaskSource::Transaction.
128 Transaction BeginTransaction();
129
Etienne Pierre-doray312462152019-03-19 16:10:17130 virtual ExecutionEnvironment GetExecutionEnvironment() = 0;
131
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38132 // Support for IntrusiveHeap.
133 void SetHeapHandle(const HeapHandle& handle);
134 void ClearHeapHandle();
135 HeapHandle heap_handle() const { return heap_handle_; }
136
137 // Returns the shutdown behavior of all Tasks in the TaskSource. Can be
138 // accessed without a Transaction because it is never mutated.
139 TaskShutdownBehavior shutdown_behavior() const {
140 return traits_.shutdown_behavior();
141 }
142
Etienne Pierre-doray45fd5d52019-03-28 15:19:55143 // A reference to TaskRunner is only retained between PushTask() and when
144 // DidRunTask() returns false, guaranteeing it is safe to dereference this
145 // pointer. Otherwise, the caller should guarantee such TaskRunner still
146 // exists before dereferencing.
147 TaskRunner* task_runner() const { return task_runner_; }
148
149 TaskSourceExecutionMode execution_mode() const { return execution_mode_; }
150
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38151 protected:
152 virtual ~TaskSource();
153
154 virtual Optional<Task> TakeTask() = 0;
155
Etienne Pierre-doray45fd5d52019-03-28 15:19:55156 // Returns true if the TaskSource should be queued after this
157 // operation.
158 virtual bool DidRunTask() = 0;
159
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38160 virtual SequenceSortKey GetSortKey() const = 0;
161
162 virtual bool IsEmpty() const = 0;
163
164 virtual void Clear() = 0;
165
166 // Sets TaskSource priority to |priority|.
167 void UpdatePriority(TaskPriority priority);
168
169 // The TaskTraits of all Tasks in the TaskSource.
170 TaskTraits traits_;
171
172 private:
173 friend class RefCountedThreadSafe<TaskSource>;
174
175 // Synchronizes access to all members.
176 mutable SchedulerLock lock_{UniversalPredecessor()};
177
178 // The TaskSource's position in its current PriorityQueue. Access is protected
179 // by the PriorityQueue's lock.
180 HeapHandle heap_handle_;
181
Etienne Pierre-doray45fd5d52019-03-28 15:19:55182 // A pointer to the TaskRunner that posts to this TaskSource, if any. The
183 // derived class is responsible for calling AddRef() when NeedWorkers()
184 // becomes true and Release() when DidRunTask() returns false.
185 TaskRunner* task_runner_;
186
187 TaskSourceExecutionMode execution_mode_;
188
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38189 // TODO(etiennep): Add support for TaskSources with more than one worker.
190 bool has_worker_ = false;
191
192 DISALLOW_COPY_AND_ASSIGN(TaskSource);
193};
194
195struct BASE_EXPORT TaskSourceAndTransaction {
196 scoped_refptr<TaskSource> task_source;
197 TaskSource::Transaction transaction;
198 TaskSourceAndTransaction(scoped_refptr<TaskSource> task_source_in,
199 TaskSource::Transaction transaction_in);
200 TaskSourceAndTransaction(TaskSourceAndTransaction&& other);
201 static TaskSourceAndTransaction FromTaskSource(
202 scoped_refptr<TaskSource> task_source);
203 ~TaskSourceAndTransaction();
204};
205
206} // namespace internal
207} // namespace base
208
209#endif // BASE_TASK_TASK_SCHEDULER_TASK_SOURCE_H_