blob: 70ec28695f13c8142b1872b02fa2f37867ae1e09 [file] [log] [blame]
ryanchung3aeb76a2017-02-23 01:41:571// Copyright 2017 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#ifndef CHROMECAST_BASE_ALARM_MANAGER_H_
6#define CHROMECAST_BASE_ALARM_MANAGER_H_
7
jameswest90b8e5b22017-06-07 23:31:428#include <functional>
9#include <memory>
ryanchung3aeb76a2017-02-23 01:41:5710#include <queue>
11#include <vector>
12
13#include "base/callback.h"
14#include "base/macros.h"
15#include "base/memory/ref_counted.h"
16#include "base/memory/weak_ptr.h"
jameswest90b8e5b22017-06-07 23:31:4217#include "base/timer/timer.h"
ryanchung3aeb76a2017-02-23 01:41:5718
19namespace base {
20class Clock;
21class SingleThreadTaskRunner;
ryanchung3aeb76a2017-02-23 01:41:5722}
23
24namespace chromecast {
25
ryanchung44776c72017-03-01 03:42:2726// Alarm handle for scoping the in-flight alarm.
27class AlarmHandle : public base::SupportsWeakPtr<AlarmHandle> {};
28
ryanchung3aeb76a2017-02-23 01:41:5729// Alarm manager allows setting a task for wall clock time rather than for an
30// elapsed amount of time. This is different from using long PostDelayedTasks
31// that are sensitive to time changes, clock drift, and other factors.
32//
33// Alarm manager polls the wall clock time every 5 seconds. If the clock is
34// equal or past the requested time, the alarm will fire.
35class AlarmManager {
36 public:
37 // Construct and start the alarm manager. The clock poller will run on the
38 // caller's thread.
39 AlarmManager();
40 ~AlarmManager();
41
42 // For testing only. Allows setting a fake clock and using a custom task
43 // runner.
44 AlarmManager(std::unique_ptr<base::Clock> clock,
45 scoped_refptr<base::SingleThreadTaskRunner> task_runner);
46
47 // Add an alarm.
48 // |task| will be executed at around |time|.
ryanchung6402a682017-02-24 22:40:1249 // Returns an AlarmHandle that must be kept alive. If the AlarmHandle is
50 // destroyed, the alarm will not fire.
ryanchung3aeb76a2017-02-23 01:41:5751 //
52 // Any thread can add alarms. The alarm will be fired on the original
53 // thread used to set the alarm.
54 //
55 // When an alarm is added to the alarm manager, the task is guaranteed to not
56 // run before the clock passes the requested time. The task may not run even
ryanchung6402a682017-02-24 22:40:1257 // if it is past the requested time if the software is suspended. However,
58 // once woken up, the event will fire within 5 seconds if the target time has
ryanchung3aeb76a2017-02-23 01:41:5759 // passed.
jameswest90b8e5b22017-06-07 23:31:4260 std::unique_ptr<AlarmHandle> PostAlarmTask(base::OnceClosure task,
ryanchung44776c72017-03-01 03:42:2761 base::Time time)
62 WARN_UNUSED_RESULT;
ryanchung3aeb76a2017-02-23 01:41:5763
64 private:
65 class AlarmInfo {
66 public:
jameswest90b8e5b22017-06-07 23:31:4267 AlarmInfo(base::OnceClosure task,
ryanchung3aeb76a2017-02-23 01:41:5768 base::Time time,
69 scoped_refptr<base::SingleThreadTaskRunner> task_runner);
70 ~AlarmInfo();
71
jameswest90b8e5b22017-06-07 23:31:4272 void PostTask();
73
ryanchung3aeb76a2017-02-23 01:41:5774 base::Time time() const { return time_; }
ryanchung3aeb76a2017-02-23 01:41:5775
76 private:
jameswest90b8e5b22017-06-07 23:31:4277 base::OnceClosure task_;
ryanchung3aeb76a2017-02-23 01:41:5778 const base::Time time_;
79 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
80 DISALLOW_COPY_AND_ASSIGN(AlarmInfo);
81 };
82
83 // Check if an alarm should fire.
84 void CheckAlarm();
85 // Add the alarm to the queue.
jameswest90b8e5b22017-06-07 23:31:4286 void AddAlarm(base::OnceClosure task,
ryanchung3aeb76a2017-02-23 01:41:5787 base::Time time,
88 scoped_refptr<base::SingleThreadTaskRunner> task_runner);
89
90 // Ordering alarms by earliest time.
91 struct alarm_compare
92 : public std::binary_function<std::unique_ptr<AlarmInfo>&,
93 std::unique_ptr<AlarmInfo>&,
94 bool> {
95 bool operator()(const std::unique_ptr<AlarmInfo>& lhs,
96 const std::unique_ptr<AlarmInfo>& rhs) const {
97 return lhs->time() > rhs->time();
98 }
99 };
100
101 // Store a list of the alarms to fire with the earliest getting priority.
102 std::priority_queue<std::unique_ptr<AlarmInfo>,
103 std::vector<std::unique_ptr<AlarmInfo>>,
104 alarm_compare>
105 next_alarm_;
106
107 // Poller for wall clock time.
108 std::unique_ptr<base::Clock> clock_;
jameswest90b8e5b22017-06-07 23:31:42109 base::RepeatingTimer clock_tick_timer_;
ryanchung3aeb76a2017-02-23 01:41:57110 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
111
112 base::WeakPtrFactory<AlarmManager> weak_factory_;
113
114 DISALLOW_COPY_AND_ASSIGN(AlarmManager);
115};
116
117} // namespace chromecast
118
ryanchung44776c72017-03-01 03:42:27119#endif // CHROMECAST_BASE_ALARM_MANAGER_H_