diff options
| author | Ratan Gupta <ratagupt@in.ibm.com> | 2017-09-03 18:01:22 +0530 |
|---|---|---|
| committer | Ratan Gupta <ratagupt@in.ibm.com> | 2017-09-13 17:06:10 +0530 |
| commit | 4f80c1a7273a7bfc376d2891d2200022f8b38c50 (patch) | |
| tree | 1edec10196b3b841df462ade9c3903291b5d6522 | |
| parent | 0f9dc1b2c4097b4c54cddfd43bf7f2a24117fec7 (diff) | |
| download | phosphor-networkd-4f80c1a7273a7bfc376d2891d2200022f8b38c50.tar.gz phosphor-networkd-4f80c1a7273a7bfc376d2891d2200022f8b38c50.zip | |
Add the timer class
Usage would be instantiate the timer with the call back
and start the timer with the time.
callback will be called once the timer expires.
Change-Id: I09394264ba18bd90a1c101fc77bc45f7268c5db0
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
| -rw-r--r-- | Makefile.am | 6 | ||||
| -rw-r--r-- | timer.cpp | 127 | ||||
| -rw-r--r-- | timer.hpp | 99 |
3 files changed, 230 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index aacb465..eac5692 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,7 +21,8 @@ noinst_HEADERS = \ system_configuration.hpp \ dhcp_configuration.hpp \ vlan_interface.hpp \ - rtnetlink_server.hpp + rtnetlink_server.hpp \ + timer.hpp phosphor_network_manager_SOURCES = \ ethernet_interface.cpp \ @@ -37,7 +38,8 @@ phosphor_network_manager_SOURCES = \ config_parser.cpp \ dhcp_configuration.cpp \ vlan_interface.cpp \ - rtnetlink_server.cpp + rtnetlink_server.cpp \ + timer.cpp CLEANFILES = \ xyz/openbmc_project/Network/VLAN/Create/server.cpp \ diff --git a/timer.cpp b/timer.cpp new file mode 100644 index 0000000..0aaf7d8 --- /dev/null +++ b/timer.cpp @@ -0,0 +1,127 @@ +#include <chrono> +#include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog-errors.hpp> + +#include "timer.hpp" +#include "xyz/openbmc_project/Common/error.hpp" + +namespace phosphor +{ +namespace network +{ + +using namespace phosphor::logging; +using namespace sdbusplus::xyz::openbmc_project::Common::Error; +// Initializes the timer object +void Timer::initialize() +{ + // This can not be called more than once. + if (eventSource) + { + log<level::ERR>("Timer already initialized"); + elog<InternalFailure>(); + } + + auto r = sd_event_default(&timeEvent); + if (r < 0) + { + log<level::ERR>("Failure in creating the sd_event", + entry("ERROR=%d", r)); + + elog<InternalFailure>(); + } + + // Add infinite expiration time + r = sd_event_add_time(timeEvent, + &eventSource, + CLOCK_MONOTONIC, // Time base + UINT64_MAX, // Expire time - way long time + 0, // Use default event accuracy + timeoutHandler, // Callback handler on timeout + this); // User data + if (r < 0) + { + log<level::ERR>("Failure to set initial expiration time value", + entry("ERROR=%d", r)); + + elog<InternalFailure>(); + } + + // Disable the timer for now + r = setTimer(SD_EVENT_OFF); + if (r < 0) + { + log<level::ERR>("Failure to disable timer", + entry("ERROR=%d", r)); + + elog<InternalFailure>(); + } + return; +} + +/** @brief callback handler on timeout */ +int Timer::timeoutHandler(sd_event_source* eventSource, + uint64_t usec, void* userData) +{ + auto timer = static_cast<Timer*>(userData); + timer->expired = true; + + // Call optional user call back function if available + if (timer->userCallBack) + { + timer->userCallBack(); + } + + log<level::INFO>("Timer expired"); + return 0; +} + +// Gets the time from steady_clock +std::chrono::microseconds Timer::getTime() +{ + using namespace std::chrono; + auto usec = steady_clock::now().time_since_epoch(); + return duration_cast<microseconds>(usec); +} + +// Enables or disables the timer +int Timer::setTimer(int action) +{ + return sd_event_source_set_enabled(eventSource, action); +} + +// Sets the time and arms the timer +int Timer::startTimer(std::chrono::microseconds timeValue) +{ + // Disable the timer + setTimer(SD_EVENT_OFF); + expired = false; + + // Get the current MONOTONIC time and add the delta + auto expireTime = getTime() + timeValue; + + // Set the time + auto r = sd_event_source_set_time(eventSource, expireTime.count()); + if (r < 0) + { + log<level::ERR>("Failure to set timer", + entry("ERROR=%d", r)); + + elog<InternalFailure>(); + } + + // A ONESHOT timer means that when the timer goes off, + // its moves to disabled state. + r = setTimer(SD_EVENT_ONESHOT); + if (r < 0) + { + log<level::ERR>("Failure to start timer", + entry("ERROR=%d", r)); + + elog<InternalFailure>(); + } + return r; +} + +} // namespace network +} // namespace phosphor diff --git a/timer.hpp b/timer.hpp new file mode 100644 index 0000000..408ded4 --- /dev/null +++ b/timer.hpp @@ -0,0 +1,99 @@ +#pragma once + +#include <chrono> +#include <functional> +#include <systemd/sd-event.h> + +namespace phosphor +{ +namespace network +{ + +/** @class Timer + * @brief Usage would be,instantiate the timer with the call back + * and start the timer for the given time. + */ +class Timer +{ + public: + /** @brief Only need the default Timer */ + Timer() = delete; + Timer(const Timer&) = delete; + Timer& operator=(const Timer&) = delete; + Timer(Timer&&) = delete; + Timer& operator=(Timer&&) = delete; + + /** @brief Constructs timer object + * + * @param[in] funcCallBack - optional function callback for timer + * expirations + */ + Timer(std::function<void()> userCallBack = nullptr): + userCallBack(userCallBack) + { + // Initialize the timer + initialize(); + } + + ~Timer() + { + if (eventSource) + { + eventSource = sd_event_source_unref(eventSource); + } + if(timeEvent) + { + timeEvent = sd_event_unref(timeEvent); + } + } + + inline auto isExpired() const + { + return expired; + } + + /** @brief Starts the timer with specified expiration value. + * input is an offset from the current steady_clock + */ + int startTimer(std::chrono::microseconds usec); + + /** @brief Enables / disables the timer */ + int setTimer(int action); + + private: + /** @brief the sd_event structure */ + sd_event* timeEvent = nullptr; + + /** @brief Source of events */ + sd_event_source* eventSource = nullptr; + + bool expired = true; + + /** @brief Initializes the timer object with infinite + * expiration time and sets up the callback handler + * + * @return None. + * + * @error std::runtime exception thrown + */ + void initialize(); + + /** @brief Callback function when timer goes off + * + * @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 Gets the current time from steady clock */ + static std::chrono::microseconds getTime(); + + /** @brief Optional function to call on timer expiration */ + std::function<void()> userCallBack; +}; + +} // namespace network +} // namespace phosphor |

