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