10a816c5dSWilliam A. Kennington III #pragma once
20a816c5dSWilliam A. Kennington III 
3*a8c11e3cSPatrick Williams #include <systemd/sd-bus.h>
4*a8c11e3cSPatrick Williams 
5220b5dabSWilliam A. Kennington III #include <function2/function2.hpp>
6715c72f8SWilliam A. Kennington III #include <sdeventplus/event.hpp>
75320b1f5SWilliam A. Kennington III #include <sdeventplus/types.hpp>
856dc78baSWilliam A. Kennington III #include <stdplus/handle/copyable.hpp>
9*a8c11e3cSPatrick Williams 
10*a8c11e3cSPatrick Williams #include <cerrno>
11*a8c11e3cSPatrick Williams #include <cstdint>
12*a8c11e3cSPatrick Williams #include <cstdio>
13*a8c11e3cSPatrick Williams #include <functional>
14*a8c11e3cSPatrick Williams #include <memory>
150a816c5dSWilliam A. Kennington III #include <type_traits>
161e125d97SWilliam A. Kennington III #include <utility>
170a816c5dSWilliam A. Kennington III 
180a816c5dSWilliam A. Kennington III namespace sdeventplus
190a816c5dSWilliam A. Kennington III {
200a816c5dSWilliam A. Kennington III namespace source
210a816c5dSWilliam A. Kennington III {
220a816c5dSWilliam A. Kennington III 
238fd0cd4cSWilliam A. Kennington III /** @class Enabled
248fd0cd4cSWilliam A. Kennington III  *  @brief Mapping of sdeventplus source enable values to the sd-event
258fd0cd4cSWilliam A. Kennington III  *         equivalent
268fd0cd4cSWilliam A. Kennington III  */
278fd0cd4cSWilliam A. Kennington III enum class Enabled
288fd0cd4cSWilliam A. Kennington III {
298fd0cd4cSWilliam A. Kennington III     Off = SD_EVENT_OFF,
308fd0cd4cSWilliam A. Kennington III     On = SD_EVENT_ON,
318fd0cd4cSWilliam A. Kennington III     OneShot = SD_EVENT_ONESHOT,
328fd0cd4cSWilliam A. Kennington III };
338fd0cd4cSWilliam A. Kennington III 
345320b1f5SWilliam A. Kennington III namespace detail
355320b1f5SWilliam A. Kennington III {
365320b1f5SWilliam A. Kennington III class BaseData;
375320b1f5SWilliam A. Kennington III } // namespace detail
385320b1f5SWilliam A. Kennington III 
393c845caaSWilliam A. Kennington III /** @class Base
403c845caaSWilliam A. Kennington III  *  @brief The base class for all sources implementing common source methods
413c845caaSWilliam A. Kennington III  *         Not instantiated directly by end users
423c845caaSWilliam A. Kennington III  */
430a816c5dSWilliam A. Kennington III class Base
440a816c5dSWilliam A. Kennington III {
450a816c5dSWilliam A. Kennington III   public:
46220b5dabSWilliam A. Kennington III     using Callback = fu2::unique_function<void(Base& source)>;
4748c42751SWilliam A. Kennington III 
485320b1f5SWilliam A. Kennington III     Base(Base&& other) = default;
495320b1f5SWilliam A. Kennington III     Base& operator=(Base&& other) = default;
5056dc78baSWilliam A. Kennington III     Base(const Base& other) = default;
5156dc78baSWilliam A. Kennington III     Base& operator=(const Base& other) = default;
525320b1f5SWilliam A. Kennington III     virtual ~Base() = default;
5365db863eSWilliam A. Kennington III 
543c845caaSWilliam A. Kennington III     /** @brief Gets the underlying sd_event_source
553c845caaSWilliam A. Kennington III      *
563c845caaSWilliam A. Kennington III      *  @return The sd_event_source
573c845caaSWilliam A. Kennington III      */
584863b96bSWilliam A. Kennington III     sd_event_source* get() const;
593c845caaSWilliam A. Kennington III 
603c845caaSWilliam A. Kennington III     /** @brief Gets the associated Event object
613c845caaSWilliam A. Kennington III      *
623c845caaSWilliam A. Kennington III      *  @return The Event
633c845caaSWilliam A. Kennington III      */
64715c72f8SWilliam A. Kennington III     const Event& get_event() const;
65715c72f8SWilliam A. Kennington III 
663c845caaSWilliam A. Kennington III     /** @brief Gets the description of the source
673c845caaSWilliam A. Kennington III      *
683c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
693c845caaSWilliam A. Kennington III      *  @return The c-string description or a nullptr if none exists
703c845caaSWilliam A. Kennington III      */
71d9fd9815SWilliam A. Kennington III     const char* get_description() const;
723c845caaSWilliam A. Kennington III 
733c845caaSWilliam A. Kennington III     /** @brief Sets the description of the source
743c845caaSWilliam A. Kennington III      *
753c845caaSWilliam A. Kennington III      *  @param[in] description - The c-string description
763c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
773c845caaSWilliam A. Kennington III      */
78d9fd9815SWilliam A. Kennington III     void set_description(const char* description) const;
793c845caaSWilliam A. Kennington III 
803c845caaSWilliam A. Kennington III     /** @brief Sets the callback associated with the source to be performed
813c845caaSWilliam A. Kennington III      *         before the event loop goes to sleep, waiting for new events
823c845caaSWilliam A. Kennington III      *
833c845caaSWilliam A. Kennington III      *  @param[in] callback - Function run for preparation of the source
843c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
853c845caaSWilliam A. Kennington III      */
8648c42751SWilliam A. Kennington III     void set_prepare(Callback&& callback);
873c845caaSWilliam A. Kennington III 
883c845caaSWilliam A. Kennington III     /** @brief Whether or not the source has any pending events that have
893c845caaSWilliam A. Kennington III      *         not been dispatched yet.
903c845caaSWilliam A. Kennington III      *
913c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
923c845caaSWilliam A. Kennington III      *  @return 'true' if the source has pending events
933c845caaSWilliam A. Kennington III      *          'false' otherwise
943c845caaSWilliam A. Kennington III      */
958fd0cd4cSWilliam A. Kennington III     bool get_pending() const;
963c845caaSWilliam A. Kennington III 
973c845caaSWilliam A. Kennington III     /** @brief Gets the priority of the source relative to other sources
983c845caaSWilliam A. Kennington III      *         The lower the priority the more important the source
993c845caaSWilliam A. Kennington III      *
1003c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
1013c845caaSWilliam A. Kennington III      *  @return A 64 bit integer representing the dispatch priority
1023c845caaSWilliam A. Kennington III      */
103d9fd9815SWilliam A. Kennington III     int64_t get_priority() const;
1043c845caaSWilliam A. Kennington III 
1053c845caaSWilliam A. Kennington III     /** @brief Sets the priority of the source relative to other sources
1063c845caaSWilliam A. Kennington III      *         The lower the priority the more important the source
1073c845caaSWilliam A. Kennington III      *
1083c845caaSWilliam A. Kennington III      *  @param[in] priority - A 64 bit integer representing the priority
1093c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
1103c845caaSWilliam A. Kennington III      */
111d9fd9815SWilliam A. Kennington III     void set_priority(int64_t priority) const;
1123c845caaSWilliam A. Kennington III 
1133c845caaSWilliam A. Kennington III     /** @brief Determines the enablement value of the source
1143c845caaSWilliam A. Kennington III      *
1153c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
1163c845caaSWilliam A. Kennington III      *  @return The enabled status of the source
1173c845caaSWilliam A. Kennington III      */
1188fd0cd4cSWilliam A. Kennington III     Enabled get_enabled() const;
1193c845caaSWilliam A. Kennington III 
1203c845caaSWilliam A. Kennington III     /** @brief Sets the enablement value of the source
1213c845caaSWilliam A. Kennington III      *
1223c845caaSWilliam A. Kennington III      *  @param[in] enabled - The new state of the source
1233c845caaSWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
1243c845caaSWilliam A. Kennington III      */
1258fd0cd4cSWilliam A. Kennington III     void set_enabled(Enabled enabled) const;
12665db863eSWilliam A. Kennington III 
12743493b58SWilliam A. Kennington III     /** @brief Determines the floating nature of the source
12843493b58SWilliam A. Kennington III      *
12943493b58SWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
13043493b58SWilliam A. Kennington III      *  @return The enabled status of the source
13143493b58SWilliam A. Kennington III      */
13243493b58SWilliam A. Kennington III     bool get_floating() const;
13343493b58SWilliam A. Kennington III 
13443493b58SWilliam A. Kennington III     /** @brief Sets the floating nature of the source
13543493b58SWilliam A. Kennington III      *         If set to true, the source will continue to run after the
13643493b58SWilliam A. Kennington III      *         destruction of this handle.
13743493b58SWilliam A. Kennington III      *
13843493b58SWilliam A. Kennington III      *  @param[in] b - Whether or not the source should float
13943493b58SWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
14043493b58SWilliam A. Kennington III      */
14143493b58SWilliam A. Kennington III     void set_floating(bool b) const;
14243493b58SWilliam A. Kennington III 
1430a816c5dSWilliam A. Kennington III   protected:
144cc6b12beSWilliam A. Kennington III     Event event;
1450a816c5dSWilliam A. Kennington III 
146bc4e4569SWilliam A. Kennington III     /** @brief Constructs a basic event source wrapper
147bc4e4569SWilliam A. Kennington III      *         Owns the passed reference to the source
148bc4e4569SWilliam A. Kennington III      *         This ownership is exception safe and will properly free the
149bc4e4569SWilliam A. Kennington III      *         source in the case of an exception during construction
150bc4e4569SWilliam A. Kennington III      *
151bc4e4569SWilliam A. Kennington III      *  @param[in] event  - The event associated with the source
152bc4e4569SWilliam A. Kennington III      *  @param[in] source - The underlying sd_event_source wrapped
1532301d47fSWilliam A. Kennington III      *  @param[in]        - Signifies that ownership is being transfered
154bc4e4569SWilliam A. Kennington III      */
155715c72f8SWilliam A. Kennington III     Base(const Event& event, sd_event_source* source, std::false_type);
15648c42751SWilliam A. Kennington III 
1575320b1f5SWilliam A. Kennington III     /** @brief Constructs a basic non-owning event source wrapper
1585320b1f5SWilliam A. Kennington III      *         Does not own the passed reference to the source because
1595320b1f5SWilliam A. Kennington III      *         this is meant to be used only as a reference inside an event
1605320b1f5SWilliam A. Kennington III      *         source.
1615320b1f5SWilliam A. Kennington III      *  @internal
1625320b1f5SWilliam A. Kennington III      *
1635320b1f5SWilliam A. Kennington III      *  @param[in] other - The source wrapper to copy
1645320b1f5SWilliam A. Kennington III      *  @param[in]       - Signifies that this new copy is non-owning
1655320b1f5SWilliam A. Kennington III      */
1665320b1f5SWilliam A. Kennington III     Base(const Base& other, sdeventplus::internal::NoOwn);
1675320b1f5SWilliam A. Kennington III 
1685320b1f5SWilliam A. Kennington III     /** @brief Sets the userdata of the source to the passed in source
1695320b1f5SWilliam A. Kennington III      *         This needs to be called by all source implementors.
1705320b1f5SWilliam A. Kennington III      *
1715320b1f5SWilliam A. Kennington III      *  @param[in] data - The data stored in the userdata slot.
1725320b1f5SWilliam A. Kennington III      *  @throws SdEventError for underlying sd_event errors
1735320b1f5SWilliam A. Kennington III      */
1745320b1f5SWilliam A. Kennington III     void set_userdata(std::unique_ptr<detail::BaseData> data) const;
1755320b1f5SWilliam A. Kennington III 
1765320b1f5SWilliam A. Kennington III     /** @brief Get the heap allocated version of the Base
1775320b1f5SWilliam A. Kennington III      *
1785320b1f5SWilliam A. Kennington III      *  @return A reference to the Base
1795320b1f5SWilliam A. Kennington III      */
1805320b1f5SWilliam A. Kennington III     detail::BaseData& get_userdata() const;
181cc6b12beSWilliam A. Kennington III 
182bc4e4569SWilliam A. Kennington III     /** @brief Returns a reference to the prepare callback executed for this
183bc4e4569SWilliam A. Kennington III      *         source
184bc4e4569SWilliam A. Kennington III      *
185bc4e4569SWilliam A. Kennington III      *  @return A reference to the callback, this should be checked to make sure
186bc4e4569SWilliam A. Kennington III      *          the callback is valid as there is no guarantee
187bc4e4569SWilliam A. Kennington III      */
188220b5dabSWilliam A. Kennington III     Callback& get_prepare();
189e0f1d199SWilliam A. Kennington III 
190bc4e4569SWilliam A. Kennington III     /** @brief A helper for subclasses to trivially wrap a c++ style callback
191bc4e4569SWilliam A. Kennington III      *         to be called from the sd-event c library
192bc4e4569SWilliam A. Kennington III      *
193bc4e4569SWilliam A. Kennington III      *  @param[in] name     - The name of the callback for use in error messages
194bc4e4569SWilliam A. Kennington III      *  @param[in] source   - The sd_event_source provided by sd-event
195bc4e4569SWilliam A. Kennington III      *  @param[in] userdata - The userdata provided by sd-event
196bc4e4569SWilliam A. Kennington III      *  @param[in] args...  - Extra arguments to pass to the callaback
197bc4e4569SWilliam A. Kennington III      *  @return An negative errno on error, or 0 on success
198bc4e4569SWilliam A. Kennington III      */
1995320b1f5SWilliam A. Kennington III     template <typename Callback, class Data, auto getter, typename... Args>
200e0f1d199SWilliam A. Kennington III     static int sourceCallback(const char* name, sd_event_source*,
2011e125d97SWilliam A. Kennington III                               void* userdata, Args&&... args)
202e0f1d199SWilliam A. Kennington III     {
203e0f1d199SWilliam A. Kennington III         if (userdata == nullptr)
204e0f1d199SWilliam A. Kennington III         {
205e0f1d199SWilliam A. Kennington III             fprintf(stderr, "sdeventplus: %s: Missing userdata\n", name);
206e0f1d199SWilliam A. Kennington III             return -EINVAL;
207e0f1d199SWilliam A. Kennington III         }
2085320b1f5SWilliam A. Kennington III         Data& data =
2095320b1f5SWilliam A. Kennington III             static_cast<Data&>(*reinterpret_cast<detail::BaseData*>(userdata));
2105320b1f5SWilliam A. Kennington III         Callback& callback = std::invoke(getter, data);
2118e7ec0feSWilliam A. Kennington III         try
2128e7ec0feSWilliam A. Kennington III         {
2138e7ec0feSWilliam A. Kennington III             std::invoke(callback, data, std::forward<Args>(args)...);
2148e7ec0feSWilliam A. Kennington III         }
2158e7ec0feSWilliam A. Kennington III         catch (const std::exception& e)
2168e7ec0feSWilliam A. Kennington III         {
2178e7ec0feSWilliam A. Kennington III             fprintf(stderr, "sdeventplus: %s: %s\n", name, e.what());
2188e7ec0feSWilliam A. Kennington III         }
2198e7ec0feSWilliam A. Kennington III         catch (...)
2208e7ec0feSWilliam A. Kennington III         {
2218e7ec0feSWilliam A. Kennington III             fprintf(stderr, "sdeventplus: %s: Unknown error\n", name);
2228e7ec0feSWilliam A. Kennington III         }
2238e7ec0feSWilliam A. Kennington III         return 0;
224e0f1d199SWilliam A. Kennington III     }
225e0f1d199SWilliam A. Kennington III 
22648c42751SWilliam A. Kennington III   private:
22756dc78baSWilliam A. Kennington III     static sd_event_source* ref(sd_event_source* const& source,
22856dc78baSWilliam A. Kennington III                                 const internal::SdEvent*& sdevent, bool& owned);
229e04cb03bSWilliam A. Kennington III     static void drop(sd_event_source*&& source,
2305320b1f5SWilliam A. Kennington III                      const internal::SdEvent*& sdevent, bool& owned);
231e04cb03bSWilliam A. Kennington III 
23256dc78baSWilliam A. Kennington III     stdplus::Copyable<sd_event_source*, const internal::SdEvent*,
23356dc78baSWilliam A. Kennington III                       bool>::Handle<drop, ref>
234e04cb03bSWilliam A. Kennington III         source;
2352d943eadSWilliam A. Kennington III 
2365320b1f5SWilliam A. Kennington III     /** @brief A wrapper around deleting the heap allocated base class
2375320b1f5SWilliam A. Kennington III      *         This is needed for calls from sd_event destroy callbacks.
238bc4e4569SWilliam A. Kennington III      *
2395320b1f5SWilliam A. Kennington III      * @param[in] userdata - The provided userdata for the source
240bc4e4569SWilliam A. Kennington III      */
2415320b1f5SWilliam A. Kennington III     static void destroy_userdata(void* userdata);
242bc4e4569SWilliam A. Kennington III 
243bc4e4569SWilliam A. Kennington III     /** @brief A wrapper around the callback that can be called from sd-event
244bc4e4569SWilliam A. Kennington III      *
245bc4e4569SWilliam A. Kennington III      * @param[in] source   - The sd_event_source associated with the call
246bc4e4569SWilliam A. Kennington III      * @param[in] userdata - The provided userdata for the source
247bc4e4569SWilliam A. Kennington III      * @return 0 on success or a negative errno otherwise
248bc4e4569SWilliam A. Kennington III      */
249e0f1d199SWilliam A. Kennington III     static int prepareCallback(sd_event_source* source, void* userdata);
2500a816c5dSWilliam A. Kennington III };
2510a816c5dSWilliam A. Kennington III 
2525320b1f5SWilliam A. Kennington III namespace detail
2535320b1f5SWilliam A. Kennington III {
2545320b1f5SWilliam A. Kennington III 
2555320b1f5SWilliam A. Kennington III class BaseData : public Base
2565320b1f5SWilliam A. Kennington III {
2575320b1f5SWilliam A. Kennington III   private:
2585320b1f5SWilliam A. Kennington III     Base::Callback prepare;
2595320b1f5SWilliam A. Kennington III 
2605320b1f5SWilliam A. Kennington III   public:
2615320b1f5SWilliam A. Kennington III     BaseData(const Base& base);
2625320b1f5SWilliam A. Kennington III 
2635320b1f5SWilliam A. Kennington III     friend Base;
2645320b1f5SWilliam A. Kennington III };
2655320b1f5SWilliam A. Kennington III 
2665320b1f5SWilliam A. Kennington III } // namespace detail
2675320b1f5SWilliam A. Kennington III 
2680a816c5dSWilliam A. Kennington III } // namespace source
2690a816c5dSWilliam A. Kennington III } // namespace sdeventplus
270