blob: 53776aeb08e9307d06a80f0b7b4f61c19b4f2720 [file] [log] [blame]
Brad Bishop14631dc2017-06-14 22:34:03 -04001#pragma once
2
3#include <chrono>
4#include <memory>
Brad Bishopd516c612017-07-19 16:15:04 -04005#include <phosphor-logging/elog.hpp>
6#include <phosphor-logging/elog-errors.hpp>
Brad Bishop14631dc2017-06-14 22:34:03 -04007#include <sdbusplus/bus.hpp>
8#include <systemd/sd-event.h>
Brad Bishopd516c612017-07-19 16:15:04 -04009#include <xyz/openbmc_project/Common/error.hpp>
Brad Bishop14631dc2017-06-14 22:34:03 -040010
11namespace sdevent
12{
13namespace event
14{
Brad Bishope54a98f2017-06-14 23:10:37 -040015namespace io
16{
17class IO;
18} // namespace io
Brad Bishop14631dc2017-06-14 22:34:03 -040019
20using EventPtr = sd_event*;
21class Event;
22
23/** @brief Get an instance of the 'default' event. */
24Event newDefault();
25
26namespace details
27{
28
29/** @brief unique_ptr functor to release an event reference. */
30struct EventDeleter
31{
32 void operator()(sd_event* ptr) const
33 {
34 deleter(ptr);
35 }
36
37 decltype(&sd_event_unref) deleter = sd_event_unref;
38};
39
40/* @brief Alias 'event' to a unique_ptr type for auto-release. */
41using Event = std::unique_ptr<sd_event, EventDeleter>;
42
43} // namespace details
44
45/** @class Event
46 * @brief Provides C++ bindings to the sd_event_* class functions.
47 */
48class Event
49{
Brad Bishopd516c612017-07-19 16:15:04 -040050 private:
51 using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
52 Error::InternalFailure;
53
Brad Bishop14631dc2017-06-14 22:34:03 -040054 public:
55 /* Define all of the basic class operations:
56 * Not allowed:
57 * - Default constructor to avoid nullptrs.
58 * - Copy operations due to internal unique_ptr.
59 * Allowed:
60 * - Move operations.
61 * - Destructor.
62 */
63 Event() = delete;
64 Event(const Event&) = delete;
65 Event& operator=(const Event&) = delete;
66 Event(Event&&) = default;
67 Event& operator=(Event&&) = default;
68 ~Event() = default;
69
70 /** @brief Conversion constructor from 'EventPtr'.
71 *
72 * Increments ref-count of the event-pointer and releases it when
73 * done.
74 */
75 explicit Event(EventPtr e);
76
77 /** @brief Constructor for 'Event'.
78 *
79 * Takes ownership of the event-pointer and releases it when done.
80 */
81 Event(EventPtr e, std::false_type);
82
83 /** @brief Release ownership of the stored event-pointer. */
84 EventPtr release()
85 {
86 return evt.release();
87 }
88
89 /** @brief Wait indefinitely for new event sources. */
90 void loop()
91 {
Brad Bishopd516c612017-07-19 16:15:04 -040092 auto rc = sd_event_loop(evt.get());
93 if (rc < 0)
94 {
95 phosphor::logging::elog<InternalFailure>();
96 }
Brad Bishop14631dc2017-06-14 22:34:03 -040097 }
98
Brad Bishop0c9271f2017-06-15 22:30:15 -040099 /** @brief Stop the loop. */
100 void exit(int status = 0)
101 {
102 auto rc = sd_event_exit(evt.get(), status);
103 if (rc < 0)
104 {
105 phosphor::logging::elog<InternalFailure>();
106 }
107 }
108
109 /** @brief Get the loop exit code. */
110 auto getExitStatus()
111 {
112 int status;
113 auto rc = sd_event_get_exit_code(evt.get(), &status);
114 if (rc < 0)
115 {
116 phosphor::logging::elog<InternalFailure>();
117 }
118
119 return status;
120 }
121
Brad Bishop14631dc2017-06-14 22:34:03 -0400122 /** @brief Attach to a DBus loop. */
123 void attach(sdbusplus::bus::bus& bus)
124 {
125 bus.attach_event(evt.get(), SD_EVENT_PRIORITY_NORMAL);
126 }
127
128 /** @brief C++ wrapper for sd_event_now. */
129 auto now()
130 {
131 using namespace std::chrono;
132
133 uint64_t usec;
Brad Bishopd516c612017-07-19 16:15:04 -0400134 auto rc = sd_event_now(evt.get(), CLOCK_MONOTONIC, &usec);
135 if (rc < 0)
136 {
137 phosphor::logging::elog<InternalFailure>();
138 }
139
Brad Bishop14631dc2017-06-14 22:34:03 -0400140 microseconds d(usec);
141 return steady_clock::time_point(d);
142 }
143
Brad Bishope54a98f2017-06-14 23:10:37 -0400144 friend class io::IO;
145
Brad Bishop14631dc2017-06-14 22:34:03 -0400146 private:
147
148 EventPtr get()
149 {
150 return evt.get();
151 }
152
153 details::Event evt;
154};
155
156inline Event::Event(EventPtr l) : evt(sd_event_ref(l))
157{
158
159}
160
161inline Event::Event(EventPtr l, std::false_type) : evt(l)
162{
163
164}
165
166inline Event newDefault()
167{
Brad Bishopd516c612017-07-19 16:15:04 -0400168 using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
169 Error::InternalFailure;
170
Brad Bishop14631dc2017-06-14 22:34:03 -0400171 sd_event* e = nullptr;
Brad Bishopd516c612017-07-19 16:15:04 -0400172 auto rc = sd_event_default(&e);
173 if (rc < 0)
174 {
175 phosphor::logging::elog<InternalFailure>();
176 }
177
Brad Bishop14631dc2017-06-14 22:34:03 -0400178 return Event(e, std::false_type());
179}
180
181} // namespace event
182} // namespace sdevent