1 #pragma once 2 3 #include <systemd/sd-event.h> 4 5 #include <sdeventplus/internal/sdevent.hpp> 6 #include <sdeventplus/types.hpp> 7 #include <stdplus/handle/copyable.hpp> 8 9 #include <optional> 10 11 namespace sdeventplus 12 { 13 14 /** @class Event 15 * @brief C++ Wrapper around sd_event objects 16 */ 17 class Event 18 { 19 public: 20 /** @brief Duration type used for specifying timeouts 21 */ 22 using Timeout = SdEventDuration; 23 using MaybeTimeout = std::optional<Timeout>; 24 25 /** @brief Constructs a new event from sd_event 26 * Takes a reference on the passed in sd_event 27 * 28 * @param[in] event - The sd_event to wrap 29 * @param[in] sdevent - Optional underlying sd_event implementation 30 * @throws SdEventError for underlying sd_event errors 31 */ 32 Event(sd_event* event, 33 const internal::SdEvent* sdevent = &internal::sdevent_impl); 34 35 /** @brief Constructs a new event from sd_event 36 * Does not take a reference on the passed in sd_event 37 * @note This will still take a reference during future copies 38 * Useful for first creation of an sd_event 39 * 40 * @param[in] event - The sd_event to wrap 41 * @param[in] - Denotes no reference taken during construction 42 * @param[in] sdevent - Optional underlying sd_event implementation 43 * @throws SdEventError for underlying sd_event errors 44 */ 45 Event(sd_event* event, std::false_type, 46 const internal::SdEvent* sdevent = &internal::sdevent_impl); 47 48 /** @brief Constructs a new non-owning event from an event 49 * Does not take a reference on the passed in sd_event 50 * Does not release the reference it is given 51 * @note This will still take a reference during future copies 52 * @internal 53 * 54 * @param[in] other - The other Event to copy 55 * @param[in] - Denotes no reference taken or release 56 */ 57 Event(const Event& other, sdeventplus::internal::NoOwn); 58 59 /** @brief Create a wrapped event around sd_event_new() 60 * 61 * @param[in] sdevent - Optional underlying sd_event implementation 62 * @throws SdEventError for underlying sd_event errors 63 * @return A new Event 64 */ 65 static Event 66 get_new(const internal::SdEvent* sdevent = &internal::sdevent_impl); 67 68 /** @brief Create a wrapped event around sd_event_default() 69 * 70 * @param[in] sdevent - Optional underlying sd_event implementation 71 * @throws SdEventError for underlying sd_event errors 72 * @return A new default Event 73 */ 74 static Event 75 get_default(const internal::SdEvent* sdevent = &internal::sdevent_impl); 76 77 /** @brief Get the underlying sd_event 78 * 79 * @return The sd_event 80 */ 81 sd_event* get() const; 82 83 /** @brief Get the sd_event interface in use 84 * 85 * @return The sd_event interface 86 */ 87 const internal::SdEvent* getSdEvent() const; 88 89 /** @brief Check for pending events and arm timers 90 * 91 * @throws SdEventError for underlying sd_event errors 92 * @return Positive value if events are pending, 0 otherwise 93 */ 94 int prepare() const; 95 96 /** @brief Waits for new events to process 97 * 98 * @param[in] timeout - nullopt for no timeout or a finite timeout 99 * @throws SdEventError for underlying sd_event errors 100 * @return Positive value if events are pending, 0 otherwise 101 * Only returns 0 a finite timeout is reached 102 */ 103 int wait(MaybeTimeout timeout) const; 104 105 /** @brief Executes the highest priority event 106 * 107 * @throws SdEventError for underlying sd_event errors 108 * @return Positive value if the event loop should continue 109 * 0 value if the event loop should exit 110 */ 111 int dispatch() const; 112 113 /** @brief Runs a single iteration of the event loop 114 * 115 * @param[in] timeout - nullopt for no timeout or a finite timeout 116 * @throws SdEventError for underlying sd_event errors 117 * @return Positive value if an event was dispatched 118 * Only returns 0 a finite timeout is reached 119 */ 120 int run(MaybeTimeout timeout) const; 121 122 /** @brief Run the event loop to completion 123 * 124 * @throws SdEventError for underlying sd_event errors 125 * @return Exit status of the event loop from exit() 126 */ 127 int loop() const; 128 129 /** @brief Sets the exit code for the loop and notifies 130 * the event loop it should terminate 131 * 132 * @param[in] code - The exit code 133 * @throws SdEventError for underlying sd_event errors 134 */ 135 void exit(int code) const; 136 137 /** @brief Gets the exit code for the event loop 138 * 139 * @throws SdEventError for underlying sd_event errors 140 * @return The exit code specified by a previous exit() 141 */ 142 int get_exit_code() const; 143 144 /** @brief Get the status of the event loop watchdog 145 * 146 * @throws SdEventError for underlying sd_event errors 147 * @return 'true' if the watchdog is supported and enabled 148 * 'false' otherwise 149 */ 150 bool get_watchdog() const; 151 152 /** @brief Sets the state of the event loop watchdog 153 * 154 * @param[in] b - Should the event loop attempt to enable the watchdog 155 * @throws SdEventError for underlying sd_event errors 156 * @return 'true' if the watchdog is supported and enabled 157 * 'false' otherwise 158 */ 159 bool set_watchdog(bool b) const; 160 161 private: 162 static sd_event* ref(sd_event* const& event, 163 const internal::SdEvent*& sdevent, bool& owned); 164 static void drop(sd_event*&& event, const internal::SdEvent*& sdevent, 165 bool& owned); 166 167 const internal::SdEvent* sdevent; 168 stdplus::Copyable<sd_event*, const internal::SdEvent*, bool>::Handle<drop, 169 ref> 170 event; 171 }; 172 173 } // namespace sdeventplus 174