blob: bc30bc64ea7eef401dc5dd14056bb3933b4d006f [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
Gabriel Charette52fa3ae2019-04-15 21:44:375#ifndef BASE_TASK_THREAD_POOL_TASK_SOURCE_H_
6#define BASE_TASK_THREAD_POOL_TASK_SOURCE_H_
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:387
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"
Gabriel Charetted35648382019-04-30 21:10:5915#include "base/task/common/checked_lock.h"
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:3816#include "base/task/common/intrusive_heap.h"
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:3817#include "base/task/task_traits.h"
Gabriel Charette52fa3ae2019-04-15 21:44:3718#include "base/task/thread_pool/sequence_sort_key.h"
19#include "base/task/thread_pool/task.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//
Etienne Pierre-dorayabfecf72019-05-09 20:41:4840// In order to execute a task from this TaskSource, TakeTask() can be called to
41// access the next Task, and DidRunTask() must be called after the task executed
42// and before accessing any subsequent Tasks. This ensure that the number of
43// workers concurrently running tasks never go over the intended concurrency.
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:3844//
45// In comments below, an "empty TaskSource" is a TaskSource with no Task.
46//
47// Note: there is a known refcounted-ownership cycle in the Scheduler
Etienne Pierre-dorayabfecf72019-05-09 20:41:4848// architecture: TaskSource -> TaskRunner -> TaskSource -> ... This is
49// okay so long as the other owners of TaskSource (PriorityQueue and
Gabriel Charette3e2898f2019-05-01 14:55:0150// WorkerThread in alternation and
Etienne Pierre-dorayabfecf72019-05-09 20:41:4851// ThreadGroupImpl::WorkerThreadDelegateImpl::GetWork() temporarily) keep
52// running it (and taking Tasks from it as a result). A dangling reference cycle
53// would only occur should they release their reference to it while it's not
54// empty. In other words, it is only correct for them to release it when
55// DidRunTask() returns false.
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:3856//
57// This class is thread-safe.
58class BASE_EXPORT TaskSource : public RefCountedThreadSafe<TaskSource> {
59 public:
60 // A Transaction can perform multiple operations atomically on a
61 // TaskSource. While a Transaction is alive, it is guaranteed that nothing
62 // else will access the TaskSource; the TaskSource's lock is held for the
63 // lifetime of the Transaction.
64 class BASE_EXPORT Transaction {
65 public:
66 Transaction(Transaction&& other);
67 ~Transaction();
68
69 // Returns the next task to run from this TaskSource. This should be called
70 // only if NeedsWorker returns true. Cannot be called on an empty
71 // TaskSource.
72 //
73 // Because this method cannot be called on an empty TaskSource, the returned
74 // Optional<Task> is never nullptr. An Optional is used in preparation for
Gabriel Charette52fa3ae2019-04-15 21:44:3775 // the merge between ThreadPool and TaskQueueManager (in Blink).
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:3876 // https://crbug.com/783309
77 Optional<Task> TakeTask();
78
79 // Must be called once the task was executed. Cannot be called on an empty
80 // TaskSource. Returns true if the TaskSource should be queued after this
81 // operation.
82 bool DidRunTask();
83
84 // Returns a SequenceSortKey representing the priority of the TaskSource.
85 // Cannot be called on an empty TaskSource.
86 SequenceSortKey GetSortKey() const;
87
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:3888 // Sets TaskSource priority to |priority|.
89 void UpdatePriority(TaskPriority priority);
90
91 // Deletes all tasks contained in this TaskSource.
92 void Clear();
93
94 // Returns the traits of all Tasks in the TaskSource.
95 TaskTraits traits() const { return task_source_->traits_; }
96
97 TaskSource* task_source() const { return task_source_; }
98
99 protected:
100 explicit Transaction(TaskSource* task_source);
101
102 private:
103 friend class TaskSource;
104
105 TaskSource* task_source_;
106
107 DISALLOW_COPY_AND_ASSIGN(Transaction);
108 };
109
110 // |traits| is metadata that applies to all Tasks in the TaskSource.
Etienne Pierre-doray45fd5d52019-03-28 15:19:55111 // |task_runner| is a reference to the TaskRunner feeding this TaskSource.
112 // |task_runner| can be nullptr only for tasks with no TaskRunner, in which
113 // case |execution_mode| must be kParallel. Otherwise, |execution_mode| is the
114 // execution mode of |task_runner|.
115 TaskSource(const TaskTraits& traits,
116 TaskRunner* task_runner,
117 TaskSourceExecutionMode execution_mode);
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38118
119 // Begins a Transaction. This method cannot be called on a thread which has an
120 // active TaskSource::Transaction.
121 Transaction BeginTransaction();
122
Etienne Pierre-doray312462152019-03-19 16:10:17123 virtual ExecutionEnvironment GetExecutionEnvironment() = 0;
124
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38125 // Support for IntrusiveHeap.
126 void SetHeapHandle(const HeapHandle& handle);
127 void ClearHeapHandle();
128 HeapHandle heap_handle() const { return heap_handle_; }
129
130 // Returns the shutdown behavior of all Tasks in the TaskSource. Can be
131 // accessed without a Transaction because it is never mutated.
132 TaskShutdownBehavior shutdown_behavior() const {
133 return traits_.shutdown_behavior();
134 }
135
Etienne Pierre-doray45fd5d52019-03-28 15:19:55136 // A reference to TaskRunner is only retained between PushTask() and when
137 // DidRunTask() returns false, guaranteeing it is safe to dereference this
138 // pointer. Otherwise, the caller should guarantee such TaskRunner still
139 // exists before dereferencing.
140 TaskRunner* task_runner() const { return task_runner_; }
141
142 TaskSourceExecutionMode execution_mode() const { return execution_mode_; }
143
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38144 protected:
145 virtual ~TaskSource();
146
147 virtual Optional<Task> TakeTask() = 0;
148
Etienne Pierre-doray45fd5d52019-03-28 15:19:55149 // Returns true if the TaskSource should be queued after this
150 // operation.
151 virtual bool DidRunTask() = 0;
152
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38153 virtual SequenceSortKey GetSortKey() const = 0;
154
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38155 virtual void Clear() = 0;
156
157 // Sets TaskSource priority to |priority|.
158 void UpdatePriority(TaskPriority priority);
159
160 // The TaskTraits of all Tasks in the TaskSource.
161 TaskTraits traits_;
162
163 private:
164 friend class RefCountedThreadSafe<TaskSource>;
165
166 // Synchronizes access to all members.
Gabriel Charetted35648382019-04-30 21:10:59167 mutable CheckedLock lock_{UniversalPredecessor()};
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38168
169 // The TaskSource's position in its current PriorityQueue. Access is protected
170 // by the PriorityQueue's lock.
171 HeapHandle heap_handle_;
172
Etienne Pierre-doray45fd5d52019-03-28 15:19:55173 // A pointer to the TaskRunner that posts to this TaskSource, if any. The
Etienne Pierre-dorayabfecf72019-05-09 20:41:48174 // derived class is responsible for calling AddRef() when a TaskSource from
175 // which no Task is executing becomes non-empty and Release() when
176 // DidRunTask() returns false.
Etienne Pierre-doray45fd5d52019-03-28 15:19:55177 TaskRunner* task_runner_;
178
179 TaskSourceExecutionMode execution_mode_;
180
Etienne Pierre-dorayb38e0fd2019-03-18 19:35:38181 DISALLOW_COPY_AND_ASSIGN(TaskSource);
182};
183
184struct BASE_EXPORT TaskSourceAndTransaction {
185 scoped_refptr<TaskSource> task_source;
186 TaskSource::Transaction transaction;
187 TaskSourceAndTransaction(scoped_refptr<TaskSource> task_source_in,
188 TaskSource::Transaction transaction_in);
189 TaskSourceAndTransaction(TaskSourceAndTransaction&& other);
190 static TaskSourceAndTransaction FromTaskSource(
191 scoped_refptr<TaskSource> task_source);
192 ~TaskSourceAndTransaction();
193};
194
195} // namespace internal
196} // namespace base
197
Gabriel Charette52fa3ae2019-04-15 21:44:37198#endif // BASE_TASK_THREAD_POOL_TASK_SOURCE_H_