blob: ea281767188e6ce002170a1da5400ff93587a0cc [file] [log] [blame]
Matt Spinler2de67cf2017-04-27 11:07:53 -05001#pragma once
2
3#include <chrono>
4#include <functional>
5#include <memory>
6#include <systemd/sd-event.h>
7
8namespace phosphor
9{
10namespace fan
11{
12namespace util
13{
14
15struct EventSourceDeleter
16{
17 void operator()(sd_event_source* eventSource) const
18 {
19 sd_event_source_unref(eventSource);
20 }
21};
22
23using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;
24
25using EventPtr = std::shared_ptr<sd_event>;
26
27/**
28 * @class Timer
29 *
30 * This class implements a simple timer that runs an arbitrary
31 * function on expiration. The timeout value is set in microseconds.
32 * It can be stopped while it is running, and queried to see if it is
33 * running.
34 *
35 * If started with the 'repeating' argument, it will keep calling the
36 * callback function every <timeout> microseconds. If started with the
37 * 'oneshot' argument, it will just call the callback function one time.
38 *
39 * It needs an sd_event loop to function.
40 */
41class Timer
42{
43 public:
44
45 enum class TimerType
46 {
47 oneshot,
48 repeating
49 };
50
51 Timer() = delete;
52 Timer(const Timer&) = delete;
53 Timer& operator=(const Timer&) = delete;
54 Timer(Timer&&) = default;
55 Timer& operator=(Timer&&) = default;
56
57 /**
58 * @brief Constructs timer object
59 *
60 * @param[in] events - sd_event pointer, previously created
61 * @param[in] callbackFunc - The function to call on timer expiration
62 */
63 Timer(EventPtr& events,
64 std::function<void()> callbackFunc);
65
66 /**
67 * @brief Destructor
68 */
69 ~Timer();
70
71 /**
72 * @brief Starts the timer
73 *
74 * The input is an offset from the current steady clock.
75 *
76 * @param[in] usec - the timeout value in microseconds
77 * @param[in] type - either a oneshot, or repeating
78 */
79 void start(std::chrono::microseconds usec,
80 TimerType type = TimerType::oneshot);
81
82 /**
83 * @brief Stop the timer
84 */
85 void stop();
86
87 /**
88 * @brief Returns true if the timer is running
89 */
90 bool running();
91
92 /**
93 * @brief Returns the timeout value
94 *
95 * @return - the last value sent in via start().
96 *
97 * Could be used to restart the timer with the same
98 * timeout. i.e. start(getTimeout());
99 */
100 inline auto getTimeout() const
101 {
102 return timeout;
103 }
104
105 /**
106 * @brief Returns the timer type
107 */
108 inline auto getType() const
109 {
110 return type;
111 }
112
113 private:
114
115 /**
116 * @brief Callback function when timer goes off
117 *
118 * Calls the callback function passed in by the user.
119 *
120 * @param[in] eventSource - Source of the event
121 * @param[in] usec - time in micro seconds
122 * @param[in] userData - User data pointer
123 */
124 static int timeoutHandler(sd_event_source* eventSource,
125 uint64_t usec, void* userData);
126
127 /**
128 * @brief Gets the current time from the steady clock
129 */
130 std::chrono::microseconds getTime();
131
132 /**
133 * @brief Wrapper around sd_event_source_set_enabled
134 *
135 * @param[in] action - either SD_EVENT_OFF, SD_EVENT_ON,
136 * or SD_EVENT_ONESHOT
137 */
138 void setTimer(int action);
139
140
141 /**
142 * @brief Sets the expiration time for the timer
143 *
144 * Sets it to timeout microseconds in the future
145 */
146 void setTimeout();
147
148 /**
149 * @brief The sd_event structure
150 */
151 EventPtr timeEvent;
152
153 /**
154 * @brief Source of events
155 */
156 EventSourcePtr eventSource;
157
158 /**
159 * @brief Either 'repeating' or 'oneshot'
160 */
161 TimerType type = TimerType::oneshot;
162
163 /**
164 * @brief The function to call when the timer expires
165 */
166 std::function<void()> callback;
167
168 /**
169 * @brief What the timer was set to run for
170 *
171 * Not cleared on timer expiration
172 */
173 std::chrono::microseconds timeout;
174};
175
176}
177}
178}