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