1 #include <cerrno>
2 #include <cstdio>
3 #include <exception>
4 #include <sdeventplus/exception.hpp>
5 #include <sdeventplus/internal/sdevent.hpp>
6 #include <sdeventplus/source/base.hpp>
7 #include <stdexcept>
8 #include <type_traits>
9 #include <utility>
10 
11 namespace sdeventplus
12 {
13 namespace source
14 {
15 
16 Base::~Base()
17 {
18     if (source)
19     {
20         set_enabled(SD_EVENT_OFF);
21     }
22 }
23 
24 int Base::prepareCallback()
25 {
26     try
27     {
28         prepare(*this);
29         return 0;
30     }
31     catch (const std::system_error& e)
32     {
33         fprintf(stderr, "sdeventplus: prepareCallback: %s\n", e.what());
34         return -e.code().value();
35     }
36     catch (const std::exception& e)
37     {
38         fprintf(stderr, "sdeventplus: prepareCallback: %s\n", e.what());
39         return -ENOSYS;
40     }
41     catch (...)
42     {
43         fprintf(stderr, "sdeventplus: prepareCallback: Unknown error\n");
44         return -ENOSYS;
45     }
46 }
47 
48 sd_event_source* Base::get() const
49 {
50     return source.get();
51 }
52 
53 const Event& Base::get_event() const
54 {
55     return event;
56 }
57 
58 const char* Base::get_description() const
59 {
60     const char* description;
61     int r = event.getSdEvent()->sd_event_source_get_description(source.get(),
62                                                                 &description);
63     if (r < 0)
64     {
65         throw SdEventError(-r, "sd_event_source_get_description");
66     }
67     return description;
68 }
69 
70 void Base::set_description(const char* description) const
71 {
72     int r = event.getSdEvent()->sd_event_source_set_description(source.get(),
73                                                                 description);
74     if (r < 0)
75     {
76         throw SdEventError(-r, "sd_event_source_set_description");
77     }
78 }
79 
80 static int prepare_callback(sd_event_source*, void* userdata)
81 {
82     if (userdata == nullptr)
83     {
84         fprintf(stderr, "sdeventplus: prepare_callback: Missing userdata\n");
85         return -EINVAL;
86     }
87     return reinterpret_cast<Base*>(userdata)->prepareCallback();
88 }
89 
90 void Base::set_prepare(Callback&& callback)
91 {
92     int r = event.getSdEvent()->sd_event_source_set_prepare(
93         source.get(), callback ? prepare_callback : nullptr);
94     if (r < 0)
95     {
96         prepare = nullptr;
97         throw SdEventError(-r, "sd_event_source_set_prepare");
98     }
99     prepare = std::move(callback);
100 }
101 
102 const Base::Callback& Base::get_prepare() const
103 {
104     return prepare;
105 }
106 
107 int Base::get_pending() const
108 {
109     int r = event.getSdEvent()->sd_event_source_get_pending(source.get());
110     if (r < 0)
111     {
112         throw SdEventError(-r, "sd_event_source_get_pending");
113     }
114     return r;
115 }
116 
117 int64_t Base::get_priority() const
118 {
119     int64_t priority;
120     int r = event.getSdEvent()->sd_event_source_get_priority(source.get(),
121                                                              &priority);
122     if (r < 0)
123     {
124         throw SdEventError(-r, "sd_event_source_get_priority");
125     }
126     return priority;
127 }
128 
129 void Base::set_priority(int64_t priority) const
130 {
131     int r = event.getSdEvent()->sd_event_source_set_priority(source.get(),
132                                                              priority);
133     if (r < 0)
134     {
135         throw SdEventError(-r, "sd_event_source_set_priority");
136     }
137 }
138 
139 int Base::get_enabled() const
140 {
141     int enabled;
142     int r =
143         event.getSdEvent()->sd_event_source_get_enabled(source.get(), &enabled);
144     if (r < 0)
145     {
146         throw SdEventError(-r, "sd_event_source_get_enabled");
147     }
148     return enabled;
149 }
150 
151 void Base::set_enabled(int enabled) const
152 {
153     int r =
154         event.getSdEvent()->sd_event_source_set_enabled(source.get(), enabled);
155     if (r < 0)
156     {
157         throw SdEventError(-r, "sd_event_source_set_enabled");
158     }
159 }
160 
161 Base::Base(const Event& event, sd_event_source* source) :
162     event(event),
163     source(source, &internal::SdEvent::sd_event_source_ref,
164            &internal::SdEvent::sd_event_source_unref, event.getSdEvent())
165 {
166 }
167 
168 Base::Base(const Event& event, sd_event_source* source, std::false_type) :
169     event(event), source(source, &internal::SdEvent::sd_event_source_ref,
170                          &internal::SdEvent::sd_event_source_unref,
171                          std::false_type(), event.getSdEvent())
172 {
173 }
174 
175 Base& Base::operator=(Base&& other)
176 {
177     if (this != &other)
178     {
179         // We need to make sure our current event is not triggered
180         // after it gets deleted in the move
181         if (source)
182         {
183             set_enabled(SD_EVENT_OFF);
184         }
185 
186         event = std::move(other.event);
187         source = std::move(other.source);
188         prepare = std::move(other.prepare);
189     }
190     return *this;
191 }
192 
193 } // namespace source
194 } // namespace sdeventplus
195