Home | History | Annotate | Download | only in trees
      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
     16 scoped_ptr<BlockingTaskRunner> BlockingTaskRunner::Create(
     17     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
     18   return make_scoped_ptr(new BlockingTaskRunner(task_runner));
     19 }
     20 
     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 
     28 BlockingTaskRunner::~BlockingTaskRunner() {}
     29 
     30 bool BlockingTaskRunner::BelongsToCurrentThread() {
     31   return base::PlatformThread::CurrentId() == thread_id_;
     32 }
     33 
     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 
     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 
     64 BlockingTaskRunner::CapturePostTasks::CapturePostTasks(
     65     BlockingTaskRunner* blocking_runner)
     66     : blocking_runner_(blocking_runner) {
     67   blocking_runner_->SetCapture(true);
     68 }
     69 
     70 BlockingTaskRunner::CapturePostTasks::~CapturePostTasks() {
     71   blocking_runner_->SetCapture(false);
     72 }
     73 
     74 }  // namespace cc
     75