summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Kodihalli <dkodihal@in.ibm.com>2018-03-07 01:10:03 -0600
committerDeepak Kodihalli <dkodihal@in.ibm.com>2018-04-09 22:32:23 -0500
commit6aa24d4406bf1675f846d418b79b6616e61ae4bd (patch)
treea9f71280b6a399f7d658098fbb4baf2ef21e15db
parentc1cece76a0d0054b705a7f05c8500fecdfb8c5e8 (diff)
downloadphosphor-hwmon-6aa24d4406bf1675f846d418b79b6616e61ae4bd.tar.gz
phosphor-hwmon-6aa24d4406bf1675f846d418b79b6616e61ae4bd.zip
Add a Timer class
The class provides for a timer, callback invocation on timer expiry, and timer control/cleanup. This will be used in subsequent commits. Change-Id: Ieb04e5ec76a1023efa2c3f5c5b88f03e9819c3eb Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
-rw-r--r--Makefile.am3
-rw-r--r--timer.cpp68
-rw-r--r--timer.hpp108
3 files changed, 178 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index aaa55bf..932e4e2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,6 +23,7 @@ libhwmon_la_SOURCES = \
sysfs.cpp \
env.cpp \
fan_speed.cpp \
- fan_pwm.cpp
+ fan_pwm.cpp \
+ timer.cpp
SUBDIRS = . test msl
diff --git a/timer.cpp b/timer.cpp
new file mode 100644
index 0000000..973b012
--- /dev/null
+++ b/timer.cpp
@@ -0,0 +1,68 @@
+#include <chrono>
+#include <system_error>
+#include <string.h>
+#include "timer.hpp"
+
+namespace phosphor
+{
+namespace hwmon
+{
+
+static std::chrono::microseconds getTime()
+{
+ using namespace std::chrono;
+ auto usec = steady_clock::now().time_since_epoch();
+ return duration_cast<microseconds>(usec);
+}
+
+Timer::Timer(sd_event* event,
+ std::function<void()> callback,
+ std::chrono::microseconds usec,
+ timer::Action action):
+ event(event),
+ callback(callback),
+ duration(usec),
+ action(action)
+{
+ auto r = sd_event_add_time(event, &eventSource,
+ CLOCK_MONOTONIC, // Time base
+ (getTime() + usec).count(), // When to fire
+ 0, // Use default event accuracy
+ timeoutHandler, // Callback handler on timeout
+ this); // User data
+ if (r < 0)
+ {
+ throw std::system_error(r, std::generic_category(), strerror(-r));
+ }
+}
+
+int Timer::timeoutHandler(sd_event_source* eventSource,
+ uint64_t usec, void* userData)
+{
+ auto timer = static_cast<Timer*>(userData);
+
+ if (timer->getAction() == timer::ON)
+ {
+ auto r = sd_event_source_set_time(
+ eventSource, (getTime() + timer->getDuration()).count());
+ if (r < 0)
+ {
+ throw std::system_error(r, std::generic_category(), strerror(-r));
+ }
+ r = sd_event_source_set_enabled(eventSource, timer::ON);
+ if (r < 0)
+ {
+ throw std::system_error(r, std::generic_category(), strerror(-r));
+ }
+ }
+
+ if(timer->callback)
+ {
+ timer->callback();
+ }
+
+ return 0;
+}
+
+} // namespace hwmon
+} // namespace phosphor
diff --git a/timer.hpp b/timer.hpp
new file mode 100644
index 0000000..bb1d6e9
--- /dev/null
+++ b/timer.hpp
@@ -0,0 +1,108 @@
+#pragma once
+
+#include <chrono>
+#include <functional>
+#include <systemd/sd-event.h>
+
+namespace phosphor
+{
+namespace hwmon
+{
+namespace timer
+{
+
+enum Action
+{
+ OFF = SD_EVENT_OFF,
+ ON = SD_EVENT_ON,
+ ONESHOT = SD_EVENT_ONESHOT
+};
+
+}
+
+/** @class Timer
+ * @brief Provides a timer source and a mechanism to callback when the timer
+ * expires.
+ *
+ * The timer is armed upon construction. The constructor requires a timeout
+ * handler function, the timer expiry duration, and the timer state (one-shot,
+ * repetitive, disabled).
+ * It's possible to change the state of the timer after it's been armed via the
+ * state() API.
+ */
+class Timer
+{
+ public:
+ Timer() = delete;
+ Timer(const Timer&) = delete;
+ Timer& operator=(const Timer&) = delete;
+ Timer(Timer&&) = delete;
+ Timer& operator=(Timer&&) = delete;
+
+ /** @brief Constructs timer object
+ *
+ * @param[in] events - sd_event pointer
+ * @param[in] callback - function callback for timer expiry
+ * @param[in] usec - timer duration, in micro seconds
+ * @param[in] action - controls the timer's lifetime
+ */
+ Timer(sd_event* event,
+ std::function<void()> userCallback,
+ std::chrono::microseconds usec,
+ timer::Action action);
+
+ ~Timer()
+ {
+ if (eventSource)
+ {
+ eventSource = sd_event_source_unref(eventSource);
+ }
+ }
+
+ /** @brief Timer expiry handler - invokes callback
+ *
+ * @param[in] eventSource - Source of the event
+ * @param[in] usec - time in micro seconds
+ * @param[in] userData - User data pointer
+ *
+ */
+ static int timeoutHandler(sd_event_source* eventSource,
+ uint64_t usec, void* userData);
+
+ /** @brief Enables / disables the timer
+ * @param[in] action - controls the timer's lifetime
+ */
+ int state(timer::Action action)
+ {
+ return sd_event_source_set_enabled(eventSource, action);
+ }
+
+ timer::Action getAction() const
+ {
+ return action;
+ }
+
+ std::chrono::microseconds getDuration() const
+ {
+ return duration;
+ }
+
+ private:
+ /** @brief the sd_event structure */
+ sd_event* event = nullptr;
+
+ /** @brief Source of events */
+ sd_event_source* eventSource = nullptr;
+
+ /** @brief Optional function to call on timer expiration */
+ std::function<void()> callback{};
+
+ /** @brief Duration of the timer */
+ std::chrono::microseconds duration{};
+
+ /** @brief whether the timer is enabled/disabled/one-shot */
+ timer::Action action = timer::OFF;
+};
+
+} // namespace hwmon
+} // namespace phosphor
OpenPOWER on IntegriCloud