Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4398)

Unified Diff: cc/worker_pool.cc

Issue 12472028: Part 1 of cc/ directory shuffles: base (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« cc/cc.gyp ('K') | « cc/worker_pool.h ('k') | cc/yuv_video_draw_quad.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/worker_pool.cc
diff --git a/cc/worker_pool.cc b/cc/worker_pool.cc
deleted file mode 100644
index e2c2af4c29dd33b28c4e179d89479bcb19b2f204..0000000000000000000000000000000000000000
--- a/cc/worker_pool.cc
+++ /dev/null
@@ -1,609 +0,0 @@
-// 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/worker_pool.h"
-
-#include "base/bind.h"
-#include "base/debug/trace_event.h"
-#include "base/stringprintf.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/threading/simple_thread.h"
-#include "cc/rendering_stats.h"
-
-#if defined(OS_ANDROID)
-// TODO(epenner): Move thread priorities to base. (crbug.com/170549)
-#include <sys/resource.h>
-#endif
-
-namespace cc {
-
-namespace {
-
-class WorkerPoolTaskImpl : public internal::WorkerPoolTask {
- public:
- WorkerPoolTaskImpl(const WorkerPool::Callback& task,
- const base::Closure& reply)
- : internal::WorkerPoolTask(reply),
- task_(task) {}
-
- virtual bool IsCheap() OVERRIDE { return false; }
-
- virtual void Run(RenderingStats* rendering_stats) OVERRIDE {
- task_.Run(rendering_stats);
- }
-
- virtual void RunOnThread(
- RenderingStats* rendering_stats, unsigned thread_index) OVERRIDE {
- task_.Run(rendering_stats);
- }
-
- private:
- WorkerPool::Callback task_;
-};
-
-} // namespace
-
-namespace internal {
-
-WorkerPoolTask::WorkerPoolTask(const base::Closure& reply) : reply_(reply) {
-}
-
-WorkerPoolTask::~WorkerPoolTask() {
-}
-
-void WorkerPoolTask::DidComplete() {
- reply_.Run();
-}
-
-} // namespace internal
-
-// Internal to the worker pool. Any data or logic that needs to be
-// shared between threads lives in this class. All members are guarded
-// by |lock_|.
-class WorkerPool::Inner : public base::DelegateSimpleThread::Delegate {
- public:
- Inner(WorkerPool* worker_pool,
- size_t num_threads,
- const std::string& thread_name_prefix,
- bool need_on_task_completed_callback);
- ~Inner();
-
- void Shutdown();
-
- void SetRecordRenderingStats(bool record_rendering_stats);
-
- void GetRenderingStats(RenderingStats* stats);
-
- void PostTask(scoped_ptr<internal::WorkerPoolTask> task);
-
- // Appends all completed tasks to worker pool's completed tasks queue
- // and returns true if idle.
- bool CollectCompletedTasks();
-
- // Runs cheap tasks on caller thread until |time_limit| is reached
- // and returns true if idle.
- bool RunCheapTasksUntilTimeLimit(base::TimeTicks time_limit);
-
- private:
- // Appends all completed tasks to |completed_tasks|. Lock must
- // already be acquired before calling this function.
- bool AppendCompletedTasksWithLockAcquired(
- ScopedPtrDeque<internal::WorkerPoolTask>* completed_tasks);
-
- // Schedule a OnTaskCompletedOnOriginThread callback if not already
- // pending. Lock must already be acquired before calling this function.
- void ScheduleOnTaskCompletedWithLockAcquired();
- void OnTaskCompletedOnOriginThread();
-
- // Schedule an OnIdleOnOriginThread callback if not already pending.
- // Lock must already be acquired before calling this function.
- void ScheduleOnIdleWithLockAcquired();
- void OnIdleOnOriginThread();
-
- // Overridden from base::DelegateSimpleThread:
- virtual void Run() OVERRIDE;
-
- // Pointer to worker pool. Can only be used on origin thread.
- // Not guarded by |lock_|.
- WorkerPool* worker_pool_on_origin_thread_;
-
- // This lock protects all members of this class except
- // |worker_pool_on_origin_thread_|. 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 posted or shutdown starts.
- base::ConditionVariable has_pending_tasks_cv_;
-
- // Target message loop used for posting callbacks.
- scoped_refptr<base::MessageLoopProxy> origin_loop_;
-
- base::WeakPtrFactory<Inner> weak_ptr_factory_;
-
- // Set to true when worker pool requires a callback for each
- // completed task.
- bool need_on_task_completed_callback_;
-
- const base::Closure on_task_completed_callback_;
- // Set when a OnTaskCompletedOnOriginThread() callback is pending.
- bool on_task_completed_pending_;
-
- const base::Closure on_idle_callback_;
- // Set when a OnIdleOnOriginThread() callback is pending.
- bool on_idle_pending_;
-
- // Provides each running thread loop with a unique index. First thread
- // loop index is 0.
- unsigned next_thread_index_;
-
- // Number of tasks currently running.
- unsigned running_task_count_;
-
- // Set during shutdown. Tells workers to exit when no more tasks
- // are pending.
- bool shutdown_;
-
- typedef ScopedPtrDeque<internal::WorkerPoolTask> TaskDeque;
- TaskDeque pending_tasks_;
- TaskDeque completed_tasks_;
-
- scoped_ptr<RenderingStats> rendering_stats_;
-
- ScopedPtrDeque<base::DelegateSimpleThread> workers_;
-
- DISALLOW_COPY_AND_ASSIGN(Inner);
-};
-
-WorkerPool::Inner::Inner(WorkerPool* worker_pool,
- size_t num_threads,
- const std::string& thread_name_prefix,
- bool need_on_task_completed_callback)
- : worker_pool_on_origin_thread_(worker_pool),
- lock_(),
- has_pending_tasks_cv_(&lock_),
- origin_loop_(base::MessageLoopProxy::current()),
- weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
- need_on_task_completed_callback_(need_on_task_completed_callback),
- on_task_completed_callback_(
- base::Bind(&WorkerPool::Inner::OnTaskCompletedOnOriginThread,
- weak_ptr_factory_.GetWeakPtr())),
- on_task_completed_pending_(false),
- on_idle_callback_(base::Bind(&WorkerPool::Inner::OnIdleOnOriginThread,
- weak_ptr_factory_.GetWeakPtr())),
- on_idle_pending_(false),
- next_thread_index_(0),
- running_task_count_(0),
- shutdown_(false) {
- base::AutoLock lock(lock_);
-
- while (workers_.size() < num_threads) {
- scoped_ptr<base::DelegateSimpleThread> worker = make_scoped_ptr(
- new base::DelegateSimpleThread(
- this,
- thread_name_prefix +
- StringPrintf("Worker%lu", workers_.size() + 1).c_str()));
- worker->Start();
- workers_.push_back(worker.Pass());
- }
-}
-
-WorkerPool::Inner::~Inner() {
- base::AutoLock lock(lock_);
-
- DCHECK(shutdown_);
-
- // Cancel all pending callbacks.
- weak_ptr_factory_.InvalidateWeakPtrs();
-
- DCHECK_EQ(pending_tasks_.size(), 0);
- DCHECK_EQ(completed_tasks_.size(), 0);
- DCHECK_EQ(running_task_count_, 0);
-}
-
-void WorkerPool::Inner::Shutdown() {
- {
- base::AutoLock lock(lock_);
-
- DCHECK(!shutdown_);
- shutdown_ = true;
-
- // Wake up a worker so it knows it should exit. This will cause all workers
- // to exit as each will wake up another worker before exiting.
- has_pending_tasks_cv_.Signal();
- }
-
- while (workers_.size()) {
- scoped_ptr<base::DelegateSimpleThread> worker = workers_.take_front();
- worker->Join();
- }
-}
-
-void WorkerPool::Inner::SetRecordRenderingStats(bool record_rendering_stats) {
- base::AutoLock lock(lock_);
-
- if (record_rendering_stats)
- rendering_stats_.reset(new RenderingStats);
- else
- rendering_stats_.reset();
-}
-
-void WorkerPool::Inner::GetRenderingStats(RenderingStats* stats) {
- base::AutoLock lock(lock_);
-
- if (rendering_stats_)
- stats->Add(*rendering_stats_);
-}
-
-void WorkerPool::Inner::PostTask(scoped_ptr<internal::WorkerPoolTask> task) {
- base::AutoLock lock(lock_);
-
- pending_tasks_.push_back(task.Pass());
-
- // There is more work available, so wake up worker thread.
- has_pending_tasks_cv_.Signal();
-}
-
-bool WorkerPool::Inner::CollectCompletedTasks() {
- base::AutoLock lock(lock_);
-
- return AppendCompletedTasksWithLockAcquired(
- &worker_pool_on_origin_thread_->completed_tasks_);
-}
-
-bool WorkerPool::Inner::RunCheapTasksUntilTimeLimit(
- base::TimeTicks time_limit) {
- base::AutoLock lock(lock_);
-
- while (base::TimeTicks::Now() < time_limit) {
- scoped_ptr<internal::WorkerPoolTask> task;
-
- // Find next cheap task.
- for (TaskDeque::iterator iter = pending_tasks_.begin();
- iter != pending_tasks_.end(); ++iter) {
- if ((*iter)->IsCheap()) {
- task = pending_tasks_.take(iter);
- break;
- }
- }
-
- if (!task) {
- // Schedule an idle callback if requested and not pending.
- if (!running_task_count_ && pending_tasks_.empty())
- ScheduleOnIdleWithLockAcquired();
-
- // Exit when no more cheap tasks are pending.
- break;
- }
-
- scoped_ptr<RenderingStats> rendering_stats;
- // Collect rendering stats if |rendering_stats_| is set.
- if (rendering_stats_)
- rendering_stats = make_scoped_ptr(new RenderingStats);
-
- // Increment |running_task_count_| before starting to run task.
- running_task_count_++;
-
- {
- base::AutoUnlock unlock(lock_);
-
- task->Run(rendering_stats.get());
-
- // Append tasks directly to worker pool's completed tasks queue.
- worker_pool_on_origin_thread_->completed_tasks_.push_back(task.Pass());
- if (need_on_task_completed_callback_)
- worker_pool_on_origin_thread_->OnTaskCompleted();
- }
-
- // Add rendering stat results to |rendering_stats_|.
- if (rendering_stats && rendering_stats_)
- rendering_stats_->Add(*rendering_stats);
-
- // Decrement |running_task_count_| now that we are done running task.
- running_task_count_--;
- }
-
- // Append any other completed tasks before releasing lock.
- return AppendCompletedTasksWithLockAcquired(
- &worker_pool_on_origin_thread_->completed_tasks_);
-}
-
-bool WorkerPool::Inner::AppendCompletedTasksWithLockAcquired(
- ScopedPtrDeque<internal::WorkerPoolTask>* completed_tasks) {
- lock_.AssertAcquired();
-
- while (completed_tasks_.size())
- completed_tasks->push_back(completed_tasks_.take_front().Pass());
-
- return !running_task_count_ && pending_tasks_.empty();
-}
-
-void WorkerPool::Inner::ScheduleOnTaskCompletedWithLockAcquired() {
- lock_.AssertAcquired();
-
- if (on_task_completed_pending_ || !need_on_task_completed_callback_)
- return;
- origin_loop_->PostTask(FROM_HERE, on_task_completed_callback_);
- on_task_completed_pending_ = true;
-}
-
-void WorkerPool::Inner::OnTaskCompletedOnOriginThread() {
- {
- base::AutoLock lock(lock_);
-
- DCHECK(on_task_completed_pending_);
- on_task_completed_pending_ = false;
-
- AppendCompletedTasksWithLockAcquired(
- &worker_pool_on_origin_thread_->completed_tasks_);
- }
-
- worker_pool_on_origin_thread_->OnTaskCompleted();
-}
-
-void WorkerPool::Inner::ScheduleOnIdleWithLockAcquired() {
- lock_.AssertAcquired();
-
- if (on_idle_pending_)
- return;
- origin_loop_->PostTask(FROM_HERE, on_idle_callback_);
- on_idle_pending_ = true;
-}
-
-void WorkerPool::Inner::OnIdleOnOriginThread() {
- {
- base::AutoLock lock(lock_);
-
- DCHECK(on_idle_pending_);
- on_idle_pending_ = false;
-
- // Early out if no longer idle.
- if (running_task_count_ || !pending_tasks_.empty())
- return;
-
- AppendCompletedTasksWithLockAcquired(
- &worker_pool_on_origin_thread_->completed_tasks_);
- }
-
- worker_pool_on_origin_thread_->OnIdle();
-}
-
-void WorkerPool::Inner::Run() {
-#if defined(OS_ANDROID)
- // TODO(epenner): Move thread priorities to base. (crbug.com/170549)
- int nice_value = 10; // Idle priority.
- setpriority(PRIO_PROCESS, base::PlatformThread::CurrentId(), nice_value);
-#endif
-
- {
- base::AutoLock lock(lock_);
-
- // Get a unique thread index.
- int thread_index = next_thread_index_++;
-
- while (true) {
- if (pending_tasks_.empty()) {
- // Exit when shutdown is set and no more tasks are pending.
- if (shutdown_)
- break;
-
- // Schedule an idle callback if requested and not pending.
- if (!running_task_count_)
- ScheduleOnIdleWithLockAcquired();
-
- // Wait for new pending tasks.
- has_pending_tasks_cv_.Wait();
- continue;
- }
-
- // Get next task.
- scoped_ptr<internal::WorkerPoolTask> task = pending_tasks_.take_front();
-
- scoped_ptr<RenderingStats> rendering_stats;
- // Collect rendering stats if |rendering_stats_| is set.
- if (rendering_stats_)
- rendering_stats = make_scoped_ptr(new RenderingStats);
-
- // Increment |running_task_count_| before starting to run task.
- running_task_count_++;
-
- // There may be more work available, so wake up another
- // worker thread.
- has_pending_tasks_cv_.Signal();
-
- {
- base::AutoUnlock unlock(lock_);
-
- task->RunOnThread(rendering_stats.get(), thread_index);
- }
-
- completed_tasks_.push_back(task.Pass());
-
- // Add rendering stat results to |rendering_stats_|.
- if (rendering_stats && rendering_stats_)
- rendering_stats_->Add(*rendering_stats);
-
- // Decrement |running_task_count_| now that we are done running task.
- running_task_count_--;
-
- // Schedule a task completed callback if requested and not pending.
- ScheduleOnTaskCompletedWithLockAcquired();
- }
-
- // We noticed we should exit. Wake up the next worker so it knows it should
- // exit as well (because the Shutdown() code only signals once).
- has_pending_tasks_cv_.Signal();
- }
-}
-
-WorkerPool::WorkerPool(WorkerPoolClient* client,
- size_t num_threads,
- base::TimeDelta check_for_completed_tasks_delay,
- const std::string& thread_name_prefix)
- : client_(client),
- origin_loop_(base::MessageLoopProxy::current()),
- weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
- check_for_completed_tasks_delay_(check_for_completed_tasks_delay),
- check_for_completed_tasks_pending_(false),
- run_cheap_tasks_callback_(
- base::Bind(&WorkerPool::RunCheapTasks,
- weak_ptr_factory_.GetWeakPtr())),
- run_cheap_tasks_pending_(false),
- inner_(make_scoped_ptr(
- new Inner(
- this,
- num_threads,
- thread_name_prefix,
- // Request OnTaskCompleted() callback when check
- // for completed tasks delay is 0.
- check_for_completed_tasks_delay == base::TimeDelta()))) {
-}
-
-WorkerPool::~WorkerPool() {
- Shutdown();
-
- // Cancel all pending callbacks.
- weak_ptr_factory_.InvalidateWeakPtrs();
-
- DCHECK_EQ(completed_tasks_.size(), 0);
-}
-
-void WorkerPool::Shutdown() {
- inner_->Shutdown();
- DispatchCompletionCallbacks();
-}
-
-void WorkerPool::PostTaskAndReply(
- const Callback& task, const base::Closure& reply) {
- PostTask(make_scoped_ptr(new WorkerPoolTaskImpl(
- task,
- reply)).PassAs<internal::WorkerPoolTask>());
-}
-
-void WorkerPool::SetRunCheapTasksTimeLimit(
- base::TimeTicks run_cheap_tasks_time_limit) {
- run_cheap_tasks_time_limit_ = run_cheap_tasks_time_limit;
- ScheduleRunCheapTasks();
-}
-
-void WorkerPool::SetRecordRenderingStats(bool record_rendering_stats) {
- inner_->SetRecordRenderingStats(record_rendering_stats);
-}
-
-void WorkerPool::GetRenderingStats(RenderingStats* stats) {
- inner_->GetRenderingStats(stats);
-}
-
-void WorkerPool::OnIdle() {
- TRACE_EVENT0("cc", "WorkerPool::OnIdle");
-
- DispatchCompletionCallbacks();
-}
-
-void WorkerPool::OnTaskCompleted() {
- TRACE_EVENT0("cc", "WorkerPool::OnTaskCompleted");
-
- DispatchCompletionCallbacks();
-}
-
-void WorkerPool::ScheduleCheckForCompletedTasks() {
- if (check_for_completed_tasks_pending_ ||
- check_for_completed_tasks_delay_ == base::TimeDelta())
- return;
- check_for_completed_tasks_callback_.Reset(
- base::Bind(&WorkerPool::CheckForCompletedTasks,
- weak_ptr_factory_.GetWeakPtr()));
- check_for_completed_tasks_time_ = base::TimeTicks::Now() +
- check_for_completed_tasks_delay_;
- origin_loop_->PostDelayedTask(
- FROM_HERE,
- check_for_completed_tasks_callback_.callback(),
- check_for_completed_tasks_delay_);
- check_for_completed_tasks_pending_ = true;
-}
-
-void WorkerPool::CheckForCompletedTasks() {
- TRACE_EVENT0("cc", "WorkerPool::CheckForCompletedTasks");
- DCHECK(check_for_completed_tasks_pending_);
- check_for_completed_tasks_pending_ = false;
-
- // Schedule another check for completed tasks if not idle.
- if (!inner_->CollectCompletedTasks())
- ScheduleCheckForCompletedTasks();
-
- DispatchCompletionCallbacks();
-}
-
-void WorkerPool::CancelCheckForCompletedTasks() {
- if (!check_for_completed_tasks_pending_)
- return;
-
- check_for_completed_tasks_callback_.Cancel();
- check_for_completed_tasks_pending_ = false;
-}
-
-void WorkerPool::DispatchCompletionCallbacks() {
- TRACE_EVENT0("cc", "WorkerPool::DispatchCompletionCallbacks");
-
- if (completed_tasks_.empty())
- return;
-
- while (completed_tasks_.size()) {
- scoped_ptr<internal::WorkerPoolTask> task = completed_tasks_.take_front();
- task->DidComplete();
- }
-
- client_->DidFinishDispatchingWorkerPoolCompletionCallbacks();
-}
-
-void WorkerPool::PostTask(scoped_ptr<internal::WorkerPoolTask> task) {
- if (task->IsCheap())
- ScheduleRunCheapTasks();
-
- // Schedule check for completed tasks if not pending.
- ScheduleCheckForCompletedTasks();
-
- inner_->PostTask(task.Pass());
-}
-
-void WorkerPool::ScheduleRunCheapTasks() {
- if (run_cheap_tasks_pending_)
- return;
- origin_loop_->PostTask(FROM_HERE, run_cheap_tasks_callback_);
- run_cheap_tasks_pending_ = true;
-}
-
-void WorkerPool::RunCheapTasks() {
- TRACE_EVENT0("cc", "WorkerPool::RunCheapTasks");
- DCHECK(run_cheap_tasks_pending_);
- run_cheap_tasks_pending_ = false;
-
- while (true) {
- base::TimeTicks time_limit = run_cheap_tasks_time_limit_;
-
- if (!check_for_completed_tasks_time_.is_null())
- time_limit = std::min(time_limit, check_for_completed_tasks_time_);
-
- bool is_idle = inner_->RunCheapTasksUntilTimeLimit(time_limit);
-
- if (base::TimeTicks::Now() >= run_cheap_tasks_time_limit_) {
- TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks out of time");
- break;
- }
-
- // We must be out of cheap tasks if this happens.
- if (check_for_completed_tasks_time_.is_null() ||
- base::TimeTicks::Now() < run_cheap_tasks_time_limit_)
- break;
-
- TRACE_EVENT_INSTANT0("cc", "WorkerPool::RunCheapTasks check time");
- CancelCheckForCompletedTasks();
- DispatchCompletionCallbacks();
- // Schedule another check for completed tasks if not idle.
- if (!is_idle)
- ScheduleCheckForCompletedTasks();
- }
-}
-
-} // namespace cc
« cc/cc.gyp ('K') | « cc/worker_pool.h ('k') | cc/yuv_video_draw_quad.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698