1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_BASE_ALARM_MANAGER_H_
#define CHROMECAST_BASE_ALARM_MANAGER_H_
#include <memory>
#include <queue>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
namespace base {
class Clock;
class SingleThreadTaskRunner;
}
namespace chromecast {
// Alarm handle for scoping the in-flight alarm.
class AlarmHandle : public base::SupportsWeakPtr<AlarmHandle> {};
// Alarm manager allows setting a task for wall clock time rather than for an
// elapsed amount of time. This is different from using long PostDelayedTasks
// that are sensitive to time changes, clock drift, and other factors.
//
// Alarm manager polls the wall clock time every 5 seconds. If the clock is
// equal or past the requested time, the alarm will fire.
class AlarmManager {
public:
// Construct and start the alarm manager. The clock poller will run on the
// caller's thread.
AlarmManager();
AlarmManager(const AlarmManager&) = delete;
AlarmManager& operator=(const AlarmManager&) = delete;
~AlarmManager();
// For testing only. Allows setting a fake clock and using a custom task
// runner.
AlarmManager(const base::Clock* clock,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
// Add an alarm.
// |task| will be executed at around |time|.
// Returns an AlarmHandle that must be kept alive. If the AlarmHandle is
// destroyed, the alarm will not fire.
//
// Any thread can add alarms. The alarm will be fired on the original
// thread used to set the alarm.
//
// When an alarm is added to the alarm manager, the task is guaranteed to not
// run before the clock passes the requested time. The task may not run even
// if it is past the requested time if the software is suspended. However,
// once woken up, the event will fire within 5 seconds if the target time has
// passed.
[[nodiscard]] std::unique_ptr<AlarmHandle> PostAlarmTask(
base::OnceClosure task,
base::Time time);
private:
class AlarmInfo {
public:
AlarmInfo(base::OnceClosure task,
base::Time time,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
AlarmInfo(const AlarmInfo&) = delete;
AlarmInfo& operator=(const AlarmInfo&) = delete;
~AlarmInfo();
void PostTask();
base::Time time() const { return time_; }
private:
base::OnceClosure task_;
const base::Time time_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
};
// Check if an alarm should fire.
void CheckAlarm();
// Add the alarm to the queue.
void AddAlarm(base::OnceClosure task,
base::Time time,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
// Ordering alarms by earliest time.
struct alarm_compare {
bool operator()(const std::unique_ptr<AlarmInfo>& lhs,
const std::unique_ptr<AlarmInfo>& rhs) const {
return lhs->time() > rhs->time();
}
};
// Store a list of the alarms to fire with the earliest getting priority.
std::priority_queue<std::unique_ptr<AlarmInfo>,
std::vector<std::unique_ptr<AlarmInfo>>,
alarm_compare>
next_alarm_;
// Poller for wall clock time.
const base::Clock* const clock_;
base::RepeatingTimer clock_tick_timer_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::WeakPtrFactory<AlarmManager> weak_factory_;
};
} // namespace chromecast
#endif // CHROMECAST_BASE_ALARM_MANAGER_H_
|