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