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>
6*220b5dabSWilliam A. Kennington III #include <function2/function2.hpp>
748c42751SWilliam A. Kennington III #include <functional>
8715c72f8SWilliam A. Kennington III #include <sdeventplus/event.hpp>
9e0f1d199SWilliam A. Kennington III #include <sdeventplus/internal/utils.hpp>
10b555c4e6SWilliam A. Kennington III #include <stdplus/handle/managed.hpp>
110a816c5dSWilliam A. Kennington III #include <systemd/sd-bus.h>
120a816c5dSWilliam A. Kennington III #include <type_traits>
131e125d97SWilliam A. Kennington III #include <utility>
140a816c5dSWilliam A. Kennington III 
150a816c5dSWilliam A. Kennington III namespace sdeventplus
160a816c5dSWilliam A. Kennington III {
170a816c5dSWilliam A. Kennington III namespace source
180a816c5dSWilliam A. Kennington III {
190a816c5dSWilliam A. Kennington III 
208fd0cd4cSWilliam A. Kennington III /** @class Enabled
218fd0cd4cSWilliam A. Kennington III  *  @brief Mapping of sdeventplus source enable values to the sd-event
228fd0cd4cSWilliam A. Kennington III  *         equivalent
238fd0cd4cSWilliam A. Kennington III  */
248fd0cd4cSWilliam A. Kennington III enum class Enabled
258fd0cd4cSWilliam A. Kennington III {
268fd0cd4cSWilliam A. Kennington III     Off = SD_EVENT_OFF,
278fd0cd4cSWilliam A. Kennington III     On = SD_EVENT_ON,
288fd0cd4cSWilliam A. Kennington III     OneShot = SD_EVENT_ONESHOT,
298fd0cd4cSWilliam A. Kennington III };
308fd0cd4cSWilliam A. Kennington III 
313c845caaSWilliam A. Kennington III /** @class Base
323c845caaSWilliam A. Kennington III  *  @brief The base class for all sources implementing common source methods
333c845caaSWilliam A. Kennington III  *         Not instantiated directly by end users
343c845caaSWilliam A. Kennington III  */
350a816c5dSWilliam A. Kennington III class Base
360a816c5dSWilliam A. Kennington III {
370a816c5dSWilliam A. Kennington III   public:
38*220b5dabSWilliam A. Kennington III     using Callback = fu2::unique_function<void(Base& source)>;
3948c42751SWilliam A. Kennington III 
4065db863eSWilliam A. Kennington III     virtual ~Base();
4165db863eSWilliam A. Kennington III 
423c845caaSWilliam A. Kennington III     /** @brief Gets the underlying sd_event_source
433c845caaSWilliam A. Kennington III      *
443c845caaSWilliam A. Kennington III      *  @return The sd_event_source
453c845caaSWilliam A. Kennington III      */
464863b96bSWilliam A. Kennington III     sd_event_source* get() const;
473c845caaSWilliam A. Kennington III 
483c845caaSWilliam A. Kennington III     /** @brief Gets the associated Event object
493c845caaSWilliam A. Kennington III      *
503c845caaSWilliam A. Kennington III      *  @return The Event
513c845caaSWilliam A. Kennington III      */
52715c72f8SWilliam A. Kennington III     const Event& get_event() const;
53715c72f8SWilliam A. Kennington III 
543c845caaSWilliam A. Kennington III     /** @brief Gets the description of the source
553c845caaSWilliam A. Kennington III      *
563c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
573c845caaSWilliam A. Kennington III      *  @return The c-string description or a nullptr if none exists
583c845caaSWilliam A. Kennington III      */
59d9fd9815SWilliam A. Kennington III     const char* get_description() const;
603c845caaSWilliam A. Kennington III 
613c845caaSWilliam A. Kennington III     /** @brief Sets the description of the source
623c845caaSWilliam A. Kennington III      *
633c845caaSWilliam A. Kennington III      *  @param[in] description - The c-string description
643c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
653c845caaSWilliam A. Kennington III      */
66d9fd9815SWilliam A. Kennington III     void set_description(const char* description) const;
673c845caaSWilliam A. Kennington III 
683c845caaSWilliam A. Kennington III     /** @brief Sets the callback associated with the source to be performed
693c845caaSWilliam A. Kennington III      *         before the event loop goes to sleep, waiting for new events
703c845caaSWilliam A. Kennington III      *
713c845caaSWilliam A. Kennington III      *  @param[in] callback - Function run for preparation of the source
723c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
733c845caaSWilliam A. Kennington III      */
7448c42751SWilliam A. Kennington III     void set_prepare(Callback&& callback);
753c845caaSWilliam A. Kennington III 
763c845caaSWilliam A. Kennington III     /** @brief Whether or not the source has any pending events that have
773c845caaSWilliam A. Kennington III      *         not been dispatched yet.
783c845caaSWilliam A. Kennington III      *
793c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
803c845caaSWilliam A. Kennington III      *  @return 'true' if the source has pending events
813c845caaSWilliam A. Kennington III      *          'false' otherwise
823c845caaSWilliam A. Kennington III      */
838fd0cd4cSWilliam A. Kennington III     bool get_pending() const;
843c845caaSWilliam A. Kennington III 
853c845caaSWilliam A. Kennington III     /** @brief Gets the priority of the source relative to other sources
863c845caaSWilliam A. Kennington III      *         The lower the priority the more important the source
873c845caaSWilliam A. Kennington III      *
883c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
893c845caaSWilliam A. Kennington III      *  @return A 64 bit integer representing the dispatch priority
903c845caaSWilliam A. Kennington III      */
91d9fd9815SWilliam A. Kennington III     int64_t get_priority() const;
923c845caaSWilliam A. Kennington III 
933c845caaSWilliam A. Kennington III     /** @brief Sets the priority of the source relative to other sources
943c845caaSWilliam A. Kennington III      *         The lower the priority the more important the source
953c845caaSWilliam A. Kennington III      *
963c845caaSWilliam A. Kennington III      *  @param[in] priority - A 64 bit integer representing the priority
973c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
983c845caaSWilliam A. Kennington III      */
99d9fd9815SWilliam A. Kennington III     void set_priority(int64_t priority) const;
1003c845caaSWilliam A. Kennington III 
1013c845caaSWilliam A. Kennington III     /** @brief Determines the enablement value of the source
1023c845caaSWilliam A. Kennington III      *
1033c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
1043c845caaSWilliam A. Kennington III      *  @return The enabled status of the source
1053c845caaSWilliam A. Kennington III      */
1068fd0cd4cSWilliam A. Kennington III     Enabled get_enabled() const;
1073c845caaSWilliam A. Kennington III 
1083c845caaSWilliam A. Kennington III     /** @brief Sets the enablement value of the source
1093c845caaSWilliam A. Kennington III      *
1103c845caaSWilliam A. Kennington III      *  @param[in] enabled - The new state of the source
1113c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
1123c845caaSWilliam A. Kennington III      */
1138fd0cd4cSWilliam A. Kennington III     void set_enabled(Enabled enabled) const;
11465db863eSWilliam A. Kennington III 
1150a816c5dSWilliam A. Kennington III   protected:
116cc6b12beSWilliam A. Kennington III     Event event;
1170a816c5dSWilliam A. Kennington III 
118bc4e4569SWilliam A. Kennington III     /** @brief Constructs a basic event source wrapper
119bc4e4569SWilliam A. Kennington III      *         Owns the passed reference to the source
120bc4e4569SWilliam A. Kennington III      *         This ownership is exception safe and will properly free the
121bc4e4569SWilliam A. Kennington III      *         source in the case of an exception during construction
122bc4e4569SWilliam A. Kennington III      *
123bc4e4569SWilliam A. Kennington III      *  @param[in] event  - The event associated with the source
124bc4e4569SWilliam A. Kennington III      *  @param[in] source - The underlying sd_event_source wrapped
1252301d47fSWilliam A. Kennington III      *  @param[in]        - Signifies that ownership is being transfered
126bc4e4569SWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
127bc4e4569SWilliam A. Kennington III      */
128715c72f8SWilliam A. Kennington III     Base(const Event& event, sd_event_source* source, std::false_type);
12948c42751SWilliam A. Kennington III 
130cc6b12beSWilliam A. Kennington III     // We can't ever copy an event_source because the callback
131cc6b12beSWilliam A. Kennington III     // data has to be unique.
132cc6b12beSWilliam A. Kennington III     Base(const Base& other) = delete;
133cc6b12beSWilliam A. Kennington III     Base& operator=(const Base& other) = delete;
134cc6b12beSWilliam A. Kennington III     // We don't want to allow any kind of slicing.
1352d943eadSWilliam A. Kennington III     Base(Base&& other);
136cc6b12beSWilliam A. Kennington III     Base& operator=(Base&& other);
137cc6b12beSWilliam A. Kennington III 
138bc4e4569SWilliam A. Kennington III     /** @brief Returns a reference to the prepare callback executed for this
139bc4e4569SWilliam A. Kennington III      *         source
140bc4e4569SWilliam A. Kennington III      *
141bc4e4569SWilliam A. Kennington III      *  @return A reference to the callback, this should be checked to make sure
142bc4e4569SWilliam A. Kennington III      *          the callback is valid as there is no guarantee
143bc4e4569SWilliam A. Kennington III      */
144*220b5dabSWilliam A. Kennington III     Callback& get_prepare();
145e0f1d199SWilliam A. Kennington III 
146bc4e4569SWilliam A. Kennington III     /** @brief A helper for subclasses to trivially wrap a c++ style callback
147bc4e4569SWilliam A. Kennington III      *         to be called from the sd-event c library
148bc4e4569SWilliam A. Kennington III      *
149bc4e4569SWilliam A. Kennington III      *  @param[in] name     - The name of the callback for use in error messages
150bc4e4569SWilliam A. Kennington III      *  @param[in] source   - The sd_event_source provided by sd-event
151bc4e4569SWilliam A. Kennington III      *  @param[in] userdata - The userdata provided by sd-event
152bc4e4569SWilliam A. Kennington III      *  @param[in] args...  - Extra arguments to pass to the callaback
153bc4e4569SWilliam A. Kennington III      *  @return An negative errno on error, or 0 on success
154bc4e4569SWilliam A. Kennington III      */
155*220b5dabSWilliam A. Kennington III     template <typename Callback, class Source, Callback& (Source::*getter)(),
156*220b5dabSWilliam A. Kennington III               typename... Args>
157e0f1d199SWilliam A. Kennington III     static int sourceCallback(const char* name, sd_event_source*,
1581e125d97SWilliam A. Kennington III                               void* userdata, Args&&... args)
159e0f1d199SWilliam A. Kennington III     {
160e0f1d199SWilliam A. Kennington III         if (userdata == nullptr)
161e0f1d199SWilliam A. Kennington III         {
162e0f1d199SWilliam A. Kennington III             fprintf(stderr, "sdeventplus: %s: Missing userdata\n", name);
163e0f1d199SWilliam A. Kennington III             return -EINVAL;
164e0f1d199SWilliam A. Kennington III         }
165e0f1d199SWilliam A. Kennington III         Source* source = reinterpret_cast<Source*>(userdata);
166e0f1d199SWilliam A. Kennington III         return internal::performCallback(name, (source->*getter)(),
1671e125d97SWilliam A. Kennington III                                          std::ref(*source),
1681e125d97SWilliam A. Kennington III                                          std::forward<Args>(args)...);
169e0f1d199SWilliam A. Kennington III     }
170e0f1d199SWilliam A. Kennington III 
17148c42751SWilliam A. Kennington III   private:
172e04cb03bSWilliam A. Kennington III     static void drop(sd_event_source*&& source,
173e04cb03bSWilliam A. Kennington III                      const internal::SdEvent*& sdevent);
174e04cb03bSWilliam A. Kennington III 
175b555c4e6SWilliam A. Kennington III     stdplus::Managed<sd_event_source*, const internal::SdEvent*>::Handle<drop>
176e04cb03bSWilliam A. Kennington III         source;
17748c42751SWilliam A. Kennington III     Callback prepare;
1782d943eadSWilliam A. Kennington III 
179bc4e4569SWilliam A. Kennington III     /** @brief A helper used to make sure the userdata for the sd-event
180bc4e4569SWilliam A. Kennington III      *         callback is set to the current source c++ object
181bc4e4569SWilliam A. Kennington III      *
182bc4e4569SWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
183bc4e4569SWilliam A. Kennington III      */
1842d943eadSWilliam A. Kennington III     void set_userdata();
185bc4e4569SWilliam A. Kennington III 
186bc4e4569SWilliam A. Kennington III     /** @brief A wrapper around the callback that can be called from sd-event
187bc4e4569SWilliam A. Kennington III      *
188bc4e4569SWilliam A. Kennington III      * @param[in] source   - The sd_event_source associated with the call
189bc4e4569SWilliam A. Kennington III      * @param[in] userdata - The provided userdata for the source
190bc4e4569SWilliam A. Kennington III      * @return 0 on success or a negative errno otherwise
191bc4e4569SWilliam A. Kennington III      */
192e0f1d199SWilliam A. Kennington III     static int prepareCallback(sd_event_source* source, void* userdata);
1930a816c5dSWilliam A. Kennington III };
1940a816c5dSWilliam A. Kennington III 
1950a816c5dSWilliam A. Kennington III } // namespace source
1960a816c5dSWilliam A. Kennington III } // namespace sdeventplus
197