• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "cc/trees/blocking_task_runner.h"
6 
7 #include <utility>
8 
9 #include "base/callback.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 
13 namespace cc {
14 
15 // static
Create(scoped_refptr<base::SingleThreadTaskRunner> task_runner)16 scoped_ptr<BlockingTaskRunner> BlockingTaskRunner::Create(
17     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
18   return make_scoped_ptr(new BlockingTaskRunner(task_runner));
19 }
20 
BlockingTaskRunner(scoped_refptr<base::SingleThreadTaskRunner> task_runner)21 BlockingTaskRunner::BlockingTaskRunner(
22     scoped_refptr<base::SingleThreadTaskRunner> task_runner)
23     : thread_id_(base::PlatformThread::CurrentId()),
24       task_runner_(task_runner),
25       capture_(0) {
26 }
27 
~BlockingTaskRunner()28 BlockingTaskRunner::~BlockingTaskRunner() {}
29 
BelongsToCurrentThread()30 bool BlockingTaskRunner::BelongsToCurrentThread() {
31   return base::PlatformThread::CurrentId() == thread_id_;
32 }
33 
PostTask(const tracked_objects::Location & from_here,const base::Closure & task)34 bool BlockingTaskRunner::PostTask(const tracked_objects::Location& from_here,
35                                   const base::Closure& task) {
36   base::AutoLock lock(lock_);
37   DCHECK(task_runner_.get() || capture_);
38   if (!capture_)
39     return task_runner_->PostTask(from_here, task);
40   captured_tasks_.push_back(task);
41   return true;
42 }
43 
SetCapture(bool capture)44 void BlockingTaskRunner::SetCapture(bool capture) {
45   DCHECK(BelongsToCurrentThread());
46 
47   std::vector<base::Closure> tasks;
48 
49   {
50     base::AutoLock lock(lock_);
51     capture_ += capture ? 1 : -1;
52     DCHECK_GE(capture_, 0);
53 
54     if (capture_)
55       return;
56 
57     // We're done capturing, so grab all the captured tasks and run them.
58     tasks.swap(captured_tasks_);
59   }
60   for (size_t i = 0; i < tasks.size(); ++i)
61     tasks[i].Run();
62 }
63 
CapturePostTasks(BlockingTaskRunner * blocking_runner)64 BlockingTaskRunner::CapturePostTasks::CapturePostTasks(
65     BlockingTaskRunner* blocking_runner)
66     : blocking_runner_(blocking_runner) {
67   blocking_runner_->SetCapture(true);
68 }
69 
~CapturePostTasks()70 BlockingTaskRunner::CapturePostTasks::~CapturePostTasks() {
71   blocking_runner_->SetCapture(false);
72 }
73 
74 }  // namespace cc
75