diff options
author | Deepak Kodihalli <dkodihal@in.ibm.com> | 2018-03-07 01:10:03 -0600 |
---|---|---|
committer | Deepak Kodihalli <dkodihal@in.ibm.com> | 2018-04-09 22:32:23 -0500 |
commit | 6aa24d4406bf1675f846d418b79b6616e61ae4bd (patch) | |
tree | a9f71280b6a399f7d658098fbb4baf2ef21e15db | |
parent | c1cece76a0d0054b705a7f05c8500fecdfb8c5e8 (diff) | |
download | phosphor-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.am | 3 | ||||
-rw-r--r-- | timer.cpp | 68 | ||||
-rw-r--r-- | timer.hpp | 108 |
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 |