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