Support custom callback function on timer expiration
Change-Id: I39b32d608ef342d63c57cbc1902e927fb39861c7
Signed-off-by: Andrew Geissler <andrewg@us.ibm.com>
diff --git a/softoff/test/utest.cpp b/softoff/test/utest.cpp
index a9dae9c..9ffb04e 100644
--- a/softoff/test/utest.cpp
+++ b/softoff/test/utest.cpp
@@ -15,7 +15,7 @@
int rc;
// Source of event
- sd_event_source* eventSource;
+ sd_event_source* eventSource = nullptr;
// Add a Timer Object
Timer timer;
@@ -37,6 +37,51 @@
}
};
+
+class TimerTestCallBack : public ::testing::Test
+{
+ public:
+ // systemd event handler
+ sd_event* events;
+
+ // Need this so that events can be initialized.
+ int rc;
+
+ // Source of event
+ sd_event_source* eventSource = nullptr;
+
+ // Add a Timer Object
+ std::unique_ptr<Timer> timer = nullptr;
+
+ // Indicates optional call back fun was called
+ bool callBackDone = false;
+
+ void callBack()
+ {
+ callBackDone = true;
+ }
+
+ // Gets called as part of each TEST_F construction
+ TimerTestCallBack()
+ : rc(sd_event_default(&events))
+
+ {
+ // Check for successful creation of
+ // event handler and timer object.
+ EXPECT_GE(rc, 0);
+
+ std::function<void()> func(std::bind(
+ &TimerTestCallBack::callBack, this));
+ timer = std::make_unique<Timer>(events, func);
+ }
+
+ // Gets called as part of each TEST_F destruction
+ ~TimerTestCallBack()
+ {
+ events = sd_event_unref(events);
+ }
+};
+
/** @brief Makes sure that timer is expired and the
* callback handler gets invoked post 2 seconds
*/
@@ -162,3 +207,59 @@
// 2 becase of one more count that happens prior to exiting
EXPECT_EQ(2, count);
}
+
+/** @brief Makes sure that optional callback is called */
+TEST_F(TimerTestCallBack, optionalFuncCallBackDone)
+{
+ using namespace std::chrono;
+
+ auto time = duration_cast<microseconds>(seconds(2));
+ EXPECT_GE(timer->startTimer(time), 0);
+
+ // Waiting 2 seconds is enough here since we have
+ // already spent some usec now
+ int count = 0;
+ while(count < 2 && !timer->isExpired())
+ {
+ // Returns -0- on timeout and positive number on dispatch
+ auto sleepTime = duration_cast<microseconds>(seconds(1));
+ if(!sd_event_run(events, sleepTime.count()))
+ {
+ count++;
+ }
+ }
+ EXPECT_EQ(true, timer->isExpired());
+ EXPECT_EQ(true, callBackDone);
+ EXPECT_EQ(1, count);
+}
+
+/** @brief Makes sure that timer is not expired
+ */
+TEST_F(TimerTestCallBack, timerNotExpiredAfter2SecondsNoOptionalCallBack)
+{
+ using namespace std::chrono;
+
+ auto time = duration_cast<microseconds>(seconds(2));
+ EXPECT_GE(timer->startTimer(time), 0);
+
+ // Now turn off the timer post a 1 second sleep
+ sleep(1);
+ EXPECT_GE(timer->setTimer(SD_EVENT_OFF), 0);
+
+ // Wait 2 seconds and see that timer is not expired
+ int count = 0;
+ while(count < 2)
+ {
+ // Returns -0- on timeout
+ auto sleepTime = duration_cast<microseconds>(seconds(1));
+ if(!sd_event_run(events, sleepTime.count()))
+ {
+ count++;
+ }
+ }
+ EXPECT_EQ(false, timer->isExpired());
+ EXPECT_EQ(false, callBackDone);
+
+ // 2 because of one more count that happens prior to exiting
+ EXPECT_EQ(2, count);
+}
diff --git a/softoff/timer.cpp b/softoff/timer.cpp
index c626536..4e8fd9a 100644
--- a/softoff/timer.cpp
+++ b/softoff/timer.cpp
@@ -51,6 +51,12 @@
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;
}
diff --git a/softoff/timer.hpp b/softoff/timer.hpp
index 9d597f8..cbd3444 100644
--- a/softoff/timer.hpp
+++ b/softoff/timer.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <functional>
#include <systemd/sd-event.h>
namespace phosphor
{
@@ -22,9 +23,12 @@
/** @brief Constructs timer object
*
* @param[in] events - sd_event pointer
+ * @param[in] funcCallBack - optional function callback for timer
+ * expirations
*/
- Timer(sd_event* events)
- : timeEvent(events)
+ Timer(sd_event* events,
+ std::function<void()> userCallBack = nullptr)
+ : timeEvent(events), userCallBack(userCallBack)
{
// Initialize the timer
initialize();
@@ -87,6 +91,9 @@
/** @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 ipmi