blob: b31ecabf60dd2f29504531fb43155e29060ce091 [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"
14#include "base/task/common/intrusive_heap.h"
15#include "base/task/task_scheduler/scheduler_lock.h"
16#include "base/task/task_scheduler/sequence_sort_key.h"
17#include "base/task/task_scheduler/task.h"
18#include "base/task/task_traits.h"
19
20namespace base {
21namespace internal {
22
23// A TaskSource is a virtual class that provides a series of Tasks that must be
24// executed.
25//
26// In order to execute a task from this TaskSource, a worker should first make
27// sure that it can take up an additional worker with NeedsWorker(). TakeTask()
28// can then be called to access the next Task, and Pop() must be called after
29// the task executed and before accessing any subsequent Tasks. This ensure that
30// the number of workers concurrently running tasks never go over the intended
31// concurrency.
32//
33// In comments below, an "empty TaskSource" is a TaskSource with no Task.
34//
35// Note: there is a known refcounted-ownership cycle in the Scheduler
36// architecture: TaskSource -> Task -> TaskRunner -> TaskSource -> ...
37// This is okay so long as the other owners of TaskSource (PriorityQueue and
38// SchedulerWorker in alternation and
39// SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetWork()
40// temporarily) keep running it (and taking Tasks from it as a result). A
41// dangling reference cycle would only occur should they release their reference
42// to it while it's not empty. In other words, it is only correct for them to
43// release it after IsEmpty() returns true.
44// TODO(etiennep): Break ownership cycle by moving TaskRunner reference from
45// Task to TaskSource.
46//
47// This class is thread-safe.
48class BASE_EXPORT TaskSource : public RefCountedThreadSafe<TaskSource> {
49 public:
50 // A Transaction can perform multiple operations atomically on a
51 // TaskSource. While a Transaction is alive, it is guaranteed that nothing
52 // else will access the TaskSource; the TaskSource's lock is held for the
53 // lifetime of the Transaction.
54 class BASE_EXPORT Transaction {
55 public:
56 Transaction(Transaction&& other);
57 ~Transaction();
58
59 // Returns the next task to run from this TaskSource. This should be called
60 // only if NeedsWorker returns true. Cannot be called on an empty
61 // TaskSource.
62 //
63 // Because this method cannot be called on an empty TaskSource, the returned
64 // Optional<Task> is never nullptr. An Optional is used in preparation for
65 // the merge between TaskScheduler and TaskQueueManager (in Blink).
66 // https://crbug.com/783309
67 Optional<Task> TakeTask();
68
69 // Must be called once the task was executed. Cannot be called on an empty
70 // TaskSource. Returns true if the TaskSource should be queued after this
71 // operation.
72 bool DidRunTask();
73
74 // Returns a SequenceSortKey representing the priority of the TaskSource.
75 // Cannot be called on an empty TaskSource.
76 SequenceSortKey GetSortKey() const;
77
78 // Returns true if additional workers should run tasks from this TaskSource.
79 bool NeedsWorker() const;
80
81 // Sets TaskSource priority to |priority|.
82 void UpdatePriority(TaskPriority priority);
83
84 // Deletes all tasks contained in this TaskSource.
85 void Clear();
86
87 // Returns the traits of all Tasks in the TaskSource.
88 TaskTraits traits() const { return task_source_->traits_; }
89
90 TaskSource* task_source() const { return task_source_; }
91
92 protected:
93 explicit Transaction(TaskSource* task_source);
94
95 private:
96 friend class TaskSource;
97
98 TaskSource* task_source_;
99
100 DISALLOW_COPY_AND_ASSIGN(Transaction);
101 };
102
103 // |traits| is metadata that applies to all Tasks in the TaskSource.
104 explicit TaskSource(const TaskTraits& traits);
105
106 // Begins a Transaction. This method cannot be called on a thread which has an
107 // active TaskSource::Transaction.
108 Transaction BeginTransaction();
109
110 // Support for IntrusiveHeap.
111 void SetHeapHandle(const HeapHandle& handle);
112 void ClearHeapHandle();
113 HeapHandle heap_handle() const { return heap_handle_; }
114
115 // Returns the shutdown behavior of all Tasks in the TaskSource. Can be
116 // accessed without a Transaction because it is never mutated.
117 TaskShutdownBehavior shutdown_behavior() const {
118 return traits_.shutdown_behavior();
119 }
120
121 protected:
122 virtual ~TaskSource();
123
124 virtual Optional<Task> TakeTask() = 0;
125
126 virtual SequenceSortKey GetSortKey() const = 0;
127
128 virtual bool IsEmpty() const = 0;
129
130 virtual void Clear() = 0;
131
132 // Sets TaskSource priority to |priority|.
133 void UpdatePriority(TaskPriority priority);
134
135 // The TaskTraits of all Tasks in the TaskSource.
136 TaskTraits traits_;
137
138 private:
139 friend class RefCountedThreadSafe<TaskSource>;
140
141 // Synchronizes access to all members.
142 mutable SchedulerLock lock_{UniversalPredecessor()};
143
144 // The TaskSource's position in its current PriorityQueue. Access is protected
145 // by the PriorityQueue's lock.
146 HeapHandle heap_handle_;
147
148 // TODO(etiennep): Add support for TaskSources with more than one worker.
149 bool has_worker_ = false;
150
151 DISALLOW_COPY_AND_ASSIGN(TaskSource);
152};
153
154struct BASE_EXPORT TaskSourceAndTransaction {
155 scoped_refptr<TaskSource> task_source;
156 TaskSource::Transaction transaction;
157 TaskSourceAndTransaction(scoped_refptr<TaskSource> task_source_in,
158 TaskSource::Transaction transaction_in);
159 TaskSourceAndTransaction(TaskSourceAndTransaction&& other);
160 static TaskSourceAndTransaction FromTaskSource(
161 scoped_refptr<TaskSource> task_source);
162 ~TaskSourceAndTransaction();
163};
164
165} // namespace internal
166} // namespace base
167
168#endif // BASE_TASK_TASK_SCHEDULER_TASK_SOURCE_H_