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

Side by Side Diff: components/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: Fix gyp files 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 "components/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 #include "components/timer/rtc_alarm.h"
13
14 namespace timer {
15
16 AlarmTimer::AlarmTimer(bool retain_user_task, bool is_repeating)
17 : base::Timer(retain_user_task, is_repeating),
18 delegate_(new RtcAlarm()),
19 can_wake_from_suspend_(false),
20 origin_message_loop_(NULL),
21 weak_factory_(this) {
22 can_wake_from_suspend_ = delegate_->Init(weak_factory_.GetWeakPtr());
23 }
24
25 AlarmTimer::AlarmTimer(const tracked_objects::Location& posted_from,
26 base::TimeDelta delay,
27 const base::Closure& user_task,
28 bool is_repeating)
29 : base::Timer(posted_from, delay, user_task, is_repeating),
30 delegate_(new RtcAlarm()),
31 can_wake_from_suspend_(false),
32 origin_message_loop_(NULL),
33 weak_factory_(this) {
34 can_wake_from_suspend_ = delegate_->Init(weak_factory_.GetWeakPtr());
35 }
36
37 AlarmTimer::~AlarmTimer() {
38 Stop();
39 }
40
41 void AlarmTimer::Stop() {
42 if (!can_wake_from_suspend_) {
43 base::Timer::Stop();
44 return;
45 }
46
47 // Clear the running flag, stop the delegate, and delete the pending task.
48 is_running_ = false;
49 delegate_->Stop();
50 pending_task_.reset();
51
52 // Stop is called when the AlarmTimer is destroyed so we need to remove
53 // ourselves as a MessageLoop::DestructionObserver to prevent a segfault
54 // later.
55 if (origin_message_loop_) {
56 origin_message_loop_->RemoveDestructionObserver(this);
57 origin_message_loop_ = NULL;
58 }
59
60 if (!retain_user_task_)
61 user_task_.Reset();
62 }
63
64 void AlarmTimer::Reset() {
65 if (!can_wake_from_suspend_) {
66 base::Timer::Reset();
67 return;
68 }
69
70 DCHECK(!user_task_.is_null());
71 DCHECK(!origin_message_loop_ ||
72 origin_message_loop_->task_runner()->RunsTasksOnCurrentThread());
73
74 // Make sure that the timer will stop if the underlying message loop is
75 // destroyed.
76 if (!origin_message_loop_) {
77 origin_message_loop_ = base::MessageLoop::current();
78 origin_message_loop_->AddDestructionObserver(this);
79 }
80
81 // Set up the pending task.
82 if (delay_ == base::TimeDelta()) {
Lei Zhang 2014/10/21 22:34:11 timer.cc uses "delay_ > TimeDelta::FromMicrosecond
Chirantan Ekbote 2014/10/21 22:52:21 Ah ok. Will fix in the next patch set.
Daniel Erat 2014/10/23 03:44:54 TimeDelta() and TimeDelta::FromMicroseconds(0) are
Chirantan Ekbote 2014/10/23 23:53:30 The documentation for timerfd_settime doesn't say
83 desired_run_time_ = base::TimeTicks();
84 pending_task_.reset(new base::PendingTask(posted_from_, user_task_));
85 } else {
86 desired_run_time_ = base::TimeTicks::Now() + delay_;
87 pending_task_.reset(new base::PendingTask(
88 posted_from_, user_task_, desired_run_time_, true));
89 }
90 base::MessageLoop::current()->task_annotator()->DidQueueTask(
91 "AlarmTimer::Reset", *pending_task_);
92
93 // Now start up the timer.
94 delegate_->Reset(delay_);
95 is_running_ = true;
96 }
97
98 void AlarmTimer::WillDestroyCurrentMessageLoop() {
99 Stop();
100 }
101
102 void AlarmTimer::OnTimerFired() {
103 if (!is_running_)
104 return;
105
106 DCHECK(pending_task_.get());
107
108 // Take ownership of the pending user task, which is going to be cleared by
109 // the Stop() or Reset() functions below.
110 scoped_ptr<base::PendingTask> pending_user_task(pending_task_.Pass());
111
112 // Re-schedule or stop the timer as requested.
113 if (is_repeating_)
114 Reset();
115 else
116 Stop();
117
118 // Now run the user task.
119 base::MessageLoop::current()->task_annotator()->RunTask(
120 "AlarmTimer::Reset", "AlarmTimer::OnTimerFired", *pending_user_task);
121 }
122
123 } // namespace timer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698