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 // Base sources cannot be directly constructed. 118 Base(const Event& event, sd_event_source* source); 119 Base(const Event& event, sd_event_source* source, std::false_type); 120 121 // We can't ever copy an event_source because the callback 122 // data has to be unique. 123 Base(const Base& other) = delete; 124 Base& operator=(const Base& other) = delete; 125 // We don't want to allow any kind of slicing. 126 Base(Base&& other); 127 Base& operator=(Base&& other); 128 129 const Callback& get_prepare() const; 130 131 template <typename Callback, class Source, 132 const Callback& (Source::*getter)() const, typename... Args> 133 static int sourceCallback(const char* name, sd_event_source*, 134 void* userdata, Args... args) 135 { 136 if (userdata == nullptr) 137 { 138 fprintf(stderr, "sdeventplus: %s: Missing userdata\n", name); 139 return -EINVAL; 140 } 141 Source* source = reinterpret_cast<Source*>(userdata); 142 return internal::performCallback(name, (source->*getter)(), 143 std::ref(*source), args...); 144 } 145 146 private: 147 Callback prepare; 148 149 void set_userdata(); 150 static int prepareCallback(sd_event_source* source, void* userdata); 151 }; 152 153 } // namespace source 154 } // namespace sdeventplus 155