blob: 863e725672b1fcf9ebc88a4e6f1e8e547194cfb9 [file] [log] [blame]
Brad Bishop605662d2017-05-30 12:39:09 -04001#pragma once
2
3#include <chrono>
4#include <functional>
5#include <memory>
6#include <systemd/sd-event.h>
7
8#include "sdevent/source.hpp"
9#include "sdevent/event.hpp"
10
11// TODO: openbmc/openbmc#1720 - add error handling for sd_event API failures
12
13namespace sdevent
14{
15namespace event
16{
17namespace timer
18{
19
20/** @class Timer
21 * @brief Provides C++ bindings to the sd_event_source* timer functions.
22 */
23class Timer
24{
25 public:
26 /* Define all of the basic class operations:
27 * Not allowed:
28 * - Default constructor to avoid nullptrs.
29 * - Copy operations due to internal unique_ptr.
30 * Allowed:
31 * - Move operations.
32 * - Destructor.
33 */
34 Timer() = delete;
35 Timer(const Timer&) = delete;
36 Timer& operator=(const Timer&) = delete;
37 Timer(Timer&&) = default;
38 Timer& operator=(Timer&&) = default;
39 ~Timer() = default;
40
41 using Callback = std::function<void(source::Source&)>;
42
43 /** @brief Register a timer callback.
44 *
45 * @param[in] event - The event to register on.
46 * @param[in] expires - The initial timer expiration time.
47 * @param[in] callback - The callback method.
48 */
49 Timer(
50 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(
61 event.get(),
62 &source,
63 CLOCK_MONOTONIC,
64 time.count(),
65 0,
66 callCallback,
67 cb.get());
68// **INDENT-OFF**
69 src = decltype(src){source, std::false_type()};
70// **INDENT-ON**
71 }
72
73 /** @brief Register a disabled timer callback.
74 *
75 * @param[in] event - The event to register on.
76 * @param[in] callback - The callback method.
77 */
78 Timer(
79 sdevent::event::Event& event,
80 Callback callback)
81 : src(nullptr),
82 cb(std::make_unique<Callback>(std::move(callback)))
83 {
84 sd_event_source* source = nullptr;
85 sd_event_add_time(
86 event.get(),
87 &source,
88 CLOCK_MONOTONIC,
89 ULLONG_MAX,
90 0,
91 callCallback,
92 cb.get());
93// **INDENT-OFF**
94 src = decltype(src){source, std::false_type()};
95// **INDENT-ON**
96 }
97
98 /** @brief Set the timer expiration time. */
99 void setTime(
100 const std::chrono::steady_clock::time_point& expires)
101 {
102 src.setTime(expires);
103 }
104
105 /** @brief Get the timer expiration time. */
106 auto getTime()
107 {
108 return src.getTime();
109 }
110
111 /** @brief Set the timer source enable state. */
112 void enable(int enable)
113 {
114 src.enable(enable);
115 }
116
117 /** @brief Query timer state. */
118 auto enabled()
119 {
120 return src.enabled();
121 }
122
123 private:
124 source::Source src;
125 std::unique_ptr<Callback> cb = nullptr;
126
127 static int callCallback(sd_event_source* s, uint64_t usec,
128 void* context)
129 {
130 source::Source source(s);
131 auto c = static_cast<Callback*>(context);
132 (*c)(source);
133
134 return 0;
135 }
136};
137} // namespace timer
138} // namespace event
139} // namespace sdevent