Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: base/timer/alarm_timer.cc

Issue 641943002: components: Introduce AlarmTimer class and use it for GCM heartbeat (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make some Timer variables protected to reduce duplication, clean up comments Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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/timer/alarm_timer.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/files/file_util.h"
10 #include "base/logging.h"
11 #include "base/pending_task.h"
12
13 #if defined(OS_CHROMEOS)
14 #include "base/timer/rtc_alarm_chromeos.h"
15 #endif
16
17 namespace base {
18
19 namespace {
20
21 // Default delegate for the alarm timer on non-Chrome OS systems. Tells the
22 // AlarmTimer class that it doesn't have the ability to wake the system from
23 // suspend and that it should just behave as a regular Timer.
24 class DefaultAlarmTimerDelegate : public base::AlarmTimer::Delegate {
25 public:
26 DefaultAlarmTimerDelegate() {}
27
28 virtual bool Init(base::WeakPtr<AlarmTimer> timer) override { return false; }
29 virtual void Stop() override {
30 NOTREACHED() << "Attempting to call Stop() on the default alarm timer "
31 << "delegate";
32 }
33 virtual void Reset(base::TimeDelta delay) override {
34 NOTREACHED() << "Attempting to call Reset() on the default alarm timer "
35 << "delegate";
36 }
37
38 protected:
39 virtual ~DefaultAlarmTimerDelegate() {}
40 };
41
42 } // namespace
43
44 AlarmTimer::AlarmTimer(bool retain_user_task, bool is_repeating)
45 : Timer(retain_user_task, is_repeating),
46 #if defined(OS_CHROMEOS)
47 delegate_(new RtcAlarmChromeos()),
48 #else
49 delegate_(new DefaultAlarmTimerDelegate()),
50 #endif
51 can_wake_from_suspend_(false),
52 origin_message_loop_(NULL),
53 weak_factory_(this) {
54 can_wake_from_suspend_ = delegate_->Init(weak_factory_.GetWeakPtr());
55 }
56
57 AlarmTimer::AlarmTimer(const tracked_objects::Location& posted_from,
58 TimeDelta delay,
59 const Closure& user_task,
60 bool is_repeating)
61 : Timer(posted_from, delay, user_task, is_repeating),
62 #if defined(OS_CHROMEOS)
Daniel Erat 2014/10/15 15:04:22 i don't have strong feelings here, but it might be
Chirantan Ekbote 2014/10/16 21:26:38 Done.
63 delegate_(new RtcAlarmChromeos()),
64 #else
65 delegate_(new DefaultAlarmTimerDelegate()),
66 #endif
67 can_wake_from_suspend_(false),
68 origin_message_loop_(NULL),
69 weak_factory_(this) {
70 can_wake_from_suspend_ = delegate_->Init(weak_factory_.GetWeakPtr());
71 }
72
73 AlarmTimer::~AlarmTimer() {
74 Stop();
75 }
76
77 bool AlarmTimer::IsRunning() const {
78 if (!can_wake_from_suspend_)
Daniel Erat 2014/10/15 15:04:21 nit: return can_wake_from_suspend_ ? is_running
79 return Timer::IsRunning();
80
81 return is_running_;
82 }
83
84 TimeDelta AlarmTimer::GetCurrentDelay() const {
85 if (!can_wake_from_suspend_)
Daniel Erat 2014/10/15 15:04:21 nit: return can_wake_from_suspend_ ? delay_ : T
86 return Timer::GetCurrentDelay();
87
88 return delay_;
89 }
90
91 void AlarmTimer::Start(const tracked_objects::Location& posted_from,
92 TimeDelta delay,
93 const Closure& user_task) {
94 if (!can_wake_from_suspend_) {
95 Timer::Start(posted_from, delay, user_task);
96 return;
97 }
98
99 // This is identical to the implementation of Timer::Start but we have this
100 // one anyway for clarity.
Daniel Erat 2014/10/15 15:04:21 not sure i understand this. if this method is iden
Chirantan Ekbote 2014/10/16 21:26:38 It's being overridden so that someone reading the
101 Timer::SetTaskInfo(posted_from, delay, user_task);
102 Reset();
103 }
104
105 void AlarmTimer::Stop() {
106 if (!can_wake_from_suspend_) {
107 Timer::Stop();
108 return;
109 }
110
111 // Clear the running flag, stop the delegate, and delete the pending task.
112 is_running_ = false;
113 delegate_->Stop();
114 pending_task_.reset();
115
116 // Stop is called when the AlarmTimer is destroyed so we need to remove
117 // ourselves as a MessageLoop::DestructionObserver to prevent a segfault
118 // later.
119 if (origin_message_loop_) {
120 origin_message_loop_->RemoveDestructionObserver(this);
121 origin_message_loop_ = NULL;
122 }
123
124 if (!retain_user_task_)
125 user_task_.Reset();
126 }
127
128 void AlarmTimer::Reset() {
129 if (!can_wake_from_suspend_) {
130 Timer::Reset();
131 return;
132 }
133
134 DCHECK(!user_task_.is_null());
135 DCHECK(!origin_message_loop_ ||
136 origin_message_loop_->task_runner()->RunsTasksOnCurrentThread());
137
138 // Make sure that the timer will stop if the underlying message loop is
139 // destroyed.
140 if (!origin_message_loop_) {
141 origin_message_loop_ = MessageLoop::current();
142 origin_message_loop_->AddDestructionObserver(this);
143 }
144
145 // Set up the pending task.
146 if (delay_ == TimeDelta()) {
147 desired_run_time_ = TimeTicks();
148 pending_task_.reset(new PendingTask(posted_from_, user_task_));
149 } else {
150 desired_run_time_ = TimeTicks::Now() + delay_;
151 pending_task_.reset(
152 new PendingTask(posted_from_, user_task_, desired_run_time_, true));
153 }
154 MessageLoop::current()->task_annotator()->DidQueueTask("AlarmTimer::Reset",
155 *pending_task_);
156
157 // Now start up the timer.
158 delegate_->Reset(delay_);
159 is_running_ = true;
160 }
161
162 void AlarmTimer::WillDestroyCurrentMessageLoop() {
163 Stop();
164 }
165
166 void AlarmTimer::OnTimerFired() {
167 if (!is_running_)
168 return;
169
170 DCHECK(pending_task_.get());
171
172 // Take ownership of the pending user task, which is going to be cleared by
173 // the Stop() or Reset() functions below.
174 scoped_ptr<PendingTask> pending_user_task(pending_task_.Pass());
175
176 // Re-schedule or stop the timer as requested.
177 if (is_repeating_)
178 Reset();
179 else
180 Stop();
181
182 // Now lets run the user task.
Daniel Erat 2014/10/15 15:04:22 nit: s/lets/let's/ or just delete that word
Chirantan Ekbote 2014/10/16 21:26:38 Done.
183 MessageLoop::current()->task_annotator()->RunTask(
184 "AlarmTimer::Reset", "AlarmTimer::OnTimerFired", *pending_user_task);
185 }
186
187 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698