1 #pragma once
2 
3 #include <systemd/sd-event.h>
4 
5 #include <function2/function2.hpp>
6 #include <sdeventplus/internal/sdevent.hpp>
7 #include <sdeventplus/source/base.hpp>
8 #include <sdeventplus/types.hpp>
9 
10 #include <type_traits>
11 
12 namespace sdeventplus
13 {
14 namespace source
15 {
16 
17 namespace detail
18 {
19 class EventBaseData;
20 } // namespace detail
21 
22 /** @class EventBase
23  *  @brief A wrapper around the sd_event_source defer type
24  *         See sd_event_add_defer(3) for more information
25  *         There are multiple types of defer sources, instantiate
26  *         Defer, Post, or Exit depending on the required event.
27  */
28 class EventBase : public Base
29 {
30   public:
31     using Callback = fu2::unique_function<void(EventBase& source)>;
32 
33     /** @brief Sets the callback
34      *
35      *  @param[in] callback - The function executed on event dispatch
36      */
37     void set_callback(Callback&& callback);
38 
39     /** @brief Constructs a non-owning event source handler
40      *         Does not own the passed reference to the source because
41      *         this is meant to be used only as a reference inside an event
42      *         source.
43      *  @internal
44      *
45      *  @param[in] other - The source wrapper to copy
46      *  @param[in]       - Signifies that this new copy is non-owning
47      */
48     EventBase(const EventBase& other, sdeventplus::internal::NoOwn);
49 
50   protected:
51     using CreateFunc = decltype(&internal::SdEvent::sd_event_add_exit);
52 
53     /** @brief Adds a new event source handler to the Event
54      *         This type of source defaults to Enabled::Oneshot, and needs to be
55      *         reconfigured upon each callback.
56      *
57      *  @param[in] name   - The name identifying the create function
58      *  @param[in] create - The SdEvent function called to create the source
59      *  @param[in] event  - The event to attach the handler
60      *  @param[in] callback - The function executed on event dispatch
61      */
62     EventBase(const char* name, CreateFunc create, const Event& event,
63               Callback&& callback);
64 
65   private:
66     /** @brief Returns a reference to the source owned event
67      *
68      *  @return A reference to the event
69      */
70     detail::EventBaseData& get_userdata() const;
71 
72     /** @brief Returns a reference to the callback executed for this source
73      *
74      *  @return A reference to the callback
75      */
76     Callback& get_callback();
77 
78     /** @brief Creates a new source attached to the Event
79      *
80      *  @param[in] name   - The name identifying the create function
81      *  @param[in] create - The SdEvent function called to create the source
82      *  @param[in] event  - The event to attach the handler
83      *  @throws SdEventError for underlying sd_event errors
84      *  @return A new sd_event_source
85      */
86     static sd_event_source* create_source(const char* name, CreateFunc create,
87                                           const Event& event);
88 
89     /** @brief A wrapper around the callback that can be called from sd-event
90      *
91      *  @param[in] source   - The sd_event_source associated with the call
92      *  @param[in] userdata - The provided userdata for the source
93      *  @return 0 on success or a negative errno otherwise
94      */
95     static int eventCallback(sd_event_source* source, void* userdata);
96 };
97 
98 namespace detail
99 {
100 
101 class EventBaseData : public EventBase, public BaseData
102 {
103   private:
104     EventBase::Callback callback;
105 
106   public:
107     EventBaseData(const EventBase& base, EventBase::Callback&& callback);
108 
109     friend EventBase;
110 };
111 
112 } // namespace detail
113 
114 class Defer : public EventBase
115 {
116   public:
117     /** @brief Adds a new defer source handler to the Event
118      *         Executes the callback upon events occurring
119      *
120      *  @param[in] event  - The event to attach the handler
121      *  @param[in] callback - The function executed on event dispatch
122      *  @throws SdEventError for underlying sd_event errors
123      */
124     Defer(const Event& event, Callback&& Callback);
125 };
126 
127 class Post : public EventBase
128 {
129   public:
130     /** @brief Adds a new post source handler to the Event
131      *         Executes the callback upon events occurring
132      *
133      *  @param[in] event  - The event to attach the handler
134      *  @param[in] callback - The function executed on event dispatch
135      *  @throws SdEventError for underlying sd_event errors
136      */
137     Post(const Event& event, Callback&& callback);
138 };
139 
140 class Exit : public EventBase
141 {
142   public:
143     /** @brief Adds a new exit source handler to the Event
144      *         Executes the callback upon events occurring
145      *
146      *  @param[in] event  - The event to attach the handler
147      *  @param[in] callback - The function executed on event dispatch
148      *  @throws SdEventError for underlying sd_event errors
149      */
150     Exit(const Event& event, Callback&& callback);
151 };
152 
153 } // namespace source
154 } // namespace sdeventplus
155