blob: 9f04dd0fb86a346aa5c046f432c4532350476d8e [file] [log] [blame]
Brad Bishop14631dc2017-06-14 22:34:03 -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{
Brad Bishope54a98f2017-06-14 23:10:37 -040014namespace io
15{
16class IO;
17} // namespace io
Brad Bishop14631dc2017-06-14 22:34:03 -040018
19using EventPtr = sd_event*;
20class Event;
21
22/** @brief Get an instance of the 'default' event. */
23Event newDefault();
24
25namespace details
26{
27
28/** @brief unique_ptr functor to release an event reference. */
29struct EventDeleter
30{
31 void operator()(sd_event* ptr) const
32 {
33 deleter(ptr);
34 }
35
36 decltype(&sd_event_unref) deleter = sd_event_unref;
37};
38
39/* @brief Alias 'event' to a unique_ptr type for auto-release. */
40using Event = std::unique_ptr<sd_event, EventDeleter>;
41
42} // namespace details
43
44/** @class Event
45 * @brief Provides C++ bindings to the sd_event_* class functions.
46 */
47class Event
48{
49 public:
50 /* Define all of the basic class operations:
51 * Not allowed:
52 * - Default constructor to avoid nullptrs.
53 * - Copy operations due to internal unique_ptr.
54 * Allowed:
55 * - Move operations.
56 * - Destructor.
57 */
58 Event() = delete;
59 Event(const Event&) = delete;
60 Event& operator=(const Event&) = delete;
61 Event(Event&&) = default;
62 Event& operator=(Event&&) = default;
63 ~Event() = default;
64
65 /** @brief Conversion constructor from 'EventPtr'.
66 *
67 * Increments ref-count of the event-pointer and releases it when
68 * done.
69 */
70 explicit Event(EventPtr e);
71
72 /** @brief Constructor for 'Event'.
73 *
74 * Takes ownership of the event-pointer and releases it when done.
75 */
76 Event(EventPtr e, std::false_type);
77
78 /** @brief Release ownership of the stored event-pointer. */
79 EventPtr release()
80 {
81 return evt.release();
82 }
83
84 /** @brief Wait indefinitely for new event sources. */
85 void loop()
86 {
87 sd_event_loop(evt.get());
88 }
89
Brad Bishop0c9271f2017-06-15 22:30:15 -040090 /** @brief Stop the loop. */
91 void exit(int status = 0)
92 {
93 auto rc = sd_event_exit(evt.get(), status);
94 if (rc < 0)
95 {
96 phosphor::logging::elog<InternalFailure>();
97 }
98 }
99
100 /** @brief Get the loop exit code. */
101 auto getExitStatus()
102 {
103 int status;
104 auto rc = sd_event_get_exit_code(evt.get(), &status);
105 if (rc < 0)
106 {
107 phosphor::logging::elog<InternalFailure>();
108 }
109
110 return status;
111 }
112
Brad Bishop14631dc2017-06-14 22:34:03 -0400113 /** @brief Attach to a DBus loop. */
114 void attach(sdbusplus::bus::bus& bus)
115 {
116 bus.attach_event(evt.get(), SD_EVENT_PRIORITY_NORMAL);
117 }
118
119 /** @brief C++ wrapper for sd_event_now. */
120 auto now()
121 {
122 using namespace std::chrono;
123
124 uint64_t usec;
125 sd_event_now(evt.get(), CLOCK_MONOTONIC, &usec);
126 microseconds d(usec);
127 return steady_clock::time_point(d);
128 }
129
Brad Bishope54a98f2017-06-14 23:10:37 -0400130 friend class io::IO;
131
Brad Bishop14631dc2017-06-14 22:34:03 -0400132 private:
133
134 EventPtr get()
135 {
136 return evt.get();
137 }
138
139 details::Event evt;
140};
141
142inline Event::Event(EventPtr l) : evt(sd_event_ref(l))
143{
144
145}
146
147inline Event::Event(EventPtr l, std::false_type) : evt(l)
148{
149
150}
151
152inline Event newDefault()
153{
154 sd_event* e = nullptr;
155 sd_event_default(&e);
156 return Event(e, std::false_type());
157}
158
159} // namespace event
160} // namespace sdevent