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