Index: cc/base/worker_pool.h |
diff --git a/cc/base/worker_pool.h b/cc/base/worker_pool.h |
index aa49ec9f9bfcf18fc208ab24dcf2201ef4c9e0c6..94c3a611e2e71d60a4ab53dc723f6e686698a115 100644 |
--- a/cc/base/worker_pool.h |
+++ b/cc/base/worker_pool.h |
@@ -5,33 +5,141 @@ |
#ifndef CC_BASE_WORKER_POOL_H_ |
#define CC_BASE_WORKER_POOL_H_ |
+#include <deque> |
#include <string> |
#include "base/cancelable_callback.h" |
+#include "base/memory/ref_counted.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/memory/weak_ptr.h" |
#include "base/message_loop.h" |
#include "cc/base/cc_export.h" |
-#include "cc/base/scoped_ptr_deque.h" |
namespace cc { |
namespace internal { |
-class WorkerPoolTask { |
+class CC_EXPORT WorkerPoolTask |
+ : public base::RefCountedThreadSafe<WorkerPoolTask> { |
public: |
- virtual ~WorkerPoolTask(); |
- |
virtual void RunOnThread(unsigned thread_index) = 0; |
+ virtual void DispatchCompletionCallback() = 0; |
+ void DidSchedule(); |
+ void WillRun(); |
+ void DidRun(); |
void DidComplete(); |
+ bool HasFinished() const; |
+ |
protected: |
- explicit WorkerPoolTask(const base::Closure& reply); |
+ friend class base::RefCountedThreadSafe<WorkerPoolTask>; |
+ |
+ WorkerPoolTask(); |
+ virtual ~WorkerPoolTask(); |
- const base::Closure reply_; |
+ private: |
+ bool did_schedule_; |
+ bool did_run_; |
+ bool did_complete_; |
}; |
nduca
2013/05/21 00:31:13
I guess i'm still puzzled why we have dependency s
reveman
2013/05/21 01:22:36
There's a 1-N relationship between tasks and depen
|
+class CC_EXPORT WorkerPoolTaskDependency { |
+ public: |
+ // Depth-first traversal of dependency graph. Parent nodes are visited |
+ // before children. |
+ class Iterator { |
+ public: |
+ explicit Iterator(const WorkerPoolTaskDependency* root); |
+ ~Iterator(); |
+ |
+ const WorkerPoolTaskDependency* operator->() const { |
+ DCHECK(current_); |
+ return current_; |
+ } |
+ |
+ const WorkerPoolTaskDependency* operator*() const { |
+ DCHECK(current_); |
+ return current_; |
+ } |
+ |
+ Iterator& operator++() { |
+ if (current_->first_child_) { |
+ current_ = current_->first_child_.get(); |
+ return *this; |
+ } |
+ |
+ while (!current_->next_sibling_ && current_ != root_) |
+ current_ = current_->parent_; |
+ if (current_ == root_) |
+ return *this; |
+ |
+ current_ = current_->next_sibling_.get(); |
+ return *this; |
+ } |
+ |
+ operator bool() const { |
+ return current_ != root_; |
+ } |
+ |
+ private: |
+ const WorkerPoolTaskDependency* current_; |
+ const WorkerPoolTaskDependency* root_; |
+ }; |
+ |
+ // Visits each task for all direct children. |
+ class TaskIterator { |
+ public: |
+ explicit TaskIterator(const WorkerPoolTaskDependency* parent); |
+ ~TaskIterator(); |
+ |
+ WorkerPoolTask* operator->() const { |
+ DCHECK(current_); |
+ return current_->task_.get(); |
+ } |
+ |
+ WorkerPoolTask* operator*() const { |
+ DCHECK(current_); |
+ return current_->task_.get(); |
+ } |
+ |
+ TaskIterator& operator++() { |
+ current_ = current_->next_sibling_.get(); |
+ return *this; |
+ } |
+ |
+ operator bool() const { |
+ return !!current_; |
+ } |
+ |
+ private: |
+ const WorkerPoolTaskDependency* current_; |
+ }; |
+ |
+ WorkerPoolTaskDependency(); |
+ ~WorkerPoolTaskDependency(); |
+ |
+ static void Create(WorkerPoolTask* task, |
+ WorkerPoolTaskDependency* parent, |
+ WorkerPoolTaskDependency* dependencies); |
+ |
+ void Swap(WorkerPoolTaskDependency* other); |
+ |
+ WorkerPoolTask* task() const { return task_.get(); } |
+ |
+ protected: |
+ // |parent_| is only set when "parent_->last_child_ == this". |
+ // This enough to traverse graph in O(n) time and O(1) space complexity, |
+ // while also allowing Swap() to be implemented in O(1) time. |
+ WorkerPoolTaskDependency* parent_; |
+ WorkerPoolTaskDependency* last_child_; |
+ scoped_ptr<WorkerPoolTaskDependency> first_child_; |
+ scoped_ptr<WorkerPoolTaskDependency> next_sibling_; |
+ scoped_refptr<WorkerPoolTask> task_; |
+}; |
+ |
+typedef WorkerPoolTaskDependency WorkerPoolTaskGraph; |
+ |
} // namespace internal |
class CC_EXPORT WorkerPoolClient { |
@@ -42,30 +150,15 @@ class CC_EXPORT WorkerPoolClient { |
virtual ~WorkerPoolClient() {} |
}; |
-// A worker thread pool that runs rendering tasks and guarantees completion |
-// of all pending tasks at shutdown. |
+// A worker thread pool that runs tasks provided by task graph and |
+// guarantees completion of all pending tasks at shutdown. |
class CC_EXPORT WorkerPool { |
public: |
- typedef base::Callback<void()> Callback; |
- |
virtual ~WorkerPool(); |
- static scoped_ptr<WorkerPool> Create( |
- size_t num_threads, |
- base::TimeDelta check_for_completed_tasks_delay, |
- const std::string& thread_name_prefix) { |
- return make_scoped_ptr(new WorkerPool(num_threads, |
- check_for_completed_tasks_delay, |
- thread_name_prefix)); |
- } |
- |
// Tells the worker pool to shutdown and returns once all pending tasks have |
// completed. |
- void Shutdown(); |
- |
- // Posts |task| to worker pool. On completion, |reply| |
- // is posted to the thread that called PostTaskAndReply(). |
- void PostTaskAndReply(const Callback& task, const base::Closure& reply); |
+ virtual void Shutdown(); |
// Set a new client. |
void SetClient(WorkerPoolClient* client) { |
@@ -77,32 +170,27 @@ class CC_EXPORT WorkerPool { |
base::TimeDelta check_for_completed_tasks_delay, |
const std::string& thread_name_prefix); |
- void PostTask(scoped_ptr<internal::WorkerPoolTask> task); |
+ void ScheduleTasks(internal::WorkerPoolTaskGraph* task_graph); |
private: |
class Inner; |
friend class Inner; |
- void OnTaskCompleted(); |
- void OnIdle(); |
+ typedef std::deque<scoped_refptr<internal::WorkerPoolTask> > TaskDeque; |
+ |
+ void OnIdle(TaskDeque* completed_tasks); |
void ScheduleCheckForCompletedTasks(); |
void CheckForCompletedTasks(); |
- void DispatchCompletionCallbacks(); |
+ void DispatchCompletionCallbacks(TaskDeque* completed_tasks); |
WorkerPoolClient* client_; |
scoped_refptr<base::MessageLoopProxy> origin_loop_; |
- base::WeakPtrFactory<WorkerPool> weak_ptr_factory_; |
+ base::CancelableClosure check_for_completed_tasks_callback_; |
base::TimeDelta check_for_completed_tasks_delay_; |
bool check_for_completed_tasks_pending_; |
- // Holds all completed tasks for which we have not yet dispatched |
- // reply callbacks. |
- ScopedPtrDeque<internal::WorkerPoolTask> completed_tasks_; |
- |
// Hide the gory details of the worker pool in |inner_|. |
const scoped_ptr<Inner> inner_; |
- |
- DISALLOW_COPY_AND_ASSIGN(WorkerPool); |
}; |
} // namespace cc |