• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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