1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/deferred_sequenced_task_runner.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace base {
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DeferredSequencedTaskRunner::DeferredTask::DeferredTask() {
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DeferredSequencedTaskRunner::DeferredTask::~DeferredTask() {
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DeferredSequencedTaskRunner::DeferredSequencedTaskRunner(
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const scoped_refptr<SequencedTaskRunner>& target_task_runner)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : started_(false),
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      target_task_runner_(target_task_runner) {
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DeferredSequencedTaskRunner::~DeferredSequencedTaskRunner() {
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DeferredSequencedTaskRunner::PostDelayedTask(
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const tracked_objects::Location& from_here,
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const Closure& task,
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TimeDelta delay) {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AutoLock lock(lock_);
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (started_) {
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(deferred_tasks_queue_.empty());
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return target_task_runner_->PostDelayedTask(from_here, task, delay);
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QueueDeferredTask(from_here, task, delay, false /* is_non_nestable */);
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DeferredSequencedTaskRunner::RunsTasksOnCurrentThread() const {
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return target_task_runner_->RunsTasksOnCurrentThread();
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DeferredSequencedTaskRunner::PostNonNestableDelayedTask(
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const tracked_objects::Location& from_here,
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const Closure& task,
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TimeDelta delay) {
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AutoLock lock(lock_);
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (started_) {
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(deferred_tasks_queue_.empty());
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return target_task_runner_->PostNonNestableDelayedTask(from_here,
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                           task,
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                           delay);
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QueueDeferredTask(from_here, task, delay, true /* is_non_nestable */);
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeferredSequencedTaskRunner::QueueDeferredTask(
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const tracked_objects::Location& from_here,
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const Closure& task,
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TimeDelta delay,
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool is_non_nestable) {
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeferredTask deferred_task;
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deferred_task.posted_from = from_here;
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deferred_task.task = task;
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deferred_task.delay = delay;
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deferred_task.is_non_nestable = is_non_nestable;
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deferred_tasks_queue_.push_back(deferred_task);
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeferredSequencedTaskRunner::Start() {
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AutoLock lock(lock_);
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!started_);
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  started_ = true;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (std::vector<DeferredTask>::iterator i = deferred_tasks_queue_.begin();
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      i != deferred_tasks_queue_.end();
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ++i) {
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const DeferredTask& task = *i;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (task.is_non_nestable) {
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      target_task_runner_->PostNonNestableDelayedTask(task.posted_from,
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                      task.task,
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                      task.delay);
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      target_task_runner_->PostDelayedTask(task.posted_from,
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           task.task,
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           task.delay);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Replace the i-th element in the |deferred_tasks_queue_| with an empty
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // |DelayedTask| to ensure that |task| is destroyed before the next task
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // is posted.
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *i = DeferredTask();
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deferred_tasks_queue_.clear();
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace base
100