summaryrefslogtreecommitdiffstats
path: root/cc/resources/task_graph_runner.h
diff options
context:
space:
mode:
authorreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-23 09:46:50 +0000
committerreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-23 09:46:50 +0000
commit00d92d32d28ccbca0241051a628d2ed5f982d1cf (patch)
treef736a9d9b72d97d00ae278beb66dcb7e745d14dd /cc/resources/task_graph_runner.h
parent8e1d91e3e45d157f0d279284bc48f47194559d06 (diff)
downloadchromium_src-00d92d32d28ccbca0241051a628d2ed5f982d1cf.zip
chromium_src-00d92d32d28ccbca0241051a628d2ed5f982d1cf.tar.gz
chromium_src-00d92d32d28ccbca0241051a628d2ed5f982d1cf.tar.bz2
Re-land: cc: Remove WorkerPool class and instead use TaskGraphRunner directly.
Removes the unnecessary WorkerPool layer. This makes the job of the TaskGraphRunner more clear and will allow us to remove some complexity and unnecessary heap allocations from the RasterWorkerPool code in follow up patches. Also moves the kNumRasterTasks switch to content/. Refactor only, no changes in behavior. BUG=331844 Review URL: https://codereview.chromium.org/141163019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@246554 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/resources/task_graph_runner.h')
-rw-r--r--cc/resources/task_graph_runner.h235
1 files changed, 235 insertions, 0 deletions
diff --git a/cc/resources/task_graph_runner.h b/cc/resources/task_graph_runner.h
new file mode 100644
index 0000000..0bc15a8
--- /dev/null
+++ b/cc/resources/task_graph_runner.h
@@ -0,0 +1,235 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_RESOURCES_TASK_GRAPH_RUNNER_H_
+#define CC_RESOURCES_TASK_GRAPH_RUNNER_H_
+
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "base/containers/scoped_ptr_hash_map.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/condition_variable.h"
+#include "base/threading/simple_thread.h"
+#include "cc/base/cc_export.h"
+#include "cc/base/scoped_ptr_deque.h"
+
+namespace cc {
+namespace internal {
+
+class CC_EXPORT Task : public base::RefCountedThreadSafe<Task> {
+ public:
+ typedef std::vector<scoped_refptr<Task> > Vector;
+
+ virtual void RunOnWorkerThread(unsigned thread_index) = 0;
+
+ void DidSchedule();
+ void WillRun();
+ void DidRun();
+
+ bool HasFinishedRunning() const;
+
+ protected:
+ friend class base::RefCountedThreadSafe<Task>;
+
+ Task();
+ virtual ~Task();
+
+ bool did_schedule_;
+ bool did_run_;
+};
+
+} // namespace internal
+} // namespace cc
+
+#if defined(COMPILER_GCC)
+namespace BASE_HASH_NAMESPACE {
+template <> struct hash<cc::internal::Task*> {
+ size_t operator()(cc::internal::Task* ptr) const {
+ return hash<size_t>()(reinterpret_cast<size_t>(ptr));
+ }
+};
+} // namespace BASE_HASH_NAMESPACE
+#endif // COMPILER
+
+namespace cc {
+namespace internal {
+
+// Dependencies are represented by edges in a task graph. A graph node
+// store edges as a vector of dependents. Each graph node is assigned
+// a priority and a run count that matches the number of dependencies.
+class CC_EXPORT GraphNode {
+ public:
+ typedef std::vector<GraphNode*> Vector;
+ typedef base::ScopedPtrHashMap<Task*, GraphNode> Map;
+
+ GraphNode(Task* task, unsigned priority);
+ ~GraphNode();
+
+ Task* task() { return task_; }
+
+ void add_dependent(GraphNode* dependent) {
+ DCHECK(dependent);
+ dependents_.push_back(dependent);
+ }
+ const Vector& dependents() const { return dependents_; }
+
+ unsigned priority() const { return priority_; }
+
+ unsigned num_dependencies() const { return num_dependencies_; }
+ void add_dependency() { ++num_dependencies_; }
+ void remove_dependency() {
+ DCHECK(num_dependencies_);
+ --num_dependencies_;
+ }
+
+ private:
+ Task* task_;
+ Vector dependents_;
+ unsigned priority_;
+ unsigned num_dependencies_;
+
+ DISALLOW_COPY_AND_ASSIGN(GraphNode);
+};
+
+class TaskGraphRunner;
+
+// Opaque identifier that defines a namespace of tasks.
+class CC_EXPORT NamespaceToken {
+ public:
+ NamespaceToken() : id_(0) {}
+ ~NamespaceToken() {}
+
+ bool IsValid() const {
+ return id_ != 0;
+ }
+
+ private:
+ friend class TaskGraphRunner;
+
+ explicit NamespaceToken(int id) : id_(id) {}
+
+ int id_;
+};
+
+// A worker thread pool that runs tasks provided by task graph. Destructor
+// might block and should not be used on a thread that needs to be responsive.
+class CC_EXPORT TaskGraphRunner : public base::DelegateSimpleThread::Delegate {
+ public:
+ typedef GraphNode::Map TaskGraph;
+
+ TaskGraphRunner(size_t num_threads, const std::string& thread_name_prefix);
+ virtual ~TaskGraphRunner();
+
+ // Returns a unique token that can be used to pass a task graph to
+ // SetTaskGraph(). Valid tokens are always nonzero.
+ NamespaceToken GetNamespaceToken();
+
+ // Schedule running of tasks in |graph|. Tasks previously scheduled but
+ // no longer needed will be canceled unless already running. Canceled
+ // tasks are moved to |completed_tasks| without being run. The result
+ // is that once scheduled, a task is guaranteed to end up in the
+ // |completed_tasks| queue even if it later get canceled by another
+ // call to SetTaskGraph().
+ void SetTaskGraph(NamespaceToken token, TaskGraph* graph);
+
+ // Wait for all scheduled tasks to finish running.
+ void WaitForTasksToFinishRunning(NamespaceToken token);
+
+ // Collect all completed tasks in |completed_tasks|.
+ void CollectCompletedTasks(
+ NamespaceToken token, Task::Vector* completed_tasks);
+
+ private:
+ struct TaskNamespace {
+ typedef std::vector<TaskNamespace*> Vector;
+
+ TaskNamespace();
+ ~TaskNamespace();
+
+ // This set contains all pending tasks.
+ TaskGraph pending_tasks;
+ // This set contains all currently running tasks.
+ TaskGraph running_tasks;
+ // Completed tasks not yet collected by origin thread.
+ Task::Vector completed_tasks;
+ // Ordered set of tasks that are ready to run.
+ internal::GraphNode::Vector ready_to_run_tasks;
+ };
+
+ typedef base::ScopedPtrHashMap<int, TaskNamespace> TaskNamespaceMap;
+
+ static bool CompareTaskPriority(const internal::GraphNode* a,
+ const internal::GraphNode* b) {
+ // In this system, numerically lower priority is run first.
+ if (a->priority() != b->priority())
+ return a->priority() > b->priority();
+
+ // Run task with most dependents first when priority is the same.
+ return a->dependents().size() < b->dependents().size();
+ }
+
+ static bool CompareTaskNamespacePriority(const TaskNamespace* a,
+ const TaskNamespace* b) {
+ DCHECK(!a->ready_to_run_tasks.empty());
+ DCHECK(!b->ready_to_run_tasks.empty());
+
+ // Compare based on task priority of the ready_to_run_tasks heap
+ // .front() will hold the max element of the heap,
+ // except after pop_heap, when max element is moved to .back().
+ return CompareTaskPriority(a->ready_to_run_tasks.front(),
+ b->ready_to_run_tasks.front());
+ }
+
+ static bool HasFinishedRunningTasksInNamespace(
+ TaskNamespace* task_namespace) {
+ return task_namespace->pending_tasks.empty() &&
+ task_namespace->running_tasks.empty();
+ }
+
+ // Overridden from base::DelegateSimpleThread:
+ virtual void Run() OVERRIDE;
+
+ // This lock protects all members of this class. Do not read or modify
+ // anything without holding this lock. Do not block while holding this
+ // lock.
+ mutable base::Lock lock_;
+
+ // Condition variable that is waited on by worker threads until new
+ // tasks are ready to run or shutdown starts.
+ base::ConditionVariable has_ready_to_run_tasks_cv_;
+
+ // Condition variable that is waited on by origin threads until a
+ // namespace has finished running all associated tasks.
+ base::ConditionVariable has_namespaces_with_finished_running_tasks_cv_;
+
+ // Provides a unique id to each NamespaceToken.
+ int next_namespace_id_;
+
+ // This set contains all namespaces with pending, running or completed
+ // tasks not yet collected.
+ TaskNamespaceMap namespaces_;
+
+ // Ordered set of task namespaces that have ready to run tasks.
+ TaskNamespace::Vector ready_to_run_namespaces_;
+
+ // Provides each running thread loop with a unique index. First thread
+ // loop index is 0.
+ unsigned next_thread_index_;
+
+ // Set during shutdown. Tells workers to exit when no more tasks
+ // are pending.
+ bool shutdown_;
+
+ ScopedPtrDeque<base::DelegateSimpleThread> workers_;
+
+ DISALLOW_COPY_AND_ASSIGN(TaskGraphRunner);
+};
+
+} // namespace internal
+} // namespace cc
+
+#endif // CC_RESOURCES_TASK_GRAPH_RUNNER_H_