|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/threading/worker_pool.h" | 
|  |  | 
|  | #include "base/bind.h" | 
|  | #include "base/compiler_specific.h" | 
|  | #include "base/debug/leak_annotations.h" | 
|  | #include "base/lazy_instance.h" | 
|  | #include "base/macros.h" | 
|  | #include "base/task_runner.h" | 
|  | #include "base/threading/post_task_and_reply_impl.h" | 
|  | #include "base/tracked_objects.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | class PostTaskAndReplyWorkerPool : public internal::PostTaskAndReplyImpl { | 
|  | public: | 
|  | explicit PostTaskAndReplyWorkerPool(bool task_is_slow) | 
|  | : task_is_slow_(task_is_slow) { | 
|  | } | 
|  | ~PostTaskAndReplyWorkerPool() override = default; | 
|  |  | 
|  | private: | 
|  | bool PostTask(const tracked_objects::Location& from_here, | 
|  | const Closure& task) override { | 
|  | return WorkerPool::PostTask(from_here, task, task_is_slow_); | 
|  | } | 
|  |  | 
|  | bool task_is_slow_; | 
|  | }; | 
|  |  | 
|  | // WorkerPoolTaskRunner --------------------------------------------- | 
|  | // A TaskRunner which posts tasks to a WorkerPool with a | 
|  | // fixed ShutdownBehavior. | 
|  | // | 
|  | // Note that this class is RefCountedThreadSafe (inherited from TaskRunner). | 
|  | class WorkerPoolTaskRunner : public TaskRunner { | 
|  | public: | 
|  | explicit WorkerPoolTaskRunner(bool tasks_are_slow); | 
|  |  | 
|  | // TaskRunner implementation | 
|  | bool PostDelayedTask(const tracked_objects::Location& from_here, | 
|  | const Closure& task, | 
|  | TimeDelta delay) override; | 
|  | bool RunsTasksOnCurrentThread() const override; | 
|  |  | 
|  | private: | 
|  | ~WorkerPoolTaskRunner() override; | 
|  |  | 
|  | // Helper function for posting a delayed task. Asserts that the delay is | 
|  | // zero because non-zero delays are not supported. | 
|  | bool PostDelayedTaskAssertZeroDelay( | 
|  | const tracked_objects::Location& from_here, | 
|  | const Closure& task, | 
|  | base::TimeDelta delay); | 
|  |  | 
|  | const bool tasks_are_slow_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(WorkerPoolTaskRunner); | 
|  | }; | 
|  |  | 
|  | WorkerPoolTaskRunner::WorkerPoolTaskRunner(bool tasks_are_slow) | 
|  | : tasks_are_slow_(tasks_are_slow) { | 
|  | } | 
|  |  | 
|  | WorkerPoolTaskRunner::~WorkerPoolTaskRunner() { | 
|  | } | 
|  |  | 
|  | bool WorkerPoolTaskRunner::PostDelayedTask( | 
|  | const tracked_objects::Location& from_here, | 
|  | const Closure& task, | 
|  | TimeDelta delay) { | 
|  | return PostDelayedTaskAssertZeroDelay(from_here, task, delay); | 
|  | } | 
|  |  | 
|  | bool WorkerPoolTaskRunner::RunsTasksOnCurrentThread() const { | 
|  | return WorkerPool::RunsTasksOnCurrentThread(); | 
|  | } | 
|  |  | 
|  | bool WorkerPoolTaskRunner::PostDelayedTaskAssertZeroDelay( | 
|  | const tracked_objects::Location& from_here, | 
|  | const Closure& task, | 
|  | base::TimeDelta delay) { | 
|  | DCHECK_EQ(delay.InMillisecondsRoundedUp(), 0) | 
|  | << "WorkerPoolTaskRunner does not support non-zero delays"; | 
|  | return WorkerPool::PostTask(from_here, task, tasks_are_slow_); | 
|  | } | 
|  |  | 
|  | struct TaskRunnerHolder { | 
|  | TaskRunnerHolder() { | 
|  | taskrunners_[0] = new WorkerPoolTaskRunner(false); | 
|  | taskrunners_[1] = new WorkerPoolTaskRunner(true); | 
|  | } | 
|  | scoped_refptr<TaskRunner> taskrunners_[2]; | 
|  | }; | 
|  |  | 
|  | base::LazyInstance<TaskRunnerHolder>::Leaky | 
|  | g_taskrunners = LAZY_INSTANCE_INITIALIZER; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | bool WorkerPool::PostTaskAndReply(const tracked_objects::Location& from_here, | 
|  | const Closure& task, | 
|  | const Closure& reply, | 
|  | bool task_is_slow) { | 
|  | // Do not report PostTaskAndReplyRelay leaks in tests. There's nothing we can | 
|  | // do about them because WorkerPool doesn't have a flushing API. | 
|  | // http://crbug.com/248513 | 
|  | // http://crbug.com/290897 | 
|  | // Note: this annotation does not cover tasks posted through a TaskRunner. | 
|  | ANNOTATE_SCOPED_MEMORY_LEAK; | 
|  | return PostTaskAndReplyWorkerPool(task_is_slow).PostTaskAndReply( | 
|  | from_here, task, reply); | 
|  | } | 
|  |  | 
|  | // static | 
|  | const scoped_refptr<TaskRunner>& | 
|  | WorkerPool::GetTaskRunner(bool tasks_are_slow) { | 
|  | return g_taskrunners.Get().taskrunners_[tasks_are_slow]; | 
|  | } | 
|  |  | 
|  | }  // namespace base |