Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / cc / resources / task_graph_runner.h
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
3 // found in the LICENSE file.
4
5 #ifndef CC_RESOURCES_TASK_GRAPH_RUNNER_H_
6 #define CC_RESOURCES_TASK_GRAPH_RUNNER_H_
7
8 #include <map>
9 #include <vector>
10
11 #include "base/logging.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/synchronization/condition_variable.h"
14 #include "cc/base/cc_export.h"
15
16 namespace cc {
17
18 class CC_EXPORT Task : public base::RefCountedThreadSafe<Task> {
19  public:
20   typedef std::vector<scoped_refptr<Task> > Vector;
21
22   virtual void RunOnWorkerThread() = 0;
23
24   void WillRun();
25   void DidRun();
26   bool HasFinishedRunning() const;
27
28  protected:
29   friend class base::RefCountedThreadSafe<Task>;
30
31   Task();
32   virtual ~Task();
33
34   bool will_run_;
35   bool did_run_;
36 };
37
38 // Dependencies are represented as edges in a task graph. Each graph node is
39 // assigned a priority and a run count that matches the number of dependencies.
40 // Priority range from 0 (most favorable scheduling) to UINT_MAX (least
41 // favorable).
42 struct CC_EXPORT TaskGraph {
43   struct Node {
44     class TaskComparator {
45      public:
46       explicit TaskComparator(const Task* task) : task_(task) {}
47
48       bool operator()(const Node& node) const { return node.task == task_; }
49
50      private:
51       const Task* task_;
52     };
53
54     typedef std::vector<Node> Vector;
55
56     Node(Task* task, unsigned priority, size_t dependencies)
57         : task(task), priority(priority), dependencies(dependencies) {}
58
59     Task* task;
60     unsigned priority;
61     size_t dependencies;
62   };
63
64   struct Edge {
65     typedef std::vector<Edge> Vector;
66
67     Edge(const Task* task, Task* dependent)
68         : task(task), dependent(dependent) {}
69
70     const Task* task;
71     Task* dependent;
72   };
73
74   TaskGraph();
75   ~TaskGraph();
76
77   void Swap(TaskGraph* other);
78   void Reset();
79
80   Node::Vector nodes;
81   Edge::Vector edges;
82 };
83
84 class TaskGraphRunner;
85
86 // Opaque identifier that defines a namespace of tasks.
87 class CC_EXPORT NamespaceToken {
88  public:
89   NamespaceToken() : id_(0) {}
90   ~NamespaceToken() {}
91
92   bool IsValid() const { return id_ != 0; }
93
94  private:
95   friend class TaskGraphRunner;
96
97   explicit NamespaceToken(int id) : id_(id) {}
98
99   int id_;
100 };
101
102 // A TaskGraphRunner is used to process tasks with dependencies. There can
103 // be any number of TaskGraphRunner instances per thread. Tasks can be scheduled
104 // from any thread and they can be run on any thread.
105 class CC_EXPORT TaskGraphRunner {
106  public:
107   TaskGraphRunner();
108   virtual ~TaskGraphRunner();
109
110   // Returns a unique token that can be used to pass a task graph to
111   // ScheduleTasks(). Valid tokens are always nonzero.
112   NamespaceToken GetNamespaceToken();
113
114   // Schedule running of tasks in |graph|. Tasks previously scheduled but no
115   // longer needed will be canceled unless already running. Canceled tasks are
116   // moved to |completed_tasks| without being run. The result is that once
117   // scheduled, a task is guaranteed to end up in the |completed_tasks| queue
118   // even if it later gets canceled by another call to ScheduleTasks().
119   void ScheduleTasks(NamespaceToken token, TaskGraph* graph);
120
121   // Wait for all scheduled tasks to finish running.
122   void WaitForTasksToFinishRunning(NamespaceToken token);
123
124   // Collect all completed tasks in |completed_tasks|.
125   void CollectCompletedTasks(NamespaceToken token,
126                              Task::Vector* completed_tasks);
127
128   // Run tasks until Shutdown() is called.
129   void Run();
130
131   // Process all pending tasks, but don't wait/sleep. Return as soon as all
132   // tasks that can be run are taken care of.
133   void RunUntilIdle();
134
135   // Signals the Run method to return when it becomes idle. It will continue to
136   // process tasks and future tasks as long as they are scheduled.
137   // Warning: if the TaskGraphRunner remains busy, it may never quit.
138   void Shutdown();
139
140  private:
141   struct PrioritizedTask {
142     typedef std::vector<PrioritizedTask> Vector;
143
144     PrioritizedTask(Task* task, unsigned priority)
145         : task(task), priority(priority) {}
146
147     Task* task;
148     unsigned priority;
149   };
150
151   typedef std::vector<const Task*> TaskVector;
152
153   struct TaskNamespace {
154     typedef std::vector<TaskNamespace*> Vector;
155
156     TaskNamespace();
157     ~TaskNamespace();
158
159     // Current task graph.
160     TaskGraph graph;
161
162     // Ordered set of tasks that are ready to run.
163     PrioritizedTask::Vector ready_to_run_tasks;
164
165     // Completed tasks not yet collected by origin thread.
166     Task::Vector completed_tasks;
167
168     // This set contains all currently running tasks.
169     TaskVector running_tasks;
170   };
171
172   typedef std::map<int, TaskNamespace> TaskNamespaceMap;
173
174   static bool CompareTaskPriority(const PrioritizedTask& a,
175                                   const PrioritizedTask& b) {
176     // In this system, numerically lower priority is run first.
177     return a.priority > b.priority;
178   }
179
180   static bool CompareTaskNamespacePriority(const TaskNamespace* a,
181                                            const TaskNamespace* b) {
182     DCHECK(!a->ready_to_run_tasks.empty());
183     DCHECK(!b->ready_to_run_tasks.empty());
184
185     // Compare based on task priority of the ready_to_run_tasks heap .front()
186     // will hold the max element of the heap, except after pop_heap, when max
187     // element is moved to .back().
188     return CompareTaskPriority(a->ready_to_run_tasks.front(),
189                                b->ready_to_run_tasks.front());
190   }
191
192   static bool HasFinishedRunningTasksInNamespace(
193       const TaskNamespace* task_namespace) {
194     return task_namespace->running_tasks.empty() &&
195            task_namespace->ready_to_run_tasks.empty();
196   }
197
198   // Run next task. Caller must acquire |lock_| prior to calling this function
199   // and make sure at least one task is ready to run.
200   void RunTaskWithLockAcquired();
201
202   // This lock protects all members of this class. Do not read or modify
203   // anything without holding this lock. Do not block while holding this lock.
204   mutable base::Lock lock_;
205
206   // Condition variable that is waited on by Run() until new tasks are ready to
207   // run or shutdown starts.
208   base::ConditionVariable has_ready_to_run_tasks_cv_;
209
210   // Condition variable that is waited on by origin threads until a namespace
211   // has finished running all associated tasks.
212   base::ConditionVariable has_namespaces_with_finished_running_tasks_cv_;
213
214   // Provides a unique id to each NamespaceToken.
215   int next_namespace_id_;
216
217   // This set contains all namespaces with pending, running or completed tasks
218   // not yet collected.
219   TaskNamespaceMap namespaces_;
220
221   // Ordered set of task namespaces that have ready to run tasks.
222   TaskNamespace::Vector ready_to_run_namespaces_;
223
224   // Set during shutdown. Tells Run() to return when no more tasks are pending.
225   bool shutdown_;
226
227   DISALLOW_COPY_AND_ASSIGN(TaskGraphRunner);
228 };
229
230 }  // namespace cc
231
232 #endif  // CC_RESOURCES_TASK_GRAPH_RUNNER_H_