1 // Copyright (c) 2013 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/deferred_sequenced_task_runner.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11
12 namespace base {
13
DeferredTask()14 DeferredSequencedTaskRunner::DeferredTask::DeferredTask()
15 : is_non_nestable(false) {
16 }
17
18 DeferredSequencedTaskRunner::DeferredTask::DeferredTask(DeferredTask&& other) =
19 default;
20
21 DeferredSequencedTaskRunner::DeferredTask::~DeferredTask() = default;
22
23 DeferredSequencedTaskRunner::DeferredTask&
24 DeferredSequencedTaskRunner::DeferredTask::operator=(DeferredTask&& other) =
25 default;
26
DeferredSequencedTaskRunner(scoped_refptr<SequencedTaskRunner> target_task_runner)27 DeferredSequencedTaskRunner::DeferredSequencedTaskRunner(
28 scoped_refptr<SequencedTaskRunner> target_task_runner)
29 : DeferredSequencedTaskRunner() {
30 DCHECK(target_task_runner);
31 target_task_runner_ = std::move(target_task_runner);
32 }
33
DeferredSequencedTaskRunner()34 DeferredSequencedTaskRunner::DeferredSequencedTaskRunner()
35 : created_thread_id_(PlatformThread::CurrentId()) {}
36
PostDelayedTask(const Location & from_here,OnceClosure task,TimeDelta delay)37 bool DeferredSequencedTaskRunner::PostDelayedTask(const Location& from_here,
38 OnceClosure task,
39 TimeDelta delay) {
40 AutoLock lock(lock_);
41 if (started_) {
42 DCHECK(deferred_tasks_queue_.empty());
43 return target_task_runner_->PostDelayedTask(from_here, std::move(task),
44 delay);
45 }
46
47 QueueDeferredTask(from_here, std::move(task), delay,
48 false /* is_non_nestable */);
49 return true;
50 }
51
RunsTasksInCurrentSequence() const52 bool DeferredSequencedTaskRunner::RunsTasksInCurrentSequence() const {
53 AutoLock lock(lock_);
54 if (target_task_runner_)
55 return target_task_runner_->RunsTasksInCurrentSequence();
56
57 return created_thread_id_ == PlatformThread::CurrentId();
58 }
59
PostNonNestableDelayedTask(const Location & from_here,OnceClosure task,TimeDelta delay)60 bool DeferredSequencedTaskRunner::PostNonNestableDelayedTask(
61 const Location& from_here,
62 OnceClosure task,
63 TimeDelta delay) {
64 AutoLock lock(lock_);
65 if (started_) {
66 DCHECK(deferred_tasks_queue_.empty());
67 return target_task_runner_->PostNonNestableDelayedTask(
68 from_here, std::move(task), delay);
69 }
70 QueueDeferredTask(from_here, std::move(task), delay,
71 true /* is_non_nestable */);
72 return true;
73 }
74
Start()75 void DeferredSequencedTaskRunner::Start() {
76 AutoLock lock(lock_);
77 StartImpl();
78 }
79
StartWithTaskRunner(scoped_refptr<SequencedTaskRunner> target_task_runner)80 void DeferredSequencedTaskRunner::StartWithTaskRunner(
81 scoped_refptr<SequencedTaskRunner> target_task_runner) {
82 AutoLock lock(lock_);
83 DCHECK(!target_task_runner_);
84 DCHECK(target_task_runner);
85 target_task_runner_ = std::move(target_task_runner);
86 StartImpl();
87 }
88
89 DeferredSequencedTaskRunner::~DeferredSequencedTaskRunner() = default;
90
QueueDeferredTask(const Location & from_here,OnceClosure task,TimeDelta delay,bool is_non_nestable)91 void DeferredSequencedTaskRunner::QueueDeferredTask(const Location& from_here,
92 OnceClosure task,
93 TimeDelta delay,
94 bool is_non_nestable) {
95 lock_.AssertAcquired();
96
97 // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167
98 // for details.
99 CHECK(task);
100
101 DeferredTask deferred_task;
102 deferred_task.posted_from = from_here;
103 deferred_task.task = std::move(task);
104 deferred_task.delay = delay;
105 deferred_task.is_non_nestable = is_non_nestable;
106 deferred_tasks_queue_.push_back(std::move(deferred_task));
107 }
108
StartImpl()109 void DeferredSequencedTaskRunner::StartImpl() {
110 lock_.AssertAcquired(); // Callers should have grabbed the lock.
111 DCHECK(!started_);
112 started_ = true;
113 DCHECK(target_task_runner_);
114 for (std::vector<DeferredTask>::iterator i = deferred_tasks_queue_.begin();
115 i != deferred_tasks_queue_.end();
116 ++i) {
117 DeferredTask& task = *i;
118 if (task.is_non_nestable) {
119 target_task_runner_->PostNonNestableDelayedTask(
120 task.posted_from, std::move(task.task), task.delay);
121 } else {
122 target_task_runner_->PostDelayedTask(task.posted_from,
123 std::move(task.task), task.delay);
124 }
125 }
126 deferred_tasks_queue_.clear();
127 }
128
129 } // namespace base
130