Commit 8876310a authored by rtenneti@chromium.org's avatar rtenneti@chromium.org

Revert 202363 "cc: Cancel and re-prioritize worker pool tasks."

> cc: Cancel and re-prioritize worker pool tasks.
> 
> This adds a task graph interface to the worker pool and
> implements a simple queue instance of this interface for
> use by the tile manager.
> 
> The task graph interface can be used describe more
> complicated task dependencies in the future and
> provides the immediate benefit of seamlessly being
> able to cancel and re-prioritize tasks.
> 
> BUG=178974
> 
> Review URL: https://chromiumcodereview.appspot.com/14689004

TBR=reveman@chromium.org

Review URL: https://codereview.chromium.org/16178002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202736 0039d316-1c4b-4281-b951-d872f2087c98
parent a649b5e5
...@@ -31,7 +31,7 @@ class ScopedPtrHashMap { ...@@ -31,7 +31,7 @@ class ScopedPtrHashMap {
~ScopedPtrHashMap() { clear(); } ~ScopedPtrHashMap() { clear(); }
void swap(ScopedPtrHashMap<Key, Value>& other) { void swap(ScopedPtrHashMap<Key, Value*>& other) {
data_.swap(other.data_); data_.swap(other.data_);
} }
......
This diff is collapsed.
...@@ -5,52 +5,31 @@ ...@@ -5,52 +5,31 @@
#ifndef CC_BASE_WORKER_POOL_H_ #ifndef CC_BASE_WORKER_POOL_H_
#define CC_BASE_WORKER_POOL_H_ #define CC_BASE_WORKER_POOL_H_
#include <deque>
#include <string> #include <string>
#include <vector>
#include "base/cancelable_callback.h" #include "base/cancelable_callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/message_loop.h" #include "base/message_loop.h"
#include "cc/base/cc_export.h" #include "cc/base/cc_export.h"
#include "cc/base/scoped_ptr_deque.h"
namespace cc { namespace cc {
namespace internal { namespace internal {
class CC_EXPORT WorkerPoolTask class WorkerPoolTask {
: public base::RefCountedThreadSafe<WorkerPoolTask> {
public: public:
typedef std::vector<scoped_refptr<WorkerPoolTask> > TaskVector; virtual ~WorkerPoolTask();
virtual void RunOnThread(unsigned thread_index) = 0; virtual void RunOnThread(unsigned thread_index) = 0;
virtual void DispatchCompletionCallback() = 0;
void DidSchedule();
void WillRun();
void DidRun();
void DidComplete(); void DidComplete();
bool IsReadyToRun() const;
bool HasFinishedRunning() const;
bool HasCompleted() const;
TaskVector& dependencies() { return dependencies_; }
protected: protected:
friend class base::RefCountedThreadSafe<WorkerPoolTask>; explicit WorkerPoolTask(const base::Closure& reply);
WorkerPoolTask();
explicit WorkerPoolTask(TaskVector* dependencies);
virtual ~WorkerPoolTask();
private: const base::Closure reply_;
bool did_schedule_;
bool did_run_;
bool did_complete_;
TaskVector dependencies_;
}; };
} // namespace internal } // namespace internal
...@@ -63,49 +42,67 @@ class CC_EXPORT WorkerPoolClient { ...@@ -63,49 +42,67 @@ class CC_EXPORT WorkerPoolClient {
virtual ~WorkerPoolClient() {} virtual ~WorkerPoolClient() {}
}; };
// A worker thread pool that runs tasks provided by task graph and // A worker thread pool that runs rendering tasks and guarantees completion
// guarantees completion of all pending tasks at shutdown. // of all pending tasks at shutdown.
class CC_EXPORT WorkerPool { class CC_EXPORT WorkerPool {
public: public:
typedef base::Callback<void()> Callback;
virtual ~WorkerPool(); 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 // Tells the worker pool to shutdown and returns once all pending tasks have
// completed. // completed.
virtual void Shutdown(); 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);
// Set a new client. // Set a new client.
void SetClient(WorkerPoolClient* client) { void SetClient(WorkerPoolClient* client) {
client_ = client; client_ = client;
} }
// Force a check for completed tasks.
void CheckForCompletedTasks();
protected: protected:
WorkerPool(size_t num_threads, WorkerPool(size_t num_threads,
base::TimeDelta check_for_completed_tasks_delay, base::TimeDelta check_for_completed_tasks_delay,
const std::string& thread_name_prefix); const std::string& thread_name_prefix);
void ScheduleTasks(internal::WorkerPoolTask* root); void PostTask(scoped_ptr<internal::WorkerPoolTask> task);
private: private:
class Inner; class Inner;
friend class Inner; friend class Inner;
typedef std::deque<scoped_refptr<internal::WorkerPoolTask> > TaskDeque; void OnTaskCompleted();
void OnIdle();
void OnIdle(TaskDeque* completed_tasks);
void ScheduleCheckForCompletedTasks(); void ScheduleCheckForCompletedTasks();
void DispatchCompletionCallbacks(TaskDeque* completed_tasks); void CheckForCompletedTasks();
void DispatchCompletionCallbacks();
WorkerPoolClient* client_; WorkerPoolClient* client_;
scoped_refptr<base::MessageLoopProxy> origin_loop_; scoped_refptr<base::MessageLoopProxy> origin_loop_;
base::CancelableClosure check_for_completed_tasks_callback_; base::WeakPtrFactory<WorkerPool> weak_ptr_factory_;
base::TimeDelta check_for_completed_tasks_delay_; base::TimeDelta check_for_completed_tasks_delay_;
bool check_for_completed_tasks_pending_; 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_|. // Hide the gory details of the worker pool in |inner_|.
const scoped_ptr<Inner> inner_; const scoped_ptr<Inner> inner_;
DISALLOW_COPY_AND_ASSIGN(WorkerPool);
}; };
} // namespace cc } // namespace cc
......
// Copyright 2013 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.
#include "cc/base/worker_pool.h"
#include "base/time.h"
#include "cc/base/completion_event.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
namespace {
static const int kTimeLimitMillis = 2000;
static const int kWarmupRuns = 5;
static const int kTimeCheckInterval = 10;
class PerfTaskImpl : public internal::WorkerPoolTask {
public:
explicit PerfTaskImpl(internal::WorkerPoolTask::TaskVector* dependencies)
: internal::WorkerPoolTask(dependencies) {}
// Overridden from internal::WorkerPoolTask:
virtual void RunOnThread(unsigned thread_index) OVERRIDE {}
virtual void DispatchCompletionCallback() OVERRIDE {}
private:
virtual ~PerfTaskImpl() {}
};
class PerfControlTaskImpl : public internal::WorkerPoolTask {
public:
explicit PerfControlTaskImpl(
internal::WorkerPoolTask::TaskVector* dependencies)
: internal::WorkerPoolTask(dependencies),
did_start_(new CompletionEvent),
can_finish_(new CompletionEvent) {}
// Overridden from internal::WorkerPoolTask:
virtual void RunOnThread(unsigned thread_index) OVERRIDE {
did_start_->Signal();
can_finish_->Wait();
}
virtual void DispatchCompletionCallback() OVERRIDE {}
void WaitForTaskToStartRunning() {
did_start_->Wait();
}
void AllowTaskToFinish() {
can_finish_->Signal();
}
private:
virtual ~PerfControlTaskImpl() {}
scoped_ptr<CompletionEvent> did_start_;
scoped_ptr<CompletionEvent> can_finish_;
};
class PerfWorkerPool : public WorkerPool {
public:
PerfWorkerPool() : WorkerPool(1, base::TimeDelta::FromDays(1024), "test") {}
virtual ~PerfWorkerPool() {}
static scoped_ptr<PerfWorkerPool> Create() {
return make_scoped_ptr(new PerfWorkerPool);
}
void ScheduleTasks(internal::WorkerPoolTask* root) {
WorkerPool::ScheduleTasks(root);
}
};
class WorkerPoolPerfTest : public testing::Test,
public WorkerPoolClient {
public:
WorkerPoolPerfTest() : num_runs_(0) {}
// Overridden from testing::Test:
virtual void SetUp() OVERRIDE {
worker_pool_ = PerfWorkerPool::Create();
worker_pool_->SetClient(this);
}
virtual void TearDown() OVERRIDE {
worker_pool_->Shutdown();
}
// Overridden from WorkerPoolClient:
virtual void DidFinishDispatchingWorkerPoolCompletionCallbacks() OVERRIDE {}
void EndTest() {
elapsed_ = base::TimeTicks::HighResNow() - start_time_;
}
void AfterTest(const std::string test_name) {
// Format matches chrome/test/perf/perf_test.h:PrintResult
printf("*RESULT %s: %.2f runs/s\n",
test_name.c_str(),
num_runs_ / elapsed_.InSecondsF());
}
void BuildTaskGraph(internal::WorkerPoolTask::TaskVector* dependencies,
unsigned current_depth,
unsigned max_depth,
unsigned num_children_per_node) {
internal::WorkerPoolTask::TaskVector children;
if (current_depth < max_depth) {
for (unsigned i = 0; i < num_children_per_node; ++i) {
BuildTaskGraph(&children,
current_depth + 1,
max_depth,
num_children_per_node);
}
} else if (leaf_task_) {
children.push_back(leaf_task_);
}
dependencies->push_back(make_scoped_refptr(new PerfTaskImpl(&children)));
}
bool DidRun() {
++num_runs_;
if (num_runs_ == kWarmupRuns)
start_time_ = base::TimeTicks::HighResNow();
if (!start_time_.is_null() && (num_runs_ % kTimeCheckInterval) == 0) {
base::TimeDelta elapsed = base::TimeTicks::HighResNow() - start_time_;
if (elapsed >= base::TimeDelta::FromMilliseconds(kTimeLimitMillis)) {
elapsed_ = elapsed;
return false;
}
}
return true;
}
void RunBuildTaskGraphTest(const std::string test_name,
unsigned max_depth,
unsigned num_children_per_node) {
start_time_ = base::TimeTicks();
num_runs_ = 0;
do {
internal::WorkerPoolTask::TaskVector children;
BuildTaskGraph(&children, 0, max_depth, num_children_per_node);
} while (DidRun());
AfterTest(test_name);
}
void RunScheduleTasksTest(const std::string test_name,
unsigned max_depth,
unsigned num_children_per_node) {
start_time_ = base::TimeTicks();
num_runs_ = 0;
do {
internal::WorkerPoolTask::TaskVector empty;
leaf_task_ = make_scoped_refptr(new PerfControlTaskImpl(&empty));
internal::WorkerPoolTask::TaskVector children;
BuildTaskGraph(&children, 0, max_depth, num_children_per_node);
scoped_refptr<PerfTaskImpl> root_task(
make_scoped_refptr(new PerfTaskImpl(&children)));
worker_pool_->ScheduleTasks(root_task);
leaf_task_->WaitForTaskToStartRunning();
worker_pool_->ScheduleTasks(NULL);
worker_pool_->CheckForCompletedTasks();
leaf_task_->AllowTaskToFinish();
} while (DidRun());
AfterTest(test_name);
}
void RunExecuteTasksTest(const std::string test_name,
unsigned max_depth,
unsigned num_children_per_node) {
start_time_ = base::TimeTicks();
num_runs_ = 0;
do {
internal::WorkerPoolTask::TaskVector children;
BuildTaskGraph(&children, 0, max_depth, num_children_per_node);
scoped_refptr<PerfControlTaskImpl> root_task(
make_scoped_refptr(new PerfControlTaskImpl(&children)));
worker_pool_->ScheduleTasks(root_task);
root_task->WaitForTaskToStartRunning();
root_task->AllowTaskToFinish();
worker_pool_->CheckForCompletedTasks();
} while (DidRun());
AfterTest(test_name);
}
protected:
scoped_ptr<PerfWorkerPool> worker_pool_;
scoped_refptr<PerfControlTaskImpl> leaf_task_;
base::TimeTicks start_time_;
base::TimeDelta elapsed_;
int num_runs_;
};
TEST_F(WorkerPoolPerfTest, BuildTaskGraph) {
RunBuildTaskGraphTest("build_task_graph_1_10", 1, 10);
RunBuildTaskGraphTest("build_task_graph_1_1000", 1, 1000);
RunBuildTaskGraphTest("build_task_graph_2_10", 2, 10);
RunBuildTaskGraphTest("build_task_graph_5_5", 5, 5);
RunBuildTaskGraphTest("build_task_graph_10_2", 10, 2);
RunBuildTaskGraphTest("build_task_graph_1000_1", 1000, 1);
RunBuildTaskGraphTest("build_task_graph_10_1", 10, 1);
}
TEST_F(WorkerPoolPerfTest, ScheduleTasks) {
RunScheduleTasksTest("schedule_tasks_1_10", 1, 10);
RunScheduleTasksTest("schedule_tasks_1_1000", 1, 1000);
RunScheduleTasksTest("schedule_tasks_2_10", 2, 10);
RunScheduleTasksTest("schedule_tasks_5_5", 5, 5);
RunScheduleTasksTest("schedule_tasks_10_2", 10, 2);
RunScheduleTasksTest("schedule_tasks_1000_1", 1000, 1);
RunScheduleTasksTest("schedule_tasks_10_1", 10, 1);
}
TEST_F(WorkerPoolPerfTest, ExecuteTasks) {
RunExecuteTasksTest("execute_tasks_1_10", 1, 10);
RunExecuteTasksTest("execute_tasks_1_1000", 1, 1000);
RunExecuteTasksTest("execute_tasks_2_10", 2, 10);
RunExecuteTasksTest("execute_tasks_5_5", 5, 5);
RunExecuteTasksTest("execute_tasks_10_2", 10, 2);
RunExecuteTasksTest("execute_tasks_1000_1", 1000, 1);
RunExecuteTasksTest("execute_tasks_10_1", 10, 1);
}
} // namespace
} // namespace cc
...@@ -4,101 +4,27 @@ ...@@ -4,101 +4,27 @@
#include "cc/base/worker_pool.h" #include "cc/base/worker_pool.h"
#include <vector>
#include "cc/base/completion_event.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace cc { namespace cc {
namespace { namespace {
class FakeTaskImpl : public internal::WorkerPoolTask {
public:
FakeTaskImpl(const base::Closure& callback,
const base::Closure& reply,
internal::WorkerPoolTask::TaskVector* dependencies)
: internal::WorkerPoolTask(dependencies),
callback_(callback),
reply_(reply) {
}
FakeTaskImpl(const base::Closure& callback, const base::Closure& reply)
: callback_(callback),
reply_(reply) {
}
// Overridden from internal::WorkerPoolTask:
virtual void RunOnThread(unsigned thread_index) OVERRIDE {
if (!callback_.is_null())
callback_.Run();
}
virtual void DispatchCompletionCallback() OVERRIDE {
if (!reply_.is_null())
reply_.Run();
}
private:
virtual ~FakeTaskImpl() {}
const base::Closure callback_;
const base::Closure reply_;
};
class FakeWorkerPool : public WorkerPool {
public:
FakeWorkerPool() : WorkerPool(1, base::TimeDelta::FromDays(1024), "test") {}
virtual ~FakeWorkerPool() {}
static scoped_ptr<FakeWorkerPool> Create() {
return make_scoped_ptr(new FakeWorkerPool);
}
void ScheduleTasks(const base::Closure& callback,
const base::Closure& reply,
const base::Closure& dependency,
int count) {
scoped_refptr<FakeTaskImpl> dependency_task(
new FakeTaskImpl(dependency, base::Closure()));
internal::WorkerPoolTask::TaskVector tasks;
for (int i = 0; i < count; ++i) {
internal::WorkerPoolTask::TaskVector dependencies(1, dependency_task);
tasks.push_back(new FakeTaskImpl(callback, reply, &dependencies));
}
scoped_refptr<FakeTaskImpl> completion_task(
new FakeTaskImpl(base::Bind(&FakeWorkerPool::OnTasksCompleted,
base::Unretained(this)),
base::Closure(),
&tasks));
scheduled_tasks_completion_.reset(new CompletionEvent);
WorkerPool::ScheduleTasks(completion_task);
}
void WaitForTasksToComplete() {
DCHECK(scheduled_tasks_completion_);
scheduled_tasks_completion_->Wait();
}
private:
void OnTasksCompleted() {
DCHECK(scheduled_tasks_completion_);
scheduled_tasks_completion_->Signal();
}
scoped_ptr<CompletionEvent> scheduled_tasks_completion_;
};
class WorkerPoolTest : public testing::Test, class WorkerPoolTest : public testing::Test,
public WorkerPoolClient { public WorkerPoolClient {
public: public:
WorkerPoolTest() : finish_dispatching_completion_callbacks_count_(0) {} WorkerPoolTest()
virtual ~WorkerPoolTest() {} : run_task_count_(0),
on_task_completed_count_(0),
finish_dispatching_completion_callbacks_count_(0) {
}
virtual ~WorkerPoolTest() {
}
// Overridden from testing::Test:
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
Reset(); Reset();
} }
virtual void TearDown() OVERRIDE { virtual void TearDown() OVERRIDE {
worker_pool_->Shutdown(); worker_pool_->Shutdown();
} }
...@@ -109,34 +35,35 @@ class WorkerPoolTest : public testing::Test, ...@@ -109,34 +35,35 @@ class WorkerPoolTest : public testing::Test,
} }
void Reset() { void Reset() {
worker_pool_ = FakeWorkerPool::Create(); worker_pool_ = WorkerPool::Create(1,
base::TimeDelta::FromDays(1024),
"test");
worker_pool_->SetClient(this); worker_pool_->SetClient(this);
} }
void RunAllTasksAndReset() { void RunAllTasksAndReset() {
worker_pool_->WaitForTasksToComplete();
worker_pool_->Shutdown(); worker_pool_->Shutdown();
Reset(); Reset();
} }
FakeWorkerPool* worker_pool() { WorkerPool* worker_pool() {
return worker_pool_.get(); return worker_pool_.get();
} }
void RunTask(unsigned id) { void RunTask() {
run_task_ids_.push_back(id); ++run_task_count_;
} }
void OnTaskCompleted(unsigned id) { void OnTaskCompleted() {
on_task_completed_ids_.push_back(id); ++on_task_completed_count_;
} }
const std::vector<unsigned>& run_task_ids() { unsigned run_task_count() {
return run_task_ids_; return run_task_count_;
} }
const std::vector<unsigned>& on_task_completed_ids() { unsigned on_task_completed_count() {
return on_task_completed_ids_; return on_task_completed_count_;
} }
unsigned finish_dispatching_completion_callbacks_count() { unsigned finish_dispatching_completion_callbacks_count() {
...@@ -144,72 +71,39 @@ class WorkerPoolTest : public testing::Test, ...@@ -144,72 +71,39 @@ class WorkerPoolTest : public testing::Test,
} }
private: private:
scoped_ptr<FakeWorkerPool> worker_pool_; scoped_ptr<WorkerPool> worker_pool_;
std::vector<unsigned> run_task_ids_; unsigned run_task_count_;
std::vector<unsigned> on_task_completed_ids_; unsigned on_task_completed_count_;
unsigned finish_dispatching_completion_callbacks_count_; unsigned finish_dispatching_completion_callbacks_count_;
}; };
TEST_F(WorkerPoolTest, Basic) { TEST_F(WorkerPoolTest, Basic) {
EXPECT_EQ(0u, run_task_ids().size()); EXPECT_EQ(0u, run_task_count());
EXPECT_EQ(0u, on_task_completed_ids().size()); EXPECT_EQ(0u, on_task_completed_count());
EXPECT_EQ(0u, finish_dispatching_completion_callbacks_count()); EXPECT_EQ(0u, finish_dispatching_completion_callbacks_count());
worker_pool()->ScheduleTasks( worker_pool()->PostTaskAndReply(
base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u), base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this)),
base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 0u), base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this)));
base::Closure(),
1);
RunAllTasksAndReset(); RunAllTasksAndReset();
EXPECT_EQ(1u, run_task_ids().size()); EXPECT_EQ(1u, run_task_count());
EXPECT_EQ(1u, on_task_completed_ids().size()); EXPECT_EQ(1u, on_task_completed_count());
EXPECT_EQ(1u, finish_dispatching_completion_callbacks_count()); EXPECT_EQ(1u, finish_dispatching_completion_callbacks_count());
worker_pool()->ScheduleTasks( worker_pool()->PostTaskAndReply(
base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u), base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this)),
base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 0u), base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this)));
base::Closure(), worker_pool()->PostTaskAndReply(
2); base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this)),
base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this)));
RunAllTasksAndReset(); RunAllTasksAndReset();
EXPECT_EQ(3u, run_task_ids().size()); EXPECT_EQ(3u, run_task_count());
EXPECT_EQ(3u, on_task_completed_ids().size()); EXPECT_EQ(3u, on_task_completed_count());
EXPECT_EQ(2u, finish_dispatching_completion_callbacks_count()); EXPECT_EQ(2u, finish_dispatching_completion_callbacks_count());
} }
TEST_F(WorkerPoolTest, Dependencies) {
worker_pool()->ScheduleTasks(
base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 1u),
base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 1u),
base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u),
1);
RunAllTasksAndReset();
// Check if dependency ran before task.
ASSERT_EQ(2u, run_task_ids().size());
EXPECT_EQ(0u, run_task_ids()[0]);
EXPECT_EQ(1u, run_task_ids()[1]);
ASSERT_EQ(1u, on_task_completed_ids().size());
EXPECT_EQ(1u, on_task_completed_ids()[0]);
worker_pool()->ScheduleTasks(
base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 1u),
base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 1u),
base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u),
2);
RunAllTasksAndReset();
// Dependency should only run once.
ASSERT_EQ(5u, run_task_ids().size());
EXPECT_EQ(0u, run_task_ids()[2]);
EXPECT_EQ(1u, run_task_ids()[3]);
EXPECT_EQ(1u, run_task_ids()[4]);
ASSERT_EQ(3u, on_task_completed_ids().size());
EXPECT_EQ(1u, on_task_completed_ids()[1]);
EXPECT_EQ(1u, on_task_completed_ids()[2]);
}
} // namespace } // namespace
} // namespace cc } // namespace cc
...@@ -226,10 +226,9 @@ ...@@ -226,10 +226,9 @@
'cc_test_support', 'cc_test_support',
], ],
'sources': [ 'sources': [
'base/worker_pool_perftest.cc',
'test/cc_test_suite.cc',
'test/run_all_unittests.cc',
'trees/layer_tree_host_perftest.cc', 'trees/layer_tree_host_perftest.cc',
'test/run_all_unittests.cc',
'test/cc_test_suite.cc',
], ],
'include_dirs': [ 'include_dirs': [
'test', 'test',
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
#ifndef CC_RESOURCES_MANAGED_TILE_STATE_H_ #ifndef CC_RESOURCES_MANAGED_TILE_STATE_H_
#define CC_RESOURCES_MANAGED_TILE_STATE_H_ #define CC_RESOURCES_MANAGED_TILE_STATE_H_
#include "base/hash_tables.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "cc/resources/platform_color.h" #include "cc/resources/platform_color.h"
#include "cc/resources/raster_worker_pool.h"
#include "cc/resources/resource_pool.h" #include "cc/resources/resource_pool.h"
#include "cc/resources/resource_provider.h" #include "cc/resources/resource_provider.h"
#include "cc/resources/tile_manager.h" #include "cc/resources/tile_manager.h"
...@@ -113,10 +113,11 @@ class CC_EXPORT ManagedTileState { ...@@ -113,10 +113,11 @@ class CC_EXPORT ManagedTileState {
scoped_ptr<base::Value> AsValue() const; scoped_ptr<base::Value> AsValue() const;
// Persisted state: valid all the time. // Persisted state: valid all the time.
typedef base::hash_set<uint32_t> PixelRefSet;
PixelRefSet decoded_pixel_refs;
TileVersion tile_version; TileVersion tile_version;
bool picture_pile_analyzed;
PicturePileImpl::Analysis picture_pile_analysis; PicturePileImpl::Analysis picture_pile_analysis;
RasterWorkerPool::Task raster_task; bool picture_pile_analyzed;
// Ephemeral state, valid only during TileManager::ManageTiles. // Ephemeral state, valid only during TileManager::ManageTiles.
bool is_in_never_bin_on_both_trees() const { bool is_in_never_bin_on_both_trees() const {
......
...@@ -10,72 +10,24 @@ namespace cc { ...@@ -10,72 +10,24 @@ namespace cc {
namespace { namespace {
class RasterWorkerPoolContainerTaskImpl : public internal::WorkerPoolTask {
public:
RasterWorkerPoolContainerTaskImpl(
internal::WorkerPoolTask::TaskVector* dependencies)
: internal::WorkerPoolTask(dependencies) {
}
// Overridden from internal::WorkerPoolTask:
virtual void RunOnThread(unsigned thread_index) OVERRIDE {}
virtual void DispatchCompletionCallback() OVERRIDE {}
private:
virtual ~RasterWorkerPoolContainerTaskImpl() {}
};
class RasterWorkerPoolTaskImpl : public internal::WorkerPoolTask { class RasterWorkerPoolTaskImpl : public internal::WorkerPoolTask {
public: public:
RasterWorkerPoolTaskImpl(const base::Closure& callback, RasterWorkerPoolTaskImpl(PicturePileImpl* picture_pile,
const RasterWorkerPool::Task::Reply& reply) const RasterWorkerPool::RasterCallback& task,
: callback_(callback), const base::Closure& reply)
reply_(reply) { : internal::WorkerPoolTask(reply),
}
// Overridden from internal::WorkerPoolTask:
virtual void RunOnThread(unsigned thread_index) OVERRIDE {
callback_.Run();
}
virtual void DispatchCompletionCallback() OVERRIDE {
reply_.Run(!HasFinishedRunning());
}
private:
virtual ~RasterWorkerPoolTaskImpl() {}
const base::Closure callback_;
const RasterWorkerPool::Task::Reply reply_;
};
class RasterWorkerPoolPictureTaskImpl : public internal::WorkerPoolTask {
public:
RasterWorkerPoolPictureTaskImpl(
PicturePileImpl* picture_pile,
const RasterWorkerPool::PictureTask::Callback& callback,
const RasterWorkerPool::Task::Reply& reply,
internal::WorkerPoolTask::TaskVector* dependencies)
: internal::WorkerPoolTask(dependencies),
picture_pile_(picture_pile), picture_pile_(picture_pile),
callback_(callback), task_(task) {
reply_(reply) {
DCHECK(picture_pile_); DCHECK(picture_pile_);
} }
// Overridden from internal::WorkerPoolTask:
virtual void RunOnThread(unsigned thread_index) OVERRIDE { virtual void RunOnThread(unsigned thread_index) OVERRIDE {
callback_.Run(picture_pile_->GetCloneForDrawingOnThread(thread_index)); task_.Run(picture_pile_->GetCloneForDrawingOnThread(thread_index));
}
virtual void DispatchCompletionCallback() OVERRIDE {
reply_.Run(!HasFinishedRunning());
} }
private: private:
virtual ~RasterWorkerPoolPictureTaskImpl() {}
scoped_refptr<PicturePileImpl> picture_pile_; scoped_refptr<PicturePileImpl> picture_pile_;
const RasterWorkerPool::PictureTask::Callback callback_; RasterWorkerPool::RasterCallback task_;
const RasterWorkerPool::Task::Reply reply_;
}; };
const char* kWorkerThreadNamePrefix = "CompositorRaster"; const char* kWorkerThreadNamePrefix = "CompositorRaster";
...@@ -84,69 +36,23 @@ const int kCheckForCompletedTasksDelayMs = 6; ...@@ -84,69 +36,23 @@ const int kCheckForCompletedTasksDelayMs = 6;
} // namespace } // namespace
RasterWorkerPool::Task::Queue::Queue() { RasterWorkerPool::RasterWorkerPool(size_t num_threads)
} : WorkerPool(
num_threads,
RasterWorkerPool::Task::Queue::~Queue() { base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs),
} kWorkerThreadNamePrefix) {
void RasterWorkerPool::Task::Queue::Append(const Task& task) {
DCHECK(!task.is_null());
tasks_.push_back(task.internal_);
}
RasterWorkerPool::Task::Task() {
}
RasterWorkerPool::Task::Task(const base::Closure& callback,
const Reply& reply)
: internal_(new RasterWorkerPoolTaskImpl(callback, reply)) {
}
RasterWorkerPool::Task::Task(Queue* dependencies)
: internal_(new RasterWorkerPoolContainerTaskImpl(&dependencies->tasks_)) {
}
RasterWorkerPool::Task::Task(scoped_refptr<internal::WorkerPoolTask> internal)
: internal_(internal) {
}
RasterWorkerPool::Task::~Task() {
}
void RasterWorkerPool::Task::Reset() {
internal_ = NULL;
}
RasterWorkerPool::PictureTask::PictureTask(PicturePileImpl* picture_pile,
const Callback& callback,
const Reply& reply,
Task::Queue* dependencies)
: RasterWorkerPool::Task(
new RasterWorkerPoolPictureTaskImpl(picture_pile,
callback,
reply,
&dependencies->tasks_)) {
}
RasterWorkerPool::RasterWorkerPool(size_t num_threads) : WorkerPool(
num_threads,
base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs),
kWorkerThreadNamePrefix) {
} }
RasterWorkerPool::~RasterWorkerPool() { RasterWorkerPool::~RasterWorkerPool() {
} }
void RasterWorkerPool::Shutdown() { void RasterWorkerPool::PostRasterTaskAndReply(PicturePileImpl* picture_pile,
// Cancel all previously scheduled tasks. const RasterCallback& task,
WorkerPool::ScheduleTasks(NULL); const base::Closure& reply) {
PostTask(make_scoped_ptr(new RasterWorkerPoolTaskImpl(
WorkerPool::Shutdown(); picture_pile,
} task,
reply)).PassAs<internal::WorkerPoolTask>());
void RasterWorkerPool::ScheduleTasks(Task* task) {
WorkerPool::ScheduleTasks(task ? task->internal_ : NULL);
} }
} // namespace cc } // namespace cc
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef CC_RESOURCES_RASTER_WORKER_POOL_H_ #ifndef CC_RESOURCES_RASTER_WORKER_POOL_H_
#define CC_RESOURCES_RASTER_WORKER_POOL_H_ #define CC_RESOURCES_RASTER_WORKER_POOL_H_
#include <string>
#include "cc/base/worker_pool.h" #include "cc/base/worker_pool.h"
namespace cc { namespace cc {
...@@ -13,55 +15,7 @@ class PicturePileImpl; ...@@ -13,55 +15,7 @@ class PicturePileImpl;
// A worker thread pool that runs raster tasks. // A worker thread pool that runs raster tasks.
class CC_EXPORT RasterWorkerPool : public WorkerPool { class CC_EXPORT RasterWorkerPool : public WorkerPool {
public: public:
class Task { typedef base::Callback<void(PicturePileImpl* picture_pile)> RasterCallback;
public:
typedef base::Callback<void(bool)> Reply;
// Highest priority task first. Order of execution is not guaranteed.
class Queue {
public:
Queue();
~Queue();
bool empty() const { return tasks_.empty(); }
// Add task to the back of the queue.
void Append(const Task& task);
private:
friend class RasterWorkerPool;
internal::WorkerPoolTask::TaskVector tasks_;
};
Task();
Task(const base::Closure& callback, const Reply& reply);
explicit Task(Queue* dependencies);
~Task();
// Returns true if Task is null (doesn't refer to anything).
bool is_null() const { return !internal_; }
// Returns the Task into an uninitialized state.
void Reset();
protected:
friend class RasterWorkerPool;
explicit Task(scoped_refptr<internal::WorkerPoolTask> internal);
scoped_refptr<internal::WorkerPoolTask> internal_;
};
class PictureTask : public Task {
public:
typedef base::Callback<void(PicturePileImpl*)> Callback;
PictureTask(PicturePileImpl* picture_pile,
const Callback& callback,
const Reply& reply,
Queue* dependencies);
};
virtual ~RasterWorkerPool(); virtual ~RasterWorkerPool();
...@@ -69,16 +23,9 @@ class CC_EXPORT RasterWorkerPool : public WorkerPool { ...@@ -69,16 +23,9 @@ class CC_EXPORT RasterWorkerPool : public WorkerPool {
return make_scoped_ptr(new RasterWorkerPool(num_threads)); return make_scoped_ptr(new RasterWorkerPool(num_threads));
} }
// Tells the worker pool to shutdown after canceling all previously void PostRasterTaskAndReply(PicturePileImpl* picture_pile,
// scheduled tasks. Reply callbacks are still guaranteed to run. const RasterCallback& task,
virtual void Shutdown() OVERRIDE; const base::Closure& reply);
// Schedule running of |root| task and all its dependencies. Tasks
// previously scheduled but no longer needed to run |root| will be
// canceled unless already running. Once scheduled, reply callbacks
// are guaranteed to run for all tasks even if they later get
// canceled by another call to ScheduleTasks().
void ScheduleTasks(Task* root);
private: private:
explicit RasterWorkerPool(size_t num_threads); explicit RasterWorkerPool(size_t num_threads);
......
...@@ -981,8 +981,6 @@ uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id) { ...@@ -981,8 +981,6 @@ uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id) {
context3d->mapBufferCHROMIUM( context3d->mapBufferCHROMIUM(
GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY)); GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
// Buffer is required to be 4-byte aligned.
CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
return image; return image;
} }
......
This diff is collapsed.
...@@ -62,8 +62,6 @@ scoped_ptr<base::Value> TileManagerBinPriorityAsValue( ...@@ -62,8 +62,6 @@ scoped_ptr<base::Value> TileManagerBinPriorityAsValue(
// created, and unregister from the manager when they are deleted. // created, and unregister from the manager when they are deleted.
class CC_EXPORT TileManager : public WorkerPoolClient { class CC_EXPORT TileManager : public WorkerPoolClient {
public: public:
typedef base::hash_set<uint32_t> PixelRefSet;
static scoped_ptr<TileManager> Create( static scoped_ptr<TileManager> Create(
TileManagerClient* client, TileManagerClient* client,
ResourceProvider* resource_provider, ResourceProvider* resource_provider,
...@@ -118,7 +116,7 @@ class CC_EXPORT TileManager : public WorkerPoolClient { ...@@ -118,7 +116,7 @@ class CC_EXPORT TileManager : public WorkerPoolClient {
void UnregisterTile(Tile* tile); void UnregisterTile(Tile* tile);
// Virtual for test // Virtual for test
virtual void ScheduleTasks(); virtual void DispatchMoreTasks();
private: private:
// Data that is passed to raster tasks. // Data that is passed to raster tasks.
...@@ -131,6 +129,8 @@ class CC_EXPORT TileManager : public WorkerPoolClient { ...@@ -131,6 +129,8 @@ class CC_EXPORT TileManager : public WorkerPoolClient {
int source_frame_number; int source_frame_number;
}; };
RasterTaskMetadata GetRasterTaskMetadata(const Tile& tile) const;
void AssignBinsToTiles(); void AssignBinsToTiles();
void SortTiles(); void SortTiles();
void AssignGpuMemoryToTiles(); void AssignGpuMemoryToTiles();
...@@ -142,19 +142,20 @@ class CC_EXPORT TileManager : public WorkerPoolClient { ...@@ -142,19 +142,20 @@ class CC_EXPORT TileManager : public WorkerPoolClient {
client_->ScheduleManageTiles(); client_->ScheduleManageTiles();
manage_tiles_pending_ = true; manage_tiles_pending_ = true;
} }
RasterWorkerPool::Task CreateImageDecodeTask( bool DispatchImageDecodeTasksForTile(Tile* tile);
Tile* tile, skia::LazyPixelRef* pixel_ref); void DispatchOneImageDecodeTask(
scoped_refptr<Tile> tile, skia::LazyPixelRef* pixel_ref);
void OnImageDecodeTaskCompleted( void OnImageDecodeTaskCompleted(
scoped_refptr<Tile> tile, scoped_refptr<Tile> tile,
uint32_t pixel_ref_id, uint32_t pixel_ref_id);
bool was_canceled); bool CanDispatchRasterTask(Tile* tile) const;
RasterTaskMetadata GetRasterTaskMetadata(const Tile& tile) const; scoped_ptr<ResourcePool::Resource> PrepareTileForRaster(Tile* tile);
RasterWorkerPool::Task CreateRasterTask(Tile* tile); void DispatchOneRasterTask(scoped_refptr<Tile> tile);
void OnRasterTaskCompleted( void OnRasterTaskCompleted(
scoped_refptr<Tile> tile, scoped_refptr<Tile> tile,
scoped_ptr<ResourcePool::Resource> resource, scoped_ptr<ResourcePool::Resource> resource,
PicturePileImpl::Analysis* analysis, PicturePileImpl::Analysis* analysis,
bool was_canceled); int manage_tiles_call_count_when_dispatched);
void DidFinishTileInitialization(Tile* tile); void DidFinishTileInitialization(Tile* tile);
void DidTileTreeBinChange(Tile* tile, void DidTileTreeBinChange(Tile* tile,
TileManagerBin new_tree_bin, TileManagerBin new_tree_bin,
...@@ -162,13 +163,9 @@ class CC_EXPORT TileManager : public WorkerPoolClient { ...@@ -162,13 +163,9 @@ class CC_EXPORT TileManager : public WorkerPoolClient {
scoped_ptr<Value> GetMemoryRequirementsAsValue() const; scoped_ptr<Value> GetMemoryRequirementsAsValue() const;
void AddRequiredTileForActivation(Tile* tile); void AddRequiredTileForActivation(Tile* tile);
static void RunImageDecodeTask(
skia::LazyPixelRef* pixel_ref,
int layer_id,
RenderingStatsInstrumentation* stats_instrumentation);
static void RunAnalyzeAndRasterTask( static void RunAnalyzeAndRasterTask(
const RasterWorkerPool::PictureTask::Callback& analyze_task, const RasterWorkerPool::RasterCallback& analyze_task,
const RasterWorkerPool::PictureTask::Callback& raster_task, const RasterWorkerPool::RasterCallback& raster_task,
PicturePileImpl* picture_pile); PicturePileImpl* picture_pile);
static void RunAnalyzeTask( static void RunAnalyzeTask(
PicturePileImpl::Analysis* analysis, PicturePileImpl::Analysis* analysis,
...@@ -186,11 +183,16 @@ class CC_EXPORT TileManager : public WorkerPoolClient { ...@@ -186,11 +183,16 @@ class CC_EXPORT TileManager : public WorkerPoolClient {
const RasterTaskMetadata& metadata, const RasterTaskMetadata& metadata,
RenderingStatsInstrumentation* stats_instrumentation, RenderingStatsInstrumentation* stats_instrumentation,
PicturePileImpl* picture_pile); PicturePileImpl* picture_pile);
static void RunImageDecodeTask(
skia::LazyPixelRef* pixel_ref,
int layer_id,
RenderingStatsInstrumentation* stats_instrumentation);
TileManagerClient* client_; TileManagerClient* client_;
scoped_ptr<ResourcePool> resource_pool_; scoped_ptr<ResourcePool> resource_pool_;
scoped_ptr<RasterWorkerPool> raster_worker_pool_; scoped_ptr<RasterWorkerPool> raster_worker_pool_;
bool manage_tiles_pending_; bool manage_tiles_pending_;
int manage_tiles_call_count_;
GlobalStateThatImpactsTilePriority global_state_; GlobalStateThatImpactsTilePriority global_state_;
...@@ -200,8 +202,8 @@ class CC_EXPORT TileManager : public WorkerPoolClient { ...@@ -200,8 +202,8 @@ class CC_EXPORT TileManager : public WorkerPoolClient {
typedef std::set<Tile*> TileSet; typedef std::set<Tile*> TileSet;
TileSet tiles_that_need_to_be_initialized_for_activation_; TileSet tiles_that_need_to_be_initialized_for_activation_;
typedef base::hash_map<uint32_t, RasterWorkerPool::Task> PixelRefMap; typedef base::hash_set<uint32_t> PixelRefSet;
PixelRefMap pending_decode_tasks_; PixelRefSet pending_decode_tasks_;
typedef std::queue<scoped_refptr<Tile> > TileQueue; typedef std::queue<scoped_refptr<Tile> > TileQueue;
TileQueue tiles_with_pending_upload_; TileQueue tiles_with_pending_upload_;
...@@ -215,6 +217,7 @@ class CC_EXPORT TileManager : public WorkerPoolClient { ...@@ -215,6 +217,7 @@ class CC_EXPORT TileManager : public WorkerPoolClient {
bool use_color_estimator_; bool use_color_estimator_;
bool did_initialize_visible_tile_; bool did_initialize_visible_tile_;
size_t pending_tasks_;
size_t max_pending_tasks_; size_t max_pending_tasks_;
DISALLOW_COPY_AND_ASSIGN(TileManager); DISALLOW_COPY_AND_ASSIGN(TileManager);
......
...@@ -17,7 +17,7 @@ class FakeTileManager : public TileManager { ...@@ -17,7 +17,7 @@ class FakeTileManager : public TileManager {
protected: protected:
// Do nothing // Do nothing
virtual void ScheduleTasks() OVERRIDE { } virtual void DispatchMoreTasks() OVERRIDE { }
}; };
} // namespace cc } // namespace cc
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment