Home | History | Annotate | Download | only in threading
      1 // Copyright (c) 2012 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 "base/threading/worker_pool.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/compiler_specific.h"
      9 #include "base/debug/leak_annotations.h"
     10 #include "base/lazy_instance.h"
     11 #include "base/task_runner.h"
     12 #include "base/threading/post_task_and_reply_impl.h"
     13 #include "base/tracked_objects.h"
     14 
     15 namespace base {
     16 
     17 namespace {
     18 
     19 class PostTaskAndReplyWorkerPool : public internal::PostTaskAndReplyImpl {
     20  public:
     21   explicit PostTaskAndReplyWorkerPool(bool task_is_slow)
     22       : task_is_slow_(task_is_slow) {
     23   }
     24 
     25  private:
     26   virtual bool PostTask(const tracked_objects::Location& from_here,
     27                         const Closure& task) OVERRIDE {
     28     return WorkerPool::PostTask(from_here, task, task_is_slow_);
     29   }
     30 
     31   bool task_is_slow_;
     32 };
     33 
     34 // WorkerPoolTaskRunner ---------------------------------------------
     35 // A TaskRunner which posts tasks to a WorkerPool with a
     36 // fixed ShutdownBehavior.
     37 //
     38 // Note that this class is RefCountedThreadSafe (inherited from TaskRunner).
     39 class WorkerPoolTaskRunner : public TaskRunner {
     40  public:
     41   explicit WorkerPoolTaskRunner(bool tasks_are_slow);
     42 
     43   // TaskRunner implementation
     44   virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
     45                                const Closure& task,
     46                                TimeDelta delay) OVERRIDE;
     47   virtual bool RunsTasksOnCurrentThread() const OVERRIDE;
     48 
     49  private:
     50   virtual ~WorkerPoolTaskRunner();
     51 
     52   // Helper function for posting a delayed task. Asserts that the delay is
     53   // zero because non-zero delays are not supported.
     54   bool PostDelayedTaskAssertZeroDelay(
     55       const tracked_objects::Location& from_here,
     56       const Closure& task,
     57       base::TimeDelta delay);
     58 
     59   const bool tasks_are_slow_;
     60 
     61   DISALLOW_COPY_AND_ASSIGN(WorkerPoolTaskRunner);
     62 };
     63 
     64 WorkerPoolTaskRunner::WorkerPoolTaskRunner(bool tasks_are_slow)
     65     : tasks_are_slow_(tasks_are_slow) {
     66 }
     67 
     68 WorkerPoolTaskRunner::~WorkerPoolTaskRunner() {
     69 }
     70 
     71 bool WorkerPoolTaskRunner::PostDelayedTask(
     72     const tracked_objects::Location& from_here,
     73     const Closure& task,
     74     TimeDelta delay) {
     75   return PostDelayedTaskAssertZeroDelay(from_here, task, delay);
     76 }
     77 
     78 bool WorkerPoolTaskRunner::RunsTasksOnCurrentThread() const {
     79   return WorkerPool::RunsTasksOnCurrentThread();
     80 }
     81 
     82 bool WorkerPoolTaskRunner::PostDelayedTaskAssertZeroDelay(
     83     const tracked_objects::Location& from_here,
     84     const Closure& task,
     85     base::TimeDelta delay) {
     86   DCHECK_EQ(delay.InMillisecondsRoundedUp(), 0)
     87       << "WorkerPoolTaskRunner does not support non-zero delays";
     88   return WorkerPool::PostTask(from_here, task, tasks_are_slow_);
     89 }
     90 
     91 struct TaskRunnerHolder {
     92   TaskRunnerHolder() {
     93     taskrunners_[0] = new WorkerPoolTaskRunner(false);
     94     taskrunners_[1] = new WorkerPoolTaskRunner(true);
     95   }
     96   scoped_refptr<TaskRunner> taskrunners_[2];
     97 };
     98 
     99 base::LazyInstance<TaskRunnerHolder>::Leaky
    100     g_taskrunners = LAZY_INSTANCE_INITIALIZER;
    101 
    102 }  // namespace
    103 
    104 bool WorkerPool::PostTaskAndReply(const tracked_objects::Location& from_here,
    105                                   const Closure& task,
    106                                   const Closure& reply,
    107                                   bool task_is_slow) {
    108   // Do not report PostTaskAndReplyRelay leaks in tests. There's nothing we can
    109   // do about them because WorkerPool doesn't have a flushing API.
    110   // http://crbug.com/248513
    111   // http://crbug.com/290897
    112   // Note: this annotation does not cover tasks posted through a TaskRunner.
    113   ANNOTATE_SCOPED_MEMORY_LEAK;
    114   return PostTaskAndReplyWorkerPool(task_is_slow).PostTaskAndReply(
    115       from_here, task, reply);
    116 }
    117 
    118 // static
    119 const scoped_refptr<TaskRunner>&
    120 WorkerPool::GetTaskRunner(bool tasks_are_slow) {
    121   return g_taskrunners.Get().taskrunners_[tasks_are_slow];
    122 }
    123 
    124 }  // namespace base
    125