15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/worker_pool.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/debug/leak_annotations.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/task_runner.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/post_task_and_reply_impl.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PostTaskAndReplyWorkerPool : public internal::PostTaskAndReplyImpl {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit PostTaskAndReplyWorkerPool(bool task_is_slow)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : task_is_slow_(task_is_slow) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool PostTask(const tracked_objects::Location& from_here,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const Closure& task) OVERRIDE {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WorkerPool::PostTask(from_here, task, task_is_slow_);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool task_is_slow_;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WorkerPoolTaskRunner ---------------------------------------------
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A TaskRunner which posts tasks to a WorkerPool with a
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fixed ShutdownBehavior.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that this class is RefCountedThreadSafe (inherited from TaskRunner).
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WorkerPoolTaskRunner : public TaskRunner {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit WorkerPoolTaskRunner(bool tasks_are_slow);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TaskRunner implementation
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const Closure& task,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               TimeDelta delay) OVERRIDE;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool RunsTasksOnCurrentThread() const OVERRIDE;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~WorkerPoolTaskRunner();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper function for posting a delayed task. Asserts that the delay is
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // zero because non-zero delays are not supported.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool PostDelayedTaskAssertZeroDelay(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const tracked_objects::Location& from_here,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Closure& task,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta delay);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool tasks_are_slow_;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WorkerPoolTaskRunner);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WorkerPoolTaskRunner::WorkerPoolTaskRunner(bool tasks_are_slow)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : tasks_are_slow_(tasks_are_slow) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WorkerPoolTaskRunner::~WorkerPoolTaskRunner() {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WorkerPoolTaskRunner::PostDelayedTask(
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Closure& task,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TimeDelta delay) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PostDelayedTaskAssertZeroDelay(from_here, task, delay);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WorkerPoolTaskRunner::RunsTasksOnCurrentThread() const {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WorkerPool::RunsTasksOnCurrentThread();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WorkerPoolTaskRunner::PostDelayedTaskAssertZeroDelay(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Closure& task,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta delay) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(delay.InMillisecondsRoundedUp(), 0)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "WorkerPoolTaskRunner does not support non-zero delays";
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WorkerPool::PostTask(from_here, task, tasks_are_slow_);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TaskRunnerHolder {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskRunnerHolder() {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    taskrunners_[0] = new WorkerPoolTaskRunner(false);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    taskrunners_[1] = new WorkerPoolTaskRunner(true);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<TaskRunner> taskrunners_[2];
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<TaskRunnerHolder>::Leaky
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_taskrunners = LAZY_INSTANCE_INITIALIZER;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WorkerPool::PostTaskAndReply(const tracked_objects::Location& from_here,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const Closure& task,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const Closure& reply,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool task_is_slow) {
108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Do not report PostTaskAndReplyRelay leaks in tests. There's nothing we can
109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // do about them because WorkerPool doesn't have a flushing API.
110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // http://crbug.com/248513
111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // http://crbug.com/290897
112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Note: this annotation does not cover tasks posted through a TaskRunner.
113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ANNOTATE_SCOPED_MEMORY_LEAK;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PostTaskAndReplyWorkerPool(task_is_slow).PostTaskAndReply(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      from_here, task, reply);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const scoped_refptr<TaskRunner>&
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WorkerPool::GetTaskRunner(bool tasks_are_slow) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_taskrunners.Get().taskrunners_[tasks_are_slow];
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
125