Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
| OLD | NEW |