blob: 405da4e01f6ae5e2ae0fbd0cf09908f27125c42e [file] [log] [blame]
Brad Bishop605662d2017-05-30 12:39:09 -04001#pragma once
2
Patrick Venture3d6d3182018-08-31 09:33:09 -07003#include "sdevent/event.hpp"
4#include "sdevent/source.hpp"
5
6#include <systemd/sd-event.h>
7
Brad Bishop605662d2017-05-30 12:39:09 -04008#include <chrono>
9#include <functional>
10#include <memory>
Brad Bishop605662d2017-05-30 12:39:09 -040011
12// TODO: openbmc/openbmc#1720 - add error handling for sd_event API failures
13
14namespace sdevent
15{
16namespace event
17{
18namespace timer
19{
20
21/** @class Timer
22 * @brief Provides C++ bindings to the sd_event_source* timer functions.
23 */
24class Timer
25{
Brad Bishopd1eac882018-03-29 10:34:05 -040026 public:
27 /* Define all of the basic class operations:
28 * Not allowed:
29 * - Default constructor to avoid nullptrs.
30 * - Copy operations due to internal unique_ptr.
31 * Allowed:
32 * - Move operations.
33 * - Destructor.
34 */
35 Timer() = delete;
36 Timer(const Timer&) = delete;
37 Timer& operator=(const Timer&) = delete;
38 Timer(Timer&&) = default;
39 Timer& operator=(Timer&&) = default;
40 ~Timer() = default;
Brad Bishop605662d2017-05-30 12:39:09 -040041
Brad Bishopd1eac882018-03-29 10:34:05 -040042 using Callback = std::function<void(source::Source&)>;
Brad Bishop605662d2017-05-30 12:39:09 -040043
Brad Bishopd1eac882018-03-29 10:34:05 -040044 /** @brief Register a timer callback.
45 *
46 * @param[in] event - The event to register on.
47 * @param[in] expires - The initial timer expiration time.
48 * @param[in] callback - The callback method.
49 */
50 Timer(sdevent::event::Event& event,
51 const std::chrono::steady_clock::time_point& expires,
52 Callback callback) :
53 src(nullptr),
54 cb(std::make_unique<Callback>(std::move(callback)))
55 {
56 using namespace std::chrono;
57 auto epoch = expires.time_since_epoch();
58 auto time = duration_cast<microseconds>(epoch);
59 sd_event_source* source = nullptr;
60 sd_event_add_time(event.get(), &source, CLOCK_MONOTONIC, time.count(),
61 0, callCallback, cb.get());
62 // **INDENT-OFF**
63 src = decltype(src){source, std::false_type()};
64 // **INDENT-ON**
65 }
Brad Bishop605662d2017-05-30 12:39:09 -040066
Brad Bishopd1eac882018-03-29 10:34:05 -040067 /** @brief Register a disabled timer callback.
68 *
69 * @param[in] event - The event to register on.
70 * @param[in] callback - The callback method.
71 */
72 Timer(sdevent::event::Event& event, Callback callback) :
73 src(nullptr), cb(std::make_unique<Callback>(std::move(callback)))
74 {
75 sd_event_source* source = nullptr;
76 sd_event_add_time(event.get(), &source, CLOCK_MONOTONIC, ULLONG_MAX, 0,
77 callCallback, cb.get());
78 // **INDENT-OFF**
79 src = decltype(src){source, std::false_type()};
80 // **INDENT-ON**
81 }
Brad Bishop605662d2017-05-30 12:39:09 -040082
Brad Bishopd1eac882018-03-29 10:34:05 -040083 /** @brief Set the timer expiration time. */
84 void setTime(const std::chrono::steady_clock::time_point& expires)
85 {
86 src.setTime(expires);
87 }
Brad Bishop605662d2017-05-30 12:39:09 -040088
Brad Bishopd1eac882018-03-29 10:34:05 -040089 /** @brief Get the timer expiration time. */
90 auto getTime()
91 {
92 return src.getTime();
93 }
Brad Bishop605662d2017-05-30 12:39:09 -040094
Brad Bishopd1eac882018-03-29 10:34:05 -040095 /** @brief Set the timer source enable state. */
96 void enable(int enable)
97 {
98 src.enable(enable);
99 }
Brad Bishop605662d2017-05-30 12:39:09 -0400100
Brad Bishopd1eac882018-03-29 10:34:05 -0400101 /** @brief Query timer state. */
102 auto enabled()
103 {
104 return src.enabled();
105 }
Brad Bishop605662d2017-05-30 12:39:09 -0400106
Brad Bishopd1eac882018-03-29 10:34:05 -0400107 private:
108 source::Source src;
109 std::unique_ptr<Callback> cb = nullptr;
Brad Bishop605662d2017-05-30 12:39:09 -0400110
Brad Bishopd1eac882018-03-29 10:34:05 -0400111 static int callCallback(sd_event_source* s, uint64_t usec, void* context)
112 {
113 source::Source source(s);
114 auto c = static_cast<Callback*>(context);
115 (*c)(source);
Brad Bishop605662d2017-05-30 12:39:09 -0400116
Brad Bishopd1eac882018-03-29 10:34:05 -0400117 return 0;
118 }
Brad Bishop605662d2017-05-30 12:39:09 -0400119};
120} // namespace timer
121} // namespace event
122} // namespace sdevent