1 #pragma once
2 
3 #include <cerrno>
4 #include <cstdint>
5 #include <cstdio>
6 #include <functional>
7 #include <sdeventplus/event.hpp>
8 #include <sdeventplus/internal/sdref.hpp>
9 #include <sdeventplus/internal/utils.hpp>
10 #include <systemd/sd-bus.h>
11 #include <type_traits>
12 
13 namespace sdeventplus
14 {
15 namespace source
16 {
17 
18 /** @class Enabled
19  *  @brief Mapping of sdeventplus source enable values to the sd-event
20  *         equivalent
21  */
22 enum class Enabled
23 {
24     Off = SD_EVENT_OFF,
25     On = SD_EVENT_ON,
26     OneShot = SD_EVENT_ONESHOT,
27 };
28 
29 /** @class Base
30  *  @brief The base class for all sources implementing common source methods
31  *         Not instantiated directly by end users
32  */
33 class Base
34 {
35   public:
36     using Callback = std::function<void(Base& source)>;
37 
38     virtual ~Base();
39 
40     /** @brief Gets the underlying sd_event_source
41      *
42      *  @return The sd_event_source
43      */
44     sd_event_source* get() const;
45 
46     /** @brief Gets the associated Event object
47      *
48      *  @return The Event
49      */
50     const Event& get_event() const;
51 
52     /** @brief Gets the description of the source
53      *
54      *  @throws SdEventError for underlying sd_event errors
55      *  @return The c-string description or a nullptr if none exists
56      */
57     const char* get_description() const;
58 
59     /** @brief Sets the description of the source
60      *
61      *  @param[in] description - The c-string description
62      *  @throws SdEventError for underlying sd_event errors
63      */
64     void set_description(const char* description) const;
65 
66     /** @brief Sets the callback associated with the source to be performed
67      *         before the event loop goes to sleep, waiting for new events
68      *
69      *  @param[in] callback - Function run for preparation of the source
70      *  @throws SdEventError for underlying sd_event errors
71      */
72     void set_prepare(Callback&& callback);
73 
74     /** @brief Whether or not the source has any pending events that have
75      *         not been dispatched yet.
76      *
77      *  @throws SdEventError for underlying sd_event errors
78      *  @return 'true' if the source has pending events
79      *          'false' otherwise
80      */
81     bool get_pending() const;
82 
83     /** @brief Gets the priority of the source relative to other sources
84      *         The lower the priority the more important the source
85      *
86      *  @throws SdEventError for underlying sd_event errors
87      *  @return A 64 bit integer representing the dispatch priority
88      */
89     int64_t get_priority() const;
90 
91     /** @brief Sets the priority of the source relative to other sources
92      *         The lower the priority the more important the source
93      *
94      *  @param[in] priority - A 64 bit integer representing the priority
95      *  @throws SdEventError for underlying sd_event errors
96      */
97     void set_priority(int64_t priority) const;
98 
99     /** @brief Determines the enablement value of the source
100      *
101      *  @throws SdEventError for underlying sd_event errors
102      *  @return The enabled status of the source
103      */
104     Enabled get_enabled() const;
105 
106     /** @brief Sets the enablement value of the source
107      *
108      *  @param[in] enabled - The new state of the source
109      *  @throws SdEventError for underlying sd_event errors
110      */
111     void set_enabled(Enabled enabled) const;
112 
113   protected:
114     Event event;
115     internal::SdRef<sd_event_source> source;
116 
117     // Base sources cannot be directly constructed.
118     Base(const Event& event, sd_event_source* source);
119     Base(const Event& event, sd_event_source* source, std::false_type);
120 
121     // We can't ever copy an event_source because the callback
122     // data has to be unique.
123     Base(const Base& other) = delete;
124     Base& operator=(const Base& other) = delete;
125     // We don't want to allow any kind of slicing.
126     Base(Base&& other);
127     Base& operator=(Base&& other);
128 
129     const Callback& get_prepare() const;
130 
131     template <typename Callback, class Source,
132               const Callback& (Source::*getter)() const, typename... Args>
133     static int sourceCallback(const char* name, sd_event_source*,
134                               void* userdata, Args... args)
135     {
136         if (userdata == nullptr)
137         {
138             fprintf(stderr, "sdeventplus: %s: Missing userdata\n", name);
139             return -EINVAL;
140         }
141         Source* source = reinterpret_cast<Source*>(userdata);
142         return internal::performCallback(name, (source->*getter)(),
143                                          std::ref(*source), args...);
144     }
145 
146   private:
147     Callback prepare;
148 
149     void set_userdata();
150     static int prepareCallback(sd_event_source* source, void* userdata);
151 };
152 
153 } // namespace source
154 } // namespace sdeventplus
155