This source file includes following definitions.
- current
- capture_
- PostTask
- SetCapture
#include "cc/trees/blocking_task_runner.h"
#include <utility>
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/message_loop/message_loop_proxy.h"
namespace cc {
typedef std::pair<base::SingleThreadTaskRunner*,
scoped_refptr<BlockingTaskRunner> > TaskRunnerPair;
struct TaskRunnerPairs {
static TaskRunnerPairs* GetInstance() {
return Singleton<TaskRunnerPairs>::get();
}
base::Lock lock;
std::vector<TaskRunnerPair> pairs;
private:
friend struct DefaultSingletonTraits<TaskRunnerPairs>;
};
scoped_refptr<BlockingTaskRunner> BlockingTaskRunner::current() {
TaskRunnerPairs* task_runners = TaskRunnerPairs::GetInstance();
base::AutoLock lock(task_runners->lock);
for (size_t i = 0; i < task_runners->pairs.size(); ++i) {
if (task_runners->pairs[i].first->HasOneRef()) {
task_runners->pairs.erase(task_runners->pairs.begin() + i);
--i;
}
}
scoped_refptr<base::SingleThreadTaskRunner> current =
base::MessageLoopProxy::current();
for (size_t i = 0; i < task_runners->pairs.size(); ++i) {
if (task_runners->pairs[i].first == current.get())
return task_runners->pairs[i].second.get();
}
scoped_refptr<BlockingTaskRunner> runner = new BlockingTaskRunner(current);
task_runners->pairs.push_back(TaskRunnerPair(current, runner));
return runner;
}
BlockingTaskRunner::BlockingTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: task_runner_(task_runner), capture_(0) {}
BlockingTaskRunner::~BlockingTaskRunner() {}
bool BlockingTaskRunner::PostTask(const tracked_objects::Location& from_here,
const base::Closure& task) {
base::AutoLock lock(lock_);
if (!capture_)
return task_runner_->PostTask(from_here, task);
captured_tasks_.push_back(task);
return true;
}
void BlockingTaskRunner::SetCapture(bool capture) {
DCHECK(BelongsToCurrentThread());
std::vector<base::Closure> tasks;
{
base::AutoLock lock(lock_);
capture_ += capture ? 1 : -1;
DCHECK_GE(capture_, 0);
if (capture_)
return;
tasks.swap(captured_tasks_);
}
for (size_t i = 0; i < tasks.size(); ++i)
tasks[i].Run();
}
BlockingTaskRunner::CapturePostTasks::CapturePostTasks()
: blocking_runner_(BlockingTaskRunner::current()) {
blocking_runner_->SetCapture(true);
}
BlockingTaskRunner::CapturePostTasks::~CapturePostTasks() {
blocking_runner_->SetCapture(false);
}
}