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 typedef std::pair
<base::SingleThreadTaskRunner
*,
16 scoped_refptr
<BlockingTaskRunner
> > TaskRunnerPair
;
18 struct TaskRunnerPairs
{
19 static TaskRunnerPairs
* GetInstance() {
20 return Singleton
<TaskRunnerPairs
>::get();
24 std::vector
<TaskRunnerPair
> pairs
;
27 friend struct DefaultSingletonTraits
<TaskRunnerPairs
>;
31 scoped_refptr
<BlockingTaskRunner
> BlockingTaskRunner::current() {
32 TaskRunnerPairs
* task_runners
= TaskRunnerPairs::GetInstance();
34 base::AutoLock
lock(task_runners
->lock
);
36 for (size_t i
= 0; i
< task_runners
->pairs
.size(); ++i
) {
37 if (task_runners
->pairs
[i
].first
->HasOneRef()) {
38 // The SingleThreadTaskRunner is kept alive by its MessageLoop, and we
39 // hold a second reference in the TaskRunnerPairs array. If the
40 // SingleThreadTaskRunner has one ref, then it is being held alive only
41 // by the BlockingTaskRunner and the MessageLoop is gone, so drop the
42 // BlockingTaskRunner from the TaskRunnerPairs array along with the
43 // SingleThreadTaskRunner.
44 task_runners
->pairs
.erase(task_runners
->pairs
.begin() + i
);
49 scoped_refptr
<base::SingleThreadTaskRunner
> current
=
50 base::MessageLoopProxy::current();
51 for (size_t i
= 0; i
< task_runners
->pairs
.size(); ++i
) {
52 if (task_runners
->pairs
[i
].first
== current
.get())
53 return task_runners
->pairs
[i
].second
.get();
56 scoped_refptr
<BlockingTaskRunner
> runner
= new BlockingTaskRunner(current
);
57 task_runners
->pairs
.push_back(TaskRunnerPair(current
, runner
));
61 BlockingTaskRunner::BlockingTaskRunner(
62 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
)
63 : task_runner_(task_runner
), capture_(0) {}
65 BlockingTaskRunner::~BlockingTaskRunner() {}
67 bool BlockingTaskRunner::PostTask(const tracked_objects::Location
& from_here
,
68 const base::Closure
& task
) {
69 base::AutoLock
lock(lock_
);
71 return task_runner_
->PostTask(from_here
, task
);
72 captured_tasks_
.push_back(task
);
76 void BlockingTaskRunner::SetCapture(bool capture
) {
77 DCHECK(BelongsToCurrentThread());
79 std::vector
<base::Closure
> tasks
;
82 base::AutoLock
lock(lock_
);
83 capture_
+= capture
? 1 : -1;
84 DCHECK_GE(capture_
, 0);
89 // We're done capturing, so grab all the captured tasks and run them.
90 tasks
.swap(captured_tasks_
);
92 for (size_t i
= 0; i
< tasks
.size(); ++i
)
96 BlockingTaskRunner::CapturePostTasks::CapturePostTasks()
97 : blocking_runner_(BlockingTaskRunner::current()) {
98 blocking_runner_
->SetCapture(true);
101 BlockingTaskRunner::CapturePostTasks::~CapturePostTasks() {
102 blocking_runner_
->SetCapture(false);