1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/blocking_task_runner.h"
9 #include "base/logging.h"
10 #include "base/memory/singleton.h"
11 #include "base/message_loop/message_loop_proxy.h"
15 struct TaskRunnerPairs
{
16 static TaskRunnerPairs
* GetInstance() {
17 return Singleton
<TaskRunnerPairs
>::get();
21 std::vector
<scoped_refptr
<BlockingTaskRunner
> > runners
;
24 friend struct DefaultSingletonTraits
<TaskRunnerPairs
>;
28 scoped_refptr
<BlockingTaskRunner
> BlockingTaskRunner::current() {
29 TaskRunnerPairs
* task_runners
= TaskRunnerPairs::GetInstance();
30 base::PlatformThreadId thread_id
= base::PlatformThread::CurrentId();
32 base::AutoLock
lock(task_runners
->lock
);
34 scoped_refptr
<BlockingTaskRunner
> current_task_runner
;
36 for (size_t i
= 0; i
< task_runners
->runners
.size(); ++i
) {
37 if (task_runners
->runners
[i
]->thread_id_
== thread_id
) {
38 current_task_runner
= task_runners
->runners
[i
];
39 } else if (task_runners
->runners
[i
]->HasOneRef()) {
40 task_runners
->runners
.erase(task_runners
->runners
.begin() + i
);
45 if (current_task_runner
)
46 return current_task_runner
;
48 scoped_refptr
<BlockingTaskRunner
> runner
=
49 new BlockingTaskRunner(base::MessageLoopProxy::current());
50 task_runners
->runners
.push_back(runner
);
54 BlockingTaskRunner::BlockingTaskRunner(
55 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
)
56 : thread_id_(base::PlatformThread::CurrentId()),
57 task_runner_(task_runner
),
61 BlockingTaskRunner::~BlockingTaskRunner() {}
63 bool BlockingTaskRunner::BelongsToCurrentThread() {
64 return base::PlatformThread::CurrentId() == thread_id_
;
67 bool BlockingTaskRunner::PostTask(const tracked_objects::Location
& from_here
,
68 const base::Closure
& task
) {
69 base::AutoLock
lock(lock_
);
70 DCHECK(task_runner_
.get() || capture_
);
72 return task_runner_
->PostTask(from_here
, task
);
73 captured_tasks_
.push_back(task
);
77 void BlockingTaskRunner::SetCapture(bool capture
) {
78 DCHECK(BelongsToCurrentThread());
80 std::vector
<base::Closure
> tasks
;
83 base::AutoLock
lock(lock_
);
84 capture_
+= capture
? 1 : -1;
85 DCHECK_GE(capture_
, 0);
90 // We're done capturing, so grab all the captured tasks and run them.
91 tasks
.swap(captured_tasks_
);
93 for (size_t i
= 0; i
< tasks
.size(); ++i
)
97 BlockingTaskRunner::CapturePostTasks::CapturePostTasks()
98 : blocking_runner_(BlockingTaskRunner::current()) {
99 blocking_runner_
->SetCapture(true);
102 BlockingTaskRunner::CapturePostTasks::~CapturePostTasks() {
103 blocking_runner_
->SetCapture(false);