Index: chromecast/base/alarm_manager.cc |
diff --git a/chromecast/base/alarm_manager.cc b/chromecast/base/alarm_manager.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..217f8acc591a2fca3d8fa444db08a8b17e9bc311 |
--- /dev/null |
+++ b/chromecast/base/alarm_manager.cc |
@@ -0,0 +1,93 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chromecast/base/alarm_manager.h" |
+ |
+#include "base/memory/ptr_util.h" |
+#include "base/threading/thread_task_runner_handle.h" |
+#include "base/time/default_clock.h" |
+ |
+namespace chromecast { |
+ |
+namespace { |
+// How often to poll the clock. |
+int kClockPollInterval = 5; |
+} // namespace |
+ |
+// AlarmInfo is for recording the time and task runner for the alarm. |
+AlarmManager::AlarmInfo::AlarmInfo( |
+ base::Time time, |
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) { |
+ time_ = time; |
+ task_runner_ = task_runner; |
+} |
+ |
+AlarmManager::AlarmInfo::~AlarmInfo() {} |
+ |
+AlarmManager::AlarmManager(std::unique_ptr<base::Clock> clock) |
+ : clock_(std::move(clock)), weak_factory_(this) { |
+ Start(); |
+} |
+ |
+AlarmManager::AlarmManager() |
+ : clock_(new base::DefaultClock()), weak_factory_(this) { |
+ Start(); |
+} |
+ |
+AlarmManager::~AlarmManager() { |
+ Stop(); |
+} |
+ |
+void AlarmManager::Start() { |
+ clock_tick_timer_.reset(new base::RepeatingTimer()); |
+ base::TimeDelta polling_frequency = |
+ base::TimeDelta::FromSeconds(kClockPollInterval); |
+ clock_tick_timer_->Start( |
+ FROM_HERE, polling_frequency, |
+ base::Bind(&AlarmManager::CheckAlarm, weak_factory_.GetWeakPtr())); |
+} |
+ |
+void AlarmManager::Stop() { |
+ clock_tick_timer_.reset(nullptr); |
+} |
+ |
+void AlarmManager::AddAlarm(AlarmDelegate* delegate, base::Time time) { |
+ base::AutoLock lock(alarms_lock_); |
+ next_alarm_.push(time); |
+ std::unique_ptr<AlarmInfo> info = |
+ base::MakeUnique<AlarmInfo>(time, base::ThreadTaskRunnerHandle::Get()); |
+ alarms_[delegate] = std::move(info); |
+} |
+void AlarmManager::RemoveAlarm(AlarmDelegate* delegate) { |
+ base::AutoLock lock(alarms_lock_); |
+ alarms_.erase(delegate); |
+} |
+ |
+void AlarmManager::CheckAlarm() { |
+ base::AutoLock lock(alarms_lock_); |
+ base::Time now = clock_->Now(); |
+ if (next_alarm_.empty() || now < next_alarm_.top()) { |
+ return; |
+ } |
+ |
+ // An alarm should fire. |
+ while ((!next_alarm_.empty()) && now >= next_alarm_.top()) { |
+ // Clear all the elapsed dates. |
+ next_alarm_.pop(); |
+ } |
+ |
+ // Fire appropriate alarms. |
+ for (auto alarm = alarms_.begin(); alarm != alarms_.end();) { |
+ if (now >= alarm->second->time_) { |
+ alarm->second->task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&AlarmDelegate::OnAlarmFire, |
+ base::Unretained(alarm->first))); |
+ alarm = alarms_.erase(alarm); |
+ } else { |
+ ++alarm; |
+ } |
+ } |
+} |
+ |
+} // chromecast |