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 Base
19 {
20   public:
21     using Callback = std::function<void(Base& source)>;
22 
23     virtual ~Base();
24 
25     sd_event_source* get() const;
26     const Event& get_event() const;
27 
28     const char* get_description() const;
29     void set_description(const char* description) const;
30     void set_prepare(Callback&& callback);
31     int get_pending() const;
32     int64_t get_priority() const;
33     void set_priority(int64_t priority) const;
34     int get_enabled() const;
35     void set_enabled(int enabled) const;
36 
37   protected:
38     Event event;
39     internal::SdRef<sd_event_source> source;
40 
41     // Base sources cannot be directly constructed.
42     Base(const Event& event, sd_event_source* source);
43     Base(const Event& event, sd_event_source* source, std::false_type);
44 
45     // We can't ever copy an event_source because the callback
46     // data has to be unique.
47     Base(const Base& other) = delete;
48     Base& operator=(const Base& other) = delete;
49     // We don't want to allow any kind of slicing.
50     Base(Base&& other);
51     Base& operator=(Base&& other);
52 
53     const Callback& get_prepare() const;
54 
55     template <typename Callback, class Source,
56               const Callback& (Source::*getter)() const, typename... Args>
57     static int sourceCallback(const char* name, sd_event_source*,
58                               void* userdata, Args... args)
59     {
60         if (userdata == nullptr)
61         {
62             fprintf(stderr, "sdeventplus: %s: Missing userdata\n", name);
63             return -EINVAL;
64         }
65         Source* source = reinterpret_cast<Source*>(userdata);
66         return internal::performCallback(name, (source->*getter)(),
67                                          std::ref(*source), args...);
68     }
69 
70   private:
71     Callback prepare;
72 
73     void set_userdata();
74     static int prepareCallback(sd_event_source* source, void* userdata);
75 };
76 
77 } // namespace source
78 } // namespace sdeventplus
79