10a816c5dSWilliam A. Kennington III #pragma once
20a816c5dSWilliam A. Kennington III 
3e0f1d199SWilliam A. Kennington III #include <cerrno>
465db863eSWilliam A. Kennington III #include <cstdint>
5e0f1d199SWilliam A. Kennington III #include <cstdio>
6220b5dabSWilliam A. Kennington III #include <function2/function2.hpp>
748c42751SWilliam A. Kennington III #include <functional>
8*5320b1f5SWilliam A. Kennington III #include <memory>
9715c72f8SWilliam A. Kennington III #include <sdeventplus/event.hpp>
10e0f1d199SWilliam A. Kennington III #include <sdeventplus/internal/utils.hpp>
11*5320b1f5SWilliam A. Kennington III #include <sdeventplus/types.hpp>
12b555c4e6SWilliam A. Kennington III #include <stdplus/handle/managed.hpp>
130a816c5dSWilliam A. Kennington III #include <systemd/sd-bus.h>
140a816c5dSWilliam A. Kennington III #include <type_traits>
151e125d97SWilliam A. Kennington III #include <utility>
160a816c5dSWilliam A. Kennington III 
170a816c5dSWilliam A. Kennington III namespace sdeventplus
180a816c5dSWilliam A. Kennington III {
190a816c5dSWilliam A. Kennington III namespace source
200a816c5dSWilliam A. Kennington III {
210a816c5dSWilliam A. Kennington III 
228fd0cd4cSWilliam A. Kennington III /** @class Enabled
238fd0cd4cSWilliam A. Kennington III  *  @brief Mapping of sdeventplus source enable values to the sd-event
248fd0cd4cSWilliam A. Kennington III  *         equivalent
258fd0cd4cSWilliam A. Kennington III  */
268fd0cd4cSWilliam A. Kennington III enum class Enabled
278fd0cd4cSWilliam A. Kennington III {
288fd0cd4cSWilliam A. Kennington III     Off = SD_EVENT_OFF,
298fd0cd4cSWilliam A. Kennington III     On = SD_EVENT_ON,
308fd0cd4cSWilliam A. Kennington III     OneShot = SD_EVENT_ONESHOT,
318fd0cd4cSWilliam A. Kennington III };
328fd0cd4cSWilliam A. Kennington III 
33*5320b1f5SWilliam A. Kennington III namespace detail
34*5320b1f5SWilliam A. Kennington III {
35*5320b1f5SWilliam A. Kennington III class BaseData;
36*5320b1f5SWilliam A. Kennington III } // namespace detail
37*5320b1f5SWilliam A. Kennington III 
383c845caaSWilliam A. Kennington III /** @class Base
393c845caaSWilliam A. Kennington III  *  @brief The base class for all sources implementing common source methods
403c845caaSWilliam A. Kennington III  *         Not instantiated directly by end users
413c845caaSWilliam A. Kennington III  */
420a816c5dSWilliam A. Kennington III class Base
430a816c5dSWilliam A. Kennington III {
440a816c5dSWilliam A. Kennington III   public:
45220b5dabSWilliam A. Kennington III     using Callback = fu2::unique_function<void(Base& source)>;
4648c42751SWilliam A. Kennington III 
47*5320b1f5SWilliam A. Kennington III     Base(Base&& other) = default;
48*5320b1f5SWilliam A. Kennington III     Base& operator=(Base&& other) = default;
49*5320b1f5SWilliam A. Kennington III     virtual ~Base() = default;
5065db863eSWilliam A. Kennington III 
513c845caaSWilliam A. Kennington III     /** @brief Gets the underlying sd_event_source
523c845caaSWilliam A. Kennington III      *
533c845caaSWilliam A. Kennington III      *  @return The sd_event_source
543c845caaSWilliam A. Kennington III      */
554863b96bSWilliam A. Kennington III     sd_event_source* get() const;
563c845caaSWilliam A. Kennington III 
573c845caaSWilliam A. Kennington III     /** @brief Gets the associated Event object
583c845caaSWilliam A. Kennington III      *
593c845caaSWilliam A. Kennington III      *  @return The Event
603c845caaSWilliam A. Kennington III      */
61715c72f8SWilliam A. Kennington III     const Event& get_event() const;
62715c72f8SWilliam A. Kennington III 
633c845caaSWilliam A. Kennington III     /** @brief Gets the description of the source
643c845caaSWilliam A. Kennington III      *
653c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
663c845caaSWilliam A. Kennington III      *  @return The c-string description or a nullptr if none exists
673c845caaSWilliam A. Kennington III      */
68d9fd9815SWilliam A. Kennington III     const char* get_description() const;
693c845caaSWilliam A. Kennington III 
703c845caaSWilliam A. Kennington III     /** @brief Sets the description of the source
713c845caaSWilliam A. Kennington III      *
723c845caaSWilliam A. Kennington III      *  @param[in] description - The c-string description
733c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
743c845caaSWilliam A. Kennington III      */
75d9fd9815SWilliam A. Kennington III     void set_description(const char* description) const;
763c845caaSWilliam A. Kennington III 
773c845caaSWilliam A. Kennington III     /** @brief Sets the callback associated with the source to be performed
783c845caaSWilliam A. Kennington III      *         before the event loop goes to sleep, waiting for new events
793c845caaSWilliam A. Kennington III      *
803c845caaSWilliam A. Kennington III      *  @param[in] callback - Function run for preparation of the source
813c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
823c845caaSWilliam A. Kennington III      */
8348c42751SWilliam A. Kennington III     void set_prepare(Callback&& callback);
843c845caaSWilliam A. Kennington III 
853c845caaSWilliam A. Kennington III     /** @brief Whether or not the source has any pending events that have
863c845caaSWilliam A. Kennington III      *         not been dispatched yet.
873c845caaSWilliam A. Kennington III      *
883c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
893c845caaSWilliam A. Kennington III      *  @return 'true' if the source has pending events
903c845caaSWilliam A. Kennington III      *          'false' otherwise
913c845caaSWilliam A. Kennington III      */
928fd0cd4cSWilliam A. Kennington III     bool get_pending() const;
933c845caaSWilliam A. Kennington III 
943c845caaSWilliam A. Kennington III     /** @brief Gets the priority of the source relative to other sources
953c845caaSWilliam A. Kennington III      *         The lower the priority the more important the source
963c845caaSWilliam A. Kennington III      *
973c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
983c845caaSWilliam A. Kennington III      *  @return A 64 bit integer representing the dispatch priority
993c845caaSWilliam A. Kennington III      */
100d9fd9815SWilliam A. Kennington III     int64_t get_priority() const;
1013c845caaSWilliam A. Kennington III 
1023c845caaSWilliam A. Kennington III     /** @brief Sets the priority of the source relative to other sources
1033c845caaSWilliam A. Kennington III      *         The lower the priority the more important the source
1043c845caaSWilliam A. Kennington III      *
1053c845caaSWilliam A. Kennington III      *  @param[in] priority - A 64 bit integer representing the priority
1063c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
1073c845caaSWilliam A. Kennington III      */
108d9fd9815SWilliam A. Kennington III     void set_priority(int64_t priority) const;
1093c845caaSWilliam A. Kennington III 
1103c845caaSWilliam A. Kennington III     /** @brief Determines the enablement value of the source
1113c845caaSWilliam A. Kennington III      *
1123c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
1133c845caaSWilliam A. Kennington III      *  @return The enabled status of the source
1143c845caaSWilliam A. Kennington III      */
1158fd0cd4cSWilliam A. Kennington III     Enabled get_enabled() const;
1163c845caaSWilliam A. Kennington III 
1173c845caaSWilliam A. Kennington III     /** @brief Sets the enablement value of the source
1183c845caaSWilliam A. Kennington III      *
1193c845caaSWilliam A. Kennington III      *  @param[in] enabled - The new state of the source
1203c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
1213c845caaSWilliam A. Kennington III      */
1228fd0cd4cSWilliam A. Kennington III     void set_enabled(Enabled enabled) const;
12365db863eSWilliam A. Kennington III 
1240a816c5dSWilliam A. Kennington III   protected:
125cc6b12beSWilliam A. Kennington III     Event event;
1260a816c5dSWilliam A. Kennington III 
127bc4e4569SWilliam A. Kennington III     /** @brief Constructs a basic event source wrapper
128bc4e4569SWilliam A. Kennington III      *         Owns the passed reference to the source
129bc4e4569SWilliam A. Kennington III      *         This ownership is exception safe and will properly free the
130bc4e4569SWilliam A. Kennington III      *         source in the case of an exception during construction
131bc4e4569SWilliam A. Kennington III      *
132bc4e4569SWilliam A. Kennington III      *  @param[in] event  - The event associated with the source
133bc4e4569SWilliam A. Kennington III      *  @param[in] source - The underlying sd_event_source wrapped
1342301d47fSWilliam A. Kennington III      *  @param[in]        - Signifies that ownership is being transfered
135bc4e4569SWilliam A. Kennington III      */
136715c72f8SWilliam A. Kennington III     Base(const Event& event, sd_event_source* source, std::false_type);
13748c42751SWilliam A. Kennington III 
138*5320b1f5SWilliam A. Kennington III     /** @brief Constructs a basic non-owning event source wrapper
139*5320b1f5SWilliam A. Kennington III      *         Does not own the passed reference to the source because
140*5320b1f5SWilliam A. Kennington III      *         this is meant to be used only as a reference inside an event
141*5320b1f5SWilliam A. Kennington III      *         source.
142*5320b1f5SWilliam A. Kennington III      *  @internal
143*5320b1f5SWilliam A. Kennington III      *
144*5320b1f5SWilliam A. Kennington III      *  @param[in] other - The source wrapper to copy
145*5320b1f5SWilliam A. Kennington III      *  @param[in]       - Signifies that this new copy is non-owning
146*5320b1f5SWilliam A. Kennington III      */
147*5320b1f5SWilliam A. Kennington III     Base(const Base& other, sdeventplus::internal::NoOwn);
148*5320b1f5SWilliam A. Kennington III 
149*5320b1f5SWilliam A. Kennington III     /** @brief Sets the userdata of the source to the passed in source
150*5320b1f5SWilliam A. Kennington III      *         This needs to be called by all source implementors.
151*5320b1f5SWilliam A. Kennington III      *
152*5320b1f5SWilliam A. Kennington III      *  @param[in] data - The data stored in the userdata slot.
153*5320b1f5SWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
154*5320b1f5SWilliam A. Kennington III      */
155*5320b1f5SWilliam A. Kennington III     void set_userdata(std::unique_ptr<detail::BaseData> data) const;
156*5320b1f5SWilliam A. Kennington III 
157*5320b1f5SWilliam A. Kennington III     /** @brief Get the heap allocated version of the Base
158*5320b1f5SWilliam A. Kennington III      *
159*5320b1f5SWilliam A. Kennington III      *  @return A reference to the Base
160*5320b1f5SWilliam A. Kennington III      */
161*5320b1f5SWilliam A. Kennington III     detail::BaseData& get_userdata() const;
162cc6b12beSWilliam A. Kennington III 
163bc4e4569SWilliam A. Kennington III     /** @brief Returns a reference to the prepare callback executed for this
164bc4e4569SWilliam A. Kennington III      *         source
165bc4e4569SWilliam A. Kennington III      *
166bc4e4569SWilliam A. Kennington III      *  @return A reference to the callback, this should be checked to make sure
167bc4e4569SWilliam A. Kennington III      *          the callback is valid as there is no guarantee
168bc4e4569SWilliam A. Kennington III      */
169220b5dabSWilliam A. Kennington III     Callback& get_prepare();
170e0f1d199SWilliam A. Kennington III 
171bc4e4569SWilliam A. Kennington III     /** @brief A helper for subclasses to trivially wrap a c++ style callback
172bc4e4569SWilliam A. Kennington III      *         to be called from the sd-event c library
173bc4e4569SWilliam A. Kennington III      *
174bc4e4569SWilliam A. Kennington III      *  @param[in] name     - The name of the callback for use in error messages
175bc4e4569SWilliam A. Kennington III      *  @param[in] source   - The sd_event_source provided by sd-event
176bc4e4569SWilliam A. Kennington III      *  @param[in] userdata - The userdata provided by sd-event
177bc4e4569SWilliam A. Kennington III      *  @param[in] args...  - Extra arguments to pass to the callaback
178bc4e4569SWilliam A. Kennington III      *  @return An negative errno on error, or 0 on success
179bc4e4569SWilliam A. Kennington III      */
180*5320b1f5SWilliam A. Kennington III     template <typename Callback, class Data, auto getter, typename... Args>
181e0f1d199SWilliam A. Kennington III     static int sourceCallback(const char* name, sd_event_source*,
1821e125d97SWilliam A. Kennington III                               void* userdata, Args&&... args)
183e0f1d199SWilliam A. Kennington III     {
184e0f1d199SWilliam A. Kennington III         if (userdata == nullptr)
185e0f1d199SWilliam A. Kennington III         {
186e0f1d199SWilliam A. Kennington III             fprintf(stderr, "sdeventplus: %s: Missing userdata\n", name);
187e0f1d199SWilliam A. Kennington III             return -EINVAL;
188e0f1d199SWilliam A. Kennington III         }
189*5320b1f5SWilliam A. Kennington III         Data& data =
190*5320b1f5SWilliam A. Kennington III             static_cast<Data&>(*reinterpret_cast<detail::BaseData*>(userdata));
191*5320b1f5SWilliam A. Kennington III         Callback& callback = std::invoke(getter, data);
192*5320b1f5SWilliam A. Kennington III         return internal::performCallback(name, callback, std::ref(data),
1931e125d97SWilliam A. Kennington III                                          std::forward<Args>(args)...);
194e0f1d199SWilliam A. Kennington III     }
195e0f1d199SWilliam A. Kennington III 
19648c42751SWilliam A. Kennington III   private:
197e04cb03bSWilliam A. Kennington III     static void drop(sd_event_source*&& source,
198*5320b1f5SWilliam A. Kennington III                      const internal::SdEvent*& sdevent, bool& owned);
199e04cb03bSWilliam A. Kennington III 
200*5320b1f5SWilliam A. Kennington III     stdplus::Managed<sd_event_source*, const internal::SdEvent*,
201*5320b1f5SWilliam A. Kennington III                      bool>::Handle<drop>
202e04cb03bSWilliam A. Kennington III         source;
2032d943eadSWilliam A. Kennington III 
204*5320b1f5SWilliam A. Kennington III     /** @brief A wrapper around deleting the heap allocated base class
205*5320b1f5SWilliam A. Kennington III      *         This is needed for calls from sd_event destroy callbacks.
206bc4e4569SWilliam A. Kennington III      *
207*5320b1f5SWilliam A. Kennington III      * @param[in] userdata - The provided userdata for the source
208bc4e4569SWilliam A. Kennington III      */
209*5320b1f5SWilliam A. Kennington III     static void destroy_userdata(void* userdata);
210bc4e4569SWilliam A. Kennington III 
211bc4e4569SWilliam A. Kennington III     /** @brief A wrapper around the callback that can be called from sd-event
212bc4e4569SWilliam A. Kennington III      *
213bc4e4569SWilliam A. Kennington III      * @param[in] source   - The sd_event_source associated with the call
214bc4e4569SWilliam A. Kennington III      * @param[in] userdata - The provided userdata for the source
215bc4e4569SWilliam A. Kennington III      * @return 0 on success or a negative errno otherwise
216bc4e4569SWilliam A. Kennington III      */
217e0f1d199SWilliam A. Kennington III     static int prepareCallback(sd_event_source* source, void* userdata);
2180a816c5dSWilliam A. Kennington III };
2190a816c5dSWilliam A. Kennington III 
220*5320b1f5SWilliam A. Kennington III namespace detail
221*5320b1f5SWilliam A. Kennington III {
222*5320b1f5SWilliam A. Kennington III 
223*5320b1f5SWilliam A. Kennington III class BaseData : public Base
224*5320b1f5SWilliam A. Kennington III {
225*5320b1f5SWilliam A. Kennington III   private:
226*5320b1f5SWilliam A. Kennington III     Base::Callback prepare;
227*5320b1f5SWilliam A. Kennington III 
228*5320b1f5SWilliam A. Kennington III   public:
229*5320b1f5SWilliam A. Kennington III     BaseData(const Base& base);
230*5320b1f5SWilliam A. Kennington III 
231*5320b1f5SWilliam A. Kennington III     friend Base;
232*5320b1f5SWilliam A. Kennington III };
233*5320b1f5SWilliam A. Kennington III 
234*5320b1f5SWilliam A. Kennington III } // namespace detail
235*5320b1f5SWilliam A. Kennington III 
2360a816c5dSWilliam A. Kennington III } // namespace source
2370a816c5dSWilliam A. Kennington III } // namespace sdeventplus
238