This source file includes following definitions.
- GetPictureCloneIndexForCurrentThread
- Run
- on_raster_finished_callback_
- RunOnWorkerThread
- ScheduleOnOriginThread
- RunOnOriginThread
- CompleteOnOriginThread
- RunReplyOnOriginThread
- RasterFinished
- OnRasterFinishedOnOriginThread
- tasks_required_for_activation_count_
- RunOnWorkerThread
- RunOnOriginThread
- RunRasterFinished
- did_complete_
- WillSchedule
- DidSchedule
- HasBeenScheduled
- WillComplete
- DidComplete
- HasCompleted
- required_for_activation
- Swap
- Reset
- weak_ptr_factory_
- SetNumRasterThreads
- GetNumRasterThreads
- GetTaskGraphRunner
- GetPictureCloneIndexForCurrentThread
- SetClient
- Shutdown
- SetTaskGraph
- CollectCompletedWorkerPoolTasks
- CreateRasterFinishedTask
- CreateRasterRequiredForActivationFinishedTask
- RunTaskOnOriginThread
- OnRasterFinished
- OnRasterRequiredForActivationFinished
- InsertNodeForTask
- InsertNodeForRasterTask
#include "cc/resources/raster_worker_pool.h"
#include <algorithm>
#include "base/atomic_sequence_num.h"
#include "base/debug/trace_event_synthetic_delay.h"
#include "base/lazy_instance.h"
#include "base/strings/stringprintf.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread_local.h"
#include "cc/base/scoped_ptr_deque.h"
namespace cc {
namespace {
struct RasterRequiredForActivationSyntheticDelayInitializer {
RasterRequiredForActivationSyntheticDelayInitializer()
: delay(base::debug::TraceEventSyntheticDelay::Lookup(
"cc.RasterRequiredForActivation")) {}
base::debug::TraceEventSyntheticDelay* delay;
};
static base::LazyInstance<RasterRequiredForActivationSyntheticDelayInitializer>
g_raster_required_for_activation_delay = LAZY_INSTANCE_INITIALIZER;
class RasterTaskGraphRunner : public internal::TaskGraphRunner,
public base::DelegateSimpleThread::Delegate {
public:
RasterTaskGraphRunner() {
size_t num_threads = RasterWorkerPool::GetNumRasterThreads();
while (workers_.size() < num_threads) {
scoped_ptr<base::DelegateSimpleThread> worker =
make_scoped_ptr(new base::DelegateSimpleThread(
this,
base::StringPrintf("CompositorRasterWorker%u",
static_cast<unsigned>(workers_.size() + 1))
.c_str()));
worker->Start();
#if defined(OS_ANDROID) || defined(OS_LINUX)
worker->SetThreadPriority(base::kThreadPriority_Background);
#endif
workers_.push_back(worker.Pass());
}
}
virtual ~RasterTaskGraphRunner() { NOTREACHED(); }
size_t GetPictureCloneIndexForCurrentThread() {
return current_tls_.Get()->picture_clone_index;
}
private:
struct ThreadLocalState {
explicit ThreadLocalState(size_t picture_clone_index)
: picture_clone_index(picture_clone_index) {}
size_t picture_clone_index;
};
virtual void Run() OVERRIDE {
int picture_clone_index = picture_clone_index_sequence_.GetNext();
DCHECK_LE(0, picture_clone_index);
DCHECK_GT(RasterWorkerPool::GetNumRasterThreads(), picture_clone_index);
current_tls_.Set(new ThreadLocalState(picture_clone_index));
internal::TaskGraphRunner::Run();
}
ScopedPtrDeque<base::DelegateSimpleThread> workers_;
base::AtomicSequenceNumber picture_clone_index_sequence_;
base::ThreadLocalPointer<ThreadLocalState> current_tls_;
};
base::LazyInstance<RasterTaskGraphRunner>::Leaky g_task_graph_runner =
LAZY_INSTANCE_INITIALIZER;
const int kDefaultNumRasterThreads = 1;
int g_num_raster_threads = 0;
class RasterFinishedWorkerPoolTaskImpl : public internal::WorkerPoolTask {
public:
typedef base::Callback<void(const internal::WorkerPoolTask* source)> Callback;
explicit RasterFinishedWorkerPoolTaskImpl(
base::SequencedTaskRunner* task_runner,
const Callback& on_raster_finished_callback)
: task_runner_(task_runner),
on_raster_finished_callback_(on_raster_finished_callback) {}
virtual void RunOnWorkerThread() OVERRIDE {
TRACE_EVENT0("cc", "RasterFinishedWorkerPoolTaskImpl::RunOnWorkerThread");
RasterFinished();
}
virtual void ScheduleOnOriginThread(internal::WorkerPoolTaskClient* client)
OVERRIDE {}
virtual void RunOnOriginThread() OVERRIDE {
TRACE_EVENT0("cc", "RasterFinishedWorkerPoolTaskImpl::RunOnOriginThread");
RasterFinished();
}
virtual void CompleteOnOriginThread(internal::WorkerPoolTaskClient* client)
OVERRIDE {}
virtual void RunReplyOnOriginThread() OVERRIDE {}
protected:
virtual ~RasterFinishedWorkerPoolTaskImpl() {}
void RasterFinished() {
task_runner_->PostTask(
FROM_HERE,
base::Bind(
&RasterFinishedWorkerPoolTaskImpl::OnRasterFinishedOnOriginThread,
this));
}
private:
void OnRasterFinishedOnOriginThread() const {
on_raster_finished_callback_.Run(this);
}
scoped_refptr<base::SequencedTaskRunner> task_runner_;
const Callback on_raster_finished_callback_;
DISALLOW_COPY_AND_ASSIGN(RasterFinishedWorkerPoolTaskImpl);
};
class RasterRequiredForActivationFinishedWorkerPoolTaskImpl
: public RasterFinishedWorkerPoolTaskImpl {
public:
RasterRequiredForActivationFinishedWorkerPoolTaskImpl(
base::SequencedTaskRunner* task_runner,
const Callback& on_raster_finished_callback,
size_t tasks_required_for_activation_count)
: RasterFinishedWorkerPoolTaskImpl(task_runner,
on_raster_finished_callback),
tasks_required_for_activation_count_(
tasks_required_for_activation_count) {
if (tasks_required_for_activation_count_) {
g_raster_required_for_activation_delay.Get().delay->BeginParallel(
&activation_delay_end_time_);
}
}
virtual void RunOnWorkerThread() OVERRIDE {
TRACE_EVENT0("cc",
"RasterRequiredForActivationFinishedWorkerPoolTaskImpl::"
"RunOnWorkerThread");
RunRasterFinished();
}
virtual void RunOnOriginThread() OVERRIDE {
TRACE_EVENT0("cc",
"RasterRequiredForActivationFinishedWorkerPoolTaskImpl::"
"RunOnOriginThread");
RunRasterFinished();
}
private:
virtual ~RasterRequiredForActivationFinishedWorkerPoolTaskImpl() {}
void RunRasterFinished() {
if (tasks_required_for_activation_count_) {
g_raster_required_for_activation_delay.Get().delay->EndParallel(
activation_delay_end_time_);
}
RasterFinished();
}
base::TimeTicks activation_delay_end_time_;
const size_t tasks_required_for_activation_count_;
DISALLOW_COPY_AND_ASSIGN(
RasterRequiredForActivationFinishedWorkerPoolTaskImpl);
};
}
namespace internal {
WorkerPoolTask::WorkerPoolTask() : did_schedule_(false), did_complete_(false) {}
WorkerPoolTask::~WorkerPoolTask() {
DCHECK(!did_schedule_);
DCHECK(!did_run_ || did_complete_);
}
void WorkerPoolTask::WillSchedule() { DCHECK(!did_schedule_); }
void WorkerPoolTask::DidSchedule() {
did_schedule_ = true;
did_complete_ = false;
}
bool WorkerPoolTask::HasBeenScheduled() const { return did_schedule_; }
void WorkerPoolTask::WillComplete() { DCHECK(!did_complete_); }
void WorkerPoolTask::DidComplete() {
DCHECK(did_schedule_);
DCHECK(!did_complete_);
did_schedule_ = false;
did_complete_ = true;
}
bool WorkerPoolTask::HasCompleted() const { return did_complete_; }
RasterWorkerPoolTask::RasterWorkerPoolTask(
const Resource* resource,
internal::WorkerPoolTask::Vector* dependencies)
: resource_(resource) {
dependencies_.swap(*dependencies);
}
RasterWorkerPoolTask::~RasterWorkerPoolTask() {}
}
RasterTaskQueue::Item::Item(internal::RasterWorkerPoolTask* task,
bool required_for_activation)
: task(task), required_for_activation(required_for_activation) {}
RasterTaskQueue::Item::~Item() {}
RasterTaskQueue::RasterTaskQueue() : required_for_activation_count(0u) {}
RasterTaskQueue::~RasterTaskQueue() {}
void RasterTaskQueue::Swap(RasterTaskQueue* other) {
items.swap(other->items);
std::swap(required_for_activation_count,
other->required_for_activation_count);
}
void RasterTaskQueue::Reset() {
required_for_activation_count = 0u;
items.clear();
}
unsigned RasterWorkerPool::kOnDemandRasterTaskPriority = 0u;
unsigned RasterWorkerPool::kBenchmarkRasterTaskPriority = 0u;
unsigned RasterWorkerPool::kRasterFinishedTaskPriority = 2u;
unsigned RasterWorkerPool::kRasterRequiredForActivationFinishedTaskPriority =
1u;
unsigned RasterWorkerPool::kRasterTaskPriorityBase = 3u;
RasterWorkerPool::RasterWorkerPool(base::SequencedTaskRunner* task_runner,
internal::TaskGraphRunner* task_graph_runner,
ResourceProvider* resource_provider)
: task_runner_(task_runner),
task_graph_runner_(task_graph_runner),
client_(NULL),
resource_provider_(resource_provider),
weak_ptr_factory_(this) {
if (task_graph_runner_)
namespace_token_ = task_graph_runner_->GetNamespaceToken();
}
RasterWorkerPool::~RasterWorkerPool() {}
void RasterWorkerPool::SetNumRasterThreads(int num_threads) {
DCHECK_LT(0, num_threads);
DCHECK_EQ(0, g_num_raster_threads);
g_num_raster_threads = num_threads;
}
int RasterWorkerPool::GetNumRasterThreads() {
if (!g_num_raster_threads)
g_num_raster_threads = kDefaultNumRasterThreads;
return g_num_raster_threads;
}
internal::TaskGraphRunner* RasterWorkerPool::GetTaskGraphRunner() {
return g_task_graph_runner.Pointer();
}
size_t RasterWorkerPool::GetPictureCloneIndexForCurrentThread() {
return g_task_graph_runner.Pointer()->GetPictureCloneIndexForCurrentThread();
}
void RasterWorkerPool::SetClient(RasterWorkerPoolClient* client) {
client_ = client;
}
void RasterWorkerPool::Shutdown() {
TRACE_EVENT0("cc", "RasterWorkerPool::Shutdown");
if (task_graph_runner_) {
internal::TaskGraph empty;
task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
}
weak_ptr_factory_.InvalidateWeakPtrs();
}
void RasterWorkerPool::SetTaskGraph(internal::TaskGraph* graph) {
TRACE_EVENT0("cc", "RasterWorkerPool::SetTaskGraph");
DCHECK(task_graph_runner_);
for (internal::TaskGraph::Node::Vector::iterator it = graph->nodes.begin();
it != graph->nodes.end();
++it) {
internal::TaskGraph::Node& node = *it;
internal::WorkerPoolTask* task =
static_cast<internal::WorkerPoolTask*>(node.task);
if (!task->HasBeenScheduled()) {
task->WillSchedule();
task->ScheduleOnOriginThread(this);
task->DidSchedule();
}
}
task_graph_runner_->ScheduleTasks(namespace_token_, graph);
}
void RasterWorkerPool::CollectCompletedWorkerPoolTasks(
internal::Task::Vector* completed_tasks) {
DCHECK(task_graph_runner_);
task_graph_runner_->CollectCompletedTasks(namespace_token_, completed_tasks);
}
scoped_refptr<internal::WorkerPoolTask>
RasterWorkerPool::CreateRasterFinishedTask() {
return make_scoped_refptr(new RasterFinishedWorkerPoolTaskImpl(
task_runner_,
base::Bind(&RasterWorkerPool::OnRasterFinished,
weak_ptr_factory_.GetWeakPtr())));
}
scoped_refptr<internal::WorkerPoolTask>
RasterWorkerPool::CreateRasterRequiredForActivationFinishedTask(
size_t tasks_required_for_activation_count) {
return make_scoped_refptr(
new RasterRequiredForActivationFinishedWorkerPoolTaskImpl(
task_runner_,
base::Bind(&RasterWorkerPool::OnRasterRequiredForActivationFinished,
weak_ptr_factory_.GetWeakPtr()),
tasks_required_for_activation_count));
}
void RasterWorkerPool::RunTaskOnOriginThread(internal::WorkerPoolTask* task) {
task->WillSchedule();
task->ScheduleOnOriginThread(this);
task->DidSchedule();
task->WillRun();
task->RunOnOriginThread();
task->DidRun();
task->WillComplete();
task->CompleteOnOriginThread(this);
task->DidComplete();
}
void RasterWorkerPool::OnRasterFinished(
const internal::WorkerPoolTask* source) {
TRACE_EVENT0("cc", "RasterWorkerPool::OnRasterFinished");
if (source != raster_finished_task_.get())
return;
OnRasterTasksFinished();
}
void RasterWorkerPool::OnRasterRequiredForActivationFinished(
const internal::WorkerPoolTask* source) {
TRACE_EVENT0("cc", "RasterWorkerPool::OnRasterRequiredForActivationFinished");
if (source != raster_required_for_activation_finished_task_.get())
return;
OnRasterTasksRequiredForActivationFinished();
}
void RasterWorkerPool::InsertNodeForTask(internal::TaskGraph* graph,
internal::WorkerPoolTask* task,
unsigned priority,
size_t dependencies) {
DCHECK(std::find_if(graph->nodes.begin(),
graph->nodes.end(),
internal::TaskGraph::Node::TaskComparator(task)) ==
graph->nodes.end());
graph->nodes.push_back(
internal::TaskGraph::Node(task, priority, dependencies));
}
void RasterWorkerPool::InsertNodeForRasterTask(
internal::TaskGraph* graph,
internal::WorkerPoolTask* raster_task,
const internal::WorkerPoolTask::Vector& decode_tasks,
unsigned priority) {
size_t dependencies = 0u;
for (internal::WorkerPoolTask::Vector::const_iterator it =
decode_tasks.begin();
it != decode_tasks.end();
++it) {
internal::WorkerPoolTask* decode_task = it->get();
if (decode_task->HasCompleted())
continue;
dependencies++;
internal::TaskGraph::Node::Vector::iterator decode_it =
std::find_if(graph->nodes.begin(),
graph->nodes.end(),
internal::TaskGraph::Node::TaskComparator(decode_task));
if (decode_it == graph->nodes.end())
InsertNodeForTask(graph, decode_task, priority, 0u);
graph->edges.push_back(internal::TaskGraph::Edge(decode_task, raster_task));
}
InsertNodeForTask(graph, raster_task, priority, dependencies);
}
}