1 #pragma once 2 3 #include <cerrno> 4 #include <cstdint> 5 #include <cstdio> 6 #include <functional> 7 #include <sdeventplus/event.hpp> 8 #include <sdeventplus/internal/sdref.hpp> 9 #include <sdeventplus/internal/utils.hpp> 10 #include <systemd/sd-bus.h> 11 #include <type_traits> 12 13 namespace sdeventplus 14 { 15 namespace source 16 { 17 18 /** @class Enabled 19 * @brief Mapping of sdeventplus source enable values to the sd-event 20 * equivalent 21 */ 22 enum class Enabled 23 { 24 Off = SD_EVENT_OFF, 25 On = SD_EVENT_ON, 26 OneShot = SD_EVENT_ONESHOT, 27 }; 28 29 /** @class Base 30 * @brief The base class for all sources implementing common source methods 31 * Not instantiated directly by end users 32 */ 33 class Base 34 { 35 public: 36 using Callback = std::function<void(Base& source)>; 37 38 virtual ~Base(); 39 40 /** @brief Gets the underlying sd_event_source 41 * 42 * @return The sd_event_source 43 */ 44 sd_event_source* get() const; 45 46 /** @brief Gets the associated Event object 47 * 48 * @return The Event 49 */ 50 const Event& get_event() const; 51 52 /** @brief Gets the description of the source 53 * 54 * @throws SdEventError for underlying sd_event errors 55 * @return The c-string description or a nullptr if none exists 56 */ 57 const char* get_description() const; 58 59 /** @brief Sets the description of the source 60 * 61 * @param[in] description - The c-string description 62 * @throws SdEventError for underlying sd_event errors 63 */ 64 void set_description(const char* description) const; 65 66 /** @brief Sets the callback associated with the source to be performed 67 * before the event loop goes to sleep, waiting for new events 68 * 69 * @param[in] callback - Function run for preparation of the source 70 * @throws SdEventError for underlying sd_event errors 71 */ 72 void set_prepare(Callback&& callback); 73 74 /** @brief Whether or not the source has any pending events that have 75 * not been dispatched yet. 76 * 77 * @throws SdEventError for underlying sd_event errors 78 * @return 'true' if the source has pending events 79 * 'false' otherwise 80 */ 81 bool get_pending() const; 82 83 /** @brief Gets the priority of the source relative to other sources 84 * The lower the priority the more important the source 85 * 86 * @throws SdEventError for underlying sd_event errors 87 * @return A 64 bit integer representing the dispatch priority 88 */ 89 int64_t get_priority() const; 90 91 /** @brief Sets the priority of the source relative to other sources 92 * The lower the priority the more important the source 93 * 94 * @param[in] priority - A 64 bit integer representing the priority 95 * @throws SdEventError for underlying sd_event errors 96 */ 97 void set_priority(int64_t priority) const; 98 99 /** @brief Determines the enablement value of the source 100 * 101 * @throws SdEventError for underlying sd_event errors 102 * @return The enabled status of the source 103 */ 104 Enabled get_enabled() const; 105 106 /** @brief Sets the enablement value of the source 107 * 108 * @param[in] enabled - The new state of the source 109 * @throws SdEventError for underlying sd_event errors 110 */ 111 void set_enabled(Enabled enabled) const; 112 113 protected: 114 Event event; 115 internal::SdRef<sd_event_source> source; 116 117 /** @brief Constructs a basic event source wrapper 118 * Adds a reference to the source 119 * 120 * @param[in] event - The event associated with the source 121 * @param[in] source - The underlying sd_event_source wrapped 122 * @throws SdEventError for underlying sd_event errors 123 */ 124 Base(const Event& event, sd_event_source* source); 125 126 /** @brief Constructs a basic event source wrapper 127 * Owns the passed reference to the source 128 * This ownership is exception safe and will properly free the 129 * source in the case of an exception during construction 130 * 131 * @param[in] event - The event associated with the source 132 * @param[in] source - The underlying sd_event_source wrapped 133 * @throws SdEventError for underlying sd_event errors 134 */ 135 Base(const Event& event, sd_event_source* source, std::false_type); 136 137 // We can't ever copy an event_source because the callback 138 // data has to be unique. 139 Base(const Base& other) = delete; 140 Base& operator=(const Base& other) = delete; 141 // We don't want to allow any kind of slicing. 142 Base(Base&& other); 143 Base& operator=(Base&& other); 144 145 /** @brief Returns a reference to the prepare callback executed for this 146 * source 147 * 148 * @return A reference to the callback, this should be checked to make sure 149 * the callback is valid as there is no guarantee 150 */ 151 const Callback& get_prepare() const; 152 153 /** @brief A helper for subclasses to trivially wrap a c++ style callback 154 * to be called from the sd-event c library 155 * 156 * @param[in] name - The name of the callback for use in error messages 157 * @param[in] source - The sd_event_source provided by sd-event 158 * @param[in] userdata - The userdata provided by sd-event 159 * @param[in] args... - Extra arguments to pass to the callaback 160 * @return An negative errno on error, or 0 on success 161 */ 162 template <typename Callback, class Source, 163 const Callback& (Source::*getter)() const, typename... Args> 164 static int sourceCallback(const char* name, sd_event_source*, 165 void* userdata, Args... args) 166 { 167 if (userdata == nullptr) 168 { 169 fprintf(stderr, "sdeventplus: %s: Missing userdata\n", name); 170 return -EINVAL; 171 } 172 Source* source = reinterpret_cast<Source*>(userdata); 173 return internal::performCallback(name, (source->*getter)(), 174 std::ref(*source), args...); 175 } 176 177 private: 178 Callback prepare; 179 180 /** @brief A helper used to make sure the userdata for the sd-event 181 * callback is set to the current source c++ object 182 * 183 * @throws SdEventError for underlying sd_event errors 184 */ 185 void set_userdata(); 186 187 /** @brief A wrapper around the callback that can be called from sd-event 188 * 189 * @param[in] source - The sd_event_source associated with the call 190 * @param[in] userdata - The provided userdata for the source 191 * @return 0 on success or a negative errno otherwise 192 */ 193 static int prepareCallback(sd_event_source* source, void* userdata); 194 }; 195 196 } // namespace source 197 } // namespace sdeventplus 198