blob: 5462202f3f3e6c346ec93a6b86c4d707a066591d [file] [log] [blame]
Brad Bishop605662d2017-05-30 12:39:09 -04001#pragma once
2
3#include <chrono>
4#include <memory>
5#include <sdbusplus/bus.hpp>
6#include <systemd/sd-event.h>
7
8// TODO: openbmc/openbmc#1720 - add error handling for sd_event API failures
9
10namespace sdevent
11{
12namespace event
13{
14namespace timer
15{
16class Timer;
17} // namespace timer
18}
19namespace event
20{
21
22using EventPtr = sd_event*;
23class Event;
24
25/** @brief Get an instance of the 'default' event. */
26Event newDefault();
27
28namespace details
29{
30
31/** @brief unique_ptr functor to release an event reference. */
32struct EventDeleter
33{
34 void operator()(sd_event* ptr) const
35 {
36 deleter(ptr);
37 }
38
39 decltype(&sd_event_unref) deleter = sd_event_unref;
40};
41
42/* @brief Alias 'event' to a unique_ptr type for auto-release. */
43using Event = std::unique_ptr<sd_event, EventDeleter>;
44
45} // namespace details
46
47/** @class Event
48 * @brief Provides C++ bindings to the sd_event_* class functions.
49 */
50class Event
51{
52 public:
53 /* Define all of the basic class operations:
54 * Not allowed:
55 * - Default constructor to avoid nullptrs.
56 * - Copy operations due to internal unique_ptr.
57 * Allowed:
58 * - Move operations.
59 * - Destructor.
60 */
61 Event() = delete;
62 Event(const Event&) = delete;
63 Event& operator=(const Event&) = delete;
64 Event(Event&&) = default;
65 Event& operator=(Event&&) = default;
66 ~Event() = default;
67
68 /** @brief Conversion constructor from 'EventPtr'.
69 *
70 * Increments ref-count of the event-pointer and releases it when
71 * done.
72 */
73 explicit Event(EventPtr e);
74
75 /** @brief Constructor for 'Event'.
76 *
77 * Takes ownership of the event-pointer and releases it when done.
78 */
79 Event(EventPtr e, std::false_type);
80
81 /** @brief Release ownership of the stored event-pointer. */
82 EventPtr release()
83 {
84 return evt.release();
85 }
86
87 /** @brief Wait indefinitely for new event sources. */
88 void loop()
89 {
90 sd_event_loop(evt.get());
91 }
92
93 /** @brief Attach to a DBus loop. */
94 void attach(sdbusplus::bus::bus& bus)
95 {
96 bus.attach_event(evt.get(), SD_EVENT_PRIORITY_NORMAL);
97 }
98
99 /** @brief C++ wrapper for sd_event_now. */
100 auto now()
101 {
102 using namespace std::chrono;
103
104 uint64_t usec;
105 sd_event_now(evt.get(), CLOCK_MONOTONIC, &usec);
106 microseconds d(usec);
107 return steady_clock::time_point(d);
108 }
109
110 friend class timer::Timer;
111
112 private:
113
114 EventPtr get()
115 {
116 return evt.get();
117 }
118
119 details::Event evt;
120};
121
122inline Event::Event(EventPtr l) : evt(sd_event_ref(l))
123{
124
125}
126
127inline Event::Event(EventPtr l, std::false_type) : evt(l)
128{
129
130}
131
132inline Event newDefault()
133{
134 sd_event* e = nullptr;
135 sd_event_default(&e);
136 return Event(e, std::false_type());
137}
138
139} // namespace event
140} // namespace sdevent