Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: cc/resources/task_graph_runner.h

Issue 154003006: cc: Switch to vector based TaskGraph implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: build fix Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/resources/raster_worker_pool_perftest.cc ('k') | cc/resources/task_graph_runner.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CC_RESOURCES_TASK_GRAPH_RUNNER_H_ 5 #ifndef CC_RESOURCES_TASK_GRAPH_RUNNER_H_
6 #define CC_RESOURCES_TASK_GRAPH_RUNNER_H_ 6 #define CC_RESOURCES_TASK_GRAPH_RUNNER_H_
7 7
8 #include <queue>
9 #include <string> 8 #include <string>
10 #include <vector> 9 #include <vector>
11 10
12 #include "base/containers/scoped_ptr_hash_map.h" 11 #include "base/containers/scoped_ptr_hash_map.h"
13 #include "base/memory/ref_counted.h" 12 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/synchronization/condition_variable.h" 13 #include "base/synchronization/condition_variable.h"
16 #include "base/threading/simple_thread.h" 14 #include "base/threading/simple_thread.h"
17 #include "cc/base/cc_export.h" 15 #include "cc/base/cc_export.h"
18 #include "cc/base/scoped_ptr_deque.h" 16 #include "cc/base/scoped_ptr_deque.h"
19 17
20 namespace cc { 18 namespace cc {
21 namespace internal { 19 namespace internal {
22 20
23 class CC_EXPORT Task : public base::RefCountedThreadSafe<Task> { 21 class CC_EXPORT Task : public base::RefCountedThreadSafe<Task> {
24 public: 22 public:
25 typedef std::vector<scoped_refptr<Task> > Vector; 23 typedef std::vector<scoped_refptr<Task> > Vector;
26 24
27 virtual void RunOnWorkerThread(unsigned thread_index) = 0; 25 virtual void RunOnWorkerThread(unsigned thread_index) = 0;
28 26
29 void WillRun(); 27 void WillRun();
30 void DidRun(); 28 void DidRun();
31 bool HasFinishedRunning() const; 29 bool HasFinishedRunning() const;
32 30
33 protected: 31 protected:
34 friend class base::RefCountedThreadSafe<Task>; 32 friend class base::RefCountedThreadSafe<Task>;
35 33
36 Task(); 34 Task();
37 virtual ~Task(); 35 virtual ~Task();
38 36
39 bool did_run_; 37 bool did_run_;
40 }; 38 };
41 39
42 } // namespace internal 40 // Dependencies are represented as edges in a task graph. Each graph node
43 } // namespace cc 41 // is assigned a priority and a run count that matches the number of
42 // dependencies.
43 struct CC_EXPORT TaskGraph {
44 struct Node {
45 class TaskComparator {
46 public:
47 explicit TaskComparator(const Task* task) : task_(task) {}
44 48
45 #if defined(COMPILER_GCC) 49 bool operator()(const Node& node) const { return node.task == task_; }
46 namespace BASE_HASH_NAMESPACE {
47 template <>
48 struct hash<cc::internal::Task*> {
49 size_t operator()(cc::internal::Task* ptr) const {
50 return hash<size_t>()(reinterpret_cast<size_t>(ptr));
51 }
52 };
53 } // namespace BASE_HASH_NAMESPACE
54 #endif // COMPILER
55 50
56 namespace cc { 51 private:
57 namespace internal { 52 const Task* task_;
53 };
58 54
59 // Dependencies are represented by edges in a task graph. A graph node 55 typedef std::vector<Node> Vector;
60 // store edges as a vector of dependents. Each graph node is assigned
61 // a priority and a run count that matches the number of dependencies.
62 class CC_EXPORT GraphNode {
63 public:
64 typedef std::vector<GraphNode*> Vector;
65 typedef base::ScopedPtrHashMap<Task*, GraphNode> Map;
66 56
67 GraphNode(Task* task, unsigned priority); 57 Node(Task* task, unsigned priority, size_t dependencies)
68 ~GraphNode(); 58 : task(task), priority(priority), dependencies(dependencies) {}
69 59
70 Task* task() { return task_; } 60 Task* task;
61 unsigned priority;
62 size_t dependencies;
63 };
71 64
72 void add_dependent(GraphNode* dependent) { 65 struct Edge {
73 DCHECK(dependent); 66 typedef std::vector<Edge> Vector;
74 dependents_.push_back(dependent);
75 }
76 const Vector& dependents() const { return dependents_; }
77 67
78 unsigned priority() const { return priority_; } 68 Edge(const Task* task, Task* dependent)
69 : task(task), dependent(dependent) {}
79 70
80 unsigned num_dependencies() const { return num_dependencies_; } 71 const Task* task;
81 void add_dependency() { ++num_dependencies_; } 72 Task* dependent;
82 void remove_dependency() { 73 };
83 DCHECK(num_dependencies_);
84 --num_dependencies_;
85 }
86 74
87 private: 75 TaskGraph();
88 Task* task_; 76 ~TaskGraph();
89 Vector dependents_;
90 unsigned priority_;
91 unsigned num_dependencies_;
92 77
93 DISALLOW_COPY_AND_ASSIGN(GraphNode); 78 void Swap(TaskGraph* other);
79 void Reset();
80
81 Node::Vector nodes;
82 Edge::Vector edges;
94 }; 83 };
95 84
96 class TaskGraphRunner; 85 class TaskGraphRunner;
97 86
98 // Opaque identifier that defines a namespace of tasks. 87 // Opaque identifier that defines a namespace of tasks.
99 class CC_EXPORT NamespaceToken { 88 class CC_EXPORT NamespaceToken {
100 public: 89 public:
101 NamespaceToken() : id_(0) {} 90 NamespaceToken() : id_(0) {}
102 ~NamespaceToken() {} 91 ~NamespaceToken() {}
103 92
104 bool IsValid() const { return id_ != 0; } 93 bool IsValid() const { return id_ != 0; }
105 94
106 private: 95 private:
107 friend class TaskGraphRunner; 96 friend class TaskGraphRunner;
108 97
109 explicit NamespaceToken(int id) : id_(id) {} 98 explicit NamespaceToken(int id) : id_(id) {}
110 99
111 int id_; 100 int id_;
112 }; 101 };
113 102
114 // A worker thread pool that runs tasks provided by task graph. Destructor 103 // A worker thread pool that runs tasks provided by task graph. Destructor
115 // might block and should not be used on a thread that needs to be responsive. 104 // might block and should not be used on a thread that needs to be responsive.
116 class CC_EXPORT TaskGraphRunner : public base::DelegateSimpleThread::Delegate { 105 class CC_EXPORT TaskGraphRunner : public base::DelegateSimpleThread::Delegate {
117 public: 106 public:
118 typedef GraphNode::Map TaskGraph;
119
120 TaskGraphRunner(size_t num_threads, const std::string& thread_name_prefix); 107 TaskGraphRunner(size_t num_threads, const std::string& thread_name_prefix);
121 virtual ~TaskGraphRunner(); 108 virtual ~TaskGraphRunner();
122 109
123 // Returns a unique token that can be used to pass a task graph to 110 // Returns a unique token that can be used to pass a task graph to
124 // SetTaskGraph(). Valid tokens are always nonzero. 111 // SetTaskGraph(). Valid tokens are always nonzero.
125 NamespaceToken GetNamespaceToken(); 112 NamespaceToken GetNamespaceToken();
126 113
127 // Schedule running of tasks in |graph|. Tasks previously scheduled but 114 // Schedule running of tasks in |graph|. Tasks previously scheduled but
128 // no longer needed will be canceled unless already running. Canceled 115 // no longer needed will be canceled unless already running. Canceled
129 // tasks are moved to |completed_tasks| without being run. The result 116 // tasks are moved to |completed_tasks| without being run. The result
130 // is that once scheduled, a task is guaranteed to end up in the 117 // is that once scheduled, a task is guaranteed to end up in the
131 // |completed_tasks| queue even if it later get canceled by another 118 // |completed_tasks| queue even if it later gets canceled by another
132 // call to SetTaskGraph(). 119 // call to SetTaskGraph().
133 void SetTaskGraph(NamespaceToken token, TaskGraph* graph); 120 void SetTaskGraph(NamespaceToken token, TaskGraph* graph);
134 121
135 // Wait for all scheduled tasks to finish running. 122 // Wait for all scheduled tasks to finish running.
136 void WaitForTasksToFinishRunning(NamespaceToken token); 123 void WaitForTasksToFinishRunning(NamespaceToken token);
137 124
138 // Collect all completed tasks in |completed_tasks|. 125 // Collect all completed tasks in |completed_tasks|.
139 void CollectCompletedTasks(NamespaceToken token, 126 void CollectCompletedTasks(NamespaceToken token,
140 Task::Vector* completed_tasks); 127 Task::Vector* completed_tasks);
141 128
142 // Run one task on current thread. Returns false if no tasks are ready 129 // Run one task on current thread. Returns false if no tasks are ready
143 // to run. This should only be used by tests. 130 // to run. This should only be used by tests.
144 bool RunTaskForTesting(); 131 bool RunTaskForTesting();
145 132
146 private: 133 private:
134 struct PrioritizedTask {
135 typedef std::vector<PrioritizedTask> Vector;
136
137 PrioritizedTask(Task* task, unsigned priority)
138 : task(task), priority(priority) {}
139
140 Task* task;
141 unsigned priority;
142 };
143
147 struct TaskNamespace { 144 struct TaskNamespace {
148 typedef std::vector<TaskNamespace*> Vector; 145 typedef std::vector<TaskNamespace*> Vector;
149 146
150 TaskNamespace(); 147 TaskNamespace();
151 ~TaskNamespace(); 148 ~TaskNamespace();
152 149
153 // This set contains all pending tasks. 150 // Current task graph.
154 TaskGraph pending_tasks; 151 TaskGraph graph;
155 // This set contains all currently running tasks. 152
156 TaskGraph running_tasks; 153 // Ordered set of tasks that are ready to run.
154 PrioritizedTask::Vector ready_to_run_tasks;
155
157 // Completed tasks not yet collected by origin thread. 156 // Completed tasks not yet collected by origin thread.
158 Task::Vector completed_tasks; 157 Task::Vector completed_tasks;
159 // Ordered set of tasks that are ready to run. 158
160 internal::GraphNode::Vector ready_to_run_tasks; 159 // Number of currently running tasks.
160 size_t num_running_tasks;
161 }; 161 };
162 162
163 typedef base::ScopedPtrHashMap<int, TaskNamespace> TaskNamespaceMap; 163 typedef base::ScopedPtrHashMap<int, TaskNamespace> TaskNamespaceMap;
164 164
165 static bool CompareTaskPriority(const internal::GraphNode* a, 165 static bool CompareTaskPriority(const PrioritizedTask& a,
166 const internal::GraphNode* b) { 166 const PrioritizedTask& b) {
167 // In this system, numerically lower priority is run first. 167 // In this system, numerically lower priority is run first.
168 if (a->priority() != b->priority()) 168 return a.priority > b.priority;
169 return a->priority() > b->priority();
170
171 // Run task with most dependents first when priority is the same.
172 return a->dependents().size() < b->dependents().size();
173 } 169 }
174 170
175 static bool CompareTaskNamespacePriority(const TaskNamespace* a, 171 static bool CompareTaskNamespacePriority(const TaskNamespace* a,
176 const TaskNamespace* b) { 172 const TaskNamespace* b) {
177 DCHECK(!a->ready_to_run_tasks.empty()); 173 DCHECK(!a->ready_to_run_tasks.empty());
178 DCHECK(!b->ready_to_run_tasks.empty()); 174 DCHECK(!b->ready_to_run_tasks.empty());
179 175
180 // Compare based on task priority of the ready_to_run_tasks heap 176 // Compare based on task priority of the ready_to_run_tasks heap
181 // .front() will hold the max element of the heap, 177 // .front() will hold the max element of the heap,
182 // except after pop_heap, when max element is moved to .back(). 178 // except after pop_heap, when max element is moved to .back().
183 return CompareTaskPriority(a->ready_to_run_tasks.front(), 179 return CompareTaskPriority(a->ready_to_run_tasks.front(),
184 b->ready_to_run_tasks.front()); 180 b->ready_to_run_tasks.front());
185 } 181 }
186 182
187 static bool HasFinishedRunningTasksInNamespace( 183 static bool HasFinishedRunningTasksInNamespace(
188 TaskNamespace* task_namespace) { 184 const TaskNamespace* task_namespace) {
189 return task_namespace->pending_tasks.empty() && 185 return !task_namespace->num_running_tasks &&
190 task_namespace->running_tasks.empty(); 186 task_namespace->ready_to_run_tasks.empty();
191 } 187 }
192 188
193 // Overridden from base::DelegateSimpleThread: 189 // Overridden from base::DelegateSimpleThread:
194 virtual void Run() OVERRIDE; 190 virtual void Run() OVERRIDE;
195 191
196 // Run next task. Caller must acquire |lock_| prior to calling this 192 // Run next task. Caller must acquire |lock_| prior to calling this
197 // function and make sure at least one task is ready to run. 193 // function and make sure at least one task is ready to run.
198 void RunTaskWithLockAcquired(int thread_index); 194 void RunTaskWithLockAcquired(int thread_index);
199 195
200 // This lock protects all members of this class. Do not read or modify 196 // This lock protects all members of this class. Do not read or modify
(...skipping 16 matching lines...) Expand all
217 // tasks not yet collected. 213 // tasks not yet collected.
218 TaskNamespaceMap namespaces_; 214 TaskNamespaceMap namespaces_;
219 215
220 // Ordered set of task namespaces that have ready to run tasks. 216 // Ordered set of task namespaces that have ready to run tasks.
221 TaskNamespace::Vector ready_to_run_namespaces_; 217 TaskNamespace::Vector ready_to_run_namespaces_;
222 218
223 // Provides each running thread loop with a unique index. First thread 219 // Provides each running thread loop with a unique index. First thread
224 // loop index is 0. 220 // loop index is 0.
225 unsigned next_thread_index_; 221 unsigned next_thread_index_;
226 222
223 // This set contains all currently running tasks.
224 typedef std::vector<const Task*> TaskVector;
225 TaskVector running_tasks_;
226
227 // Set during shutdown. Tells workers to exit when no more tasks 227 // Set during shutdown. Tells workers to exit when no more tasks
228 // are pending. 228 // are pending.
229 bool shutdown_; 229 bool shutdown_;
230 230
231 ScopedPtrDeque<base::DelegateSimpleThread> workers_; 231 ScopedPtrDeque<base::DelegateSimpleThread> workers_;
232 232
233 DISALLOW_COPY_AND_ASSIGN(TaskGraphRunner); 233 DISALLOW_COPY_AND_ASSIGN(TaskGraphRunner);
234 }; 234 };
235 235
236 } // namespace internal 236 } // namespace internal
237 } // namespace cc 237 } // namespace cc
238 238
239 #endif // CC_RESOURCES_TASK_GRAPH_RUNNER_H_ 239 #endif // CC_RESOURCES_TASK_GRAPH_RUNNER_H_
OLDNEW
« no previous file with comments | « cc/resources/raster_worker_pool_perftest.cc ('k') | cc/resources/task_graph_runner.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698