17 #include <sys/epoll.h> 18 #include "eventloopinterface.h" 26 #if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) 27 #define __INCLUDE_LEVEL__ 2 29 #include <systemd/sd-event.h> 34 uint32_t IOEventFlagsToEpollFlags(IOEventFlags flags) {
36 if (flags & IOEventFlag::In) {
39 if (flags & IOEventFlag::Out) {
42 if (flags & IOEventFlag::Err) {
45 if (flags & IOEventFlag::Hup) {
48 if (flags & IOEventFlag::EdgeTrigger) {
54 IOEventFlags EpollFlagsToIOEventFlags(uint32_t flags) {
55 return ((flags & EPOLLIN) ? IOEventFlag::In : IOEventFlags()) |
56 ((flags & EPOLLOUT) ? IOEventFlag::Out : IOEventFlags()) |
57 ((flags & EPOLLERR) ? IOEventFlag::Err : IOEventFlags()) |
58 ((flags & EPOLLHUP) ? IOEventFlag::Hup : IOEventFlags()) |
59 ((flags & EPOLLET) ? IOEventFlag::EdgeTrigger : IOEventFlags());
73 FCITX_NODISCARD std::unique_ptr<EventSourceIO>
74 addIOEvent(
int fd,
IOEventFlags flags, IOCallback callback)
override;
75 FCITX_NODISCARD std::unique_ptr<EventSourceTime>
76 addTimeEvent(clockid_t clock, uint64_t usec, uint64_t accuracy,
77 TimeCallback callback)
override;
78 FCITX_NODISCARD std::unique_ptr<EventSource>
79 addExitEvent(EventCallback callback)
override;
80 FCITX_NODISCARD std::unique_ptr<EventSource>
81 addDeferEvent(EventCallback callback)
override;
82 FCITX_NODISCARD std::unique_ptr<EventSource>
83 addPostEvent(EventCallback callback)
override;
84 FCITX_NODISCARD std::unique_ptr<EventSourceAsync>
85 addAsyncEvent(EventCallback callback)
override;
89 sd_event *event_ =
nullptr;
92 std::unique_ptr<EventLoopInterface> createDefaultEventLoop() {
93 return std::make_unique<EventLoopSDEvent>();
96 const char *defaultEventLoopImplementation() {
return "sd-event"; }
98 template <
typename Interface>
103 sd_event_source_set_enabled(eventSource_, SD_EVENT_OFF);
104 sd_event_source_set_userdata(eventSource_,
nullptr);
105 sd_event_source_unref(eventSource_);
109 void setEventSource(sd_event_source *event) { eventSource_ = event; }
111 bool isEnabled()
const override {
113 if (
int err = sd_event_source_get_enabled(eventSource_, &result);
117 return result != SD_EVENT_OFF;
120 void setEnabled(
bool enabled)
override {
121 sd_event_source_set_enabled(eventSource_,
122 enabled ? SD_EVENT_ON : SD_EVENT_OFF);
125 bool isOneShot()
const override {
127 if (
int err = sd_event_source_get_enabled(eventSource_, &result);
131 return result == SD_EVENT_ONESHOT;
134 void setOneShot()
override {
135 sd_event_source_set_enabled(eventSource_, SD_EVENT_ONESHOT);
139 sd_event_source *eventSource_;
144 : callback_(std::make_shared<EventCallback>(std::move(_callback))) {}
146 std::shared_ptr<EventCallback> callback_;
151 : callback_(std::make_shared<IOCallback>(std::move(_callback))) {}
153 int fd()
const override {
154 int ret = sd_event_source_get_io_fd(eventSource_);
161 void setFd(
int fd)
override {
162 int ret = sd_event_source_set_io_fd(eventSource_, fd);
170 int ret = sd_event_source_get_io_events(eventSource_, &events);
174 return EpollFlagsToIOEventFlags(events);
178 int ret = sd_event_source_set_io_events(
179 eventSource_, IOEventFlagsToEpollFlags(flags));
187 int ret = sd_event_source_get_io_revents(eventSource_, &revents);
191 return EpollFlagsToIOEventFlags(revents);
194 std::shared_ptr<IOCallback> callback_;
199 : callback_(std::make_shared<TimeCallback>(std::move(_callback))) {}
201 uint64_t time()
const override {
203 int err = sd_event_source_get_time(eventSource_, &time);
210 void setTime(uint64_t time)
override {
211 int ret = sd_event_source_set_time(eventSource_, time);
217 uint64_t accuracy()
const override {
219 int err = sd_event_source_get_time_accuracy(eventSource_, &time);
226 void setAccuracy(uint64_t time)
override {
227 int ret = sd_event_source_set_time_accuracy(eventSource_, time);
233 clockid_t clock()
const override {
235 int err = sd_event_source_get_time_clock(eventSource_, &clock);
242 std::shared_ptr<TimeCallback> callback_;
245 EventLoopSDEvent::EventLoopSDEvent() {
246 if (
int rc = sd_event_new(&event_); rc < 0) {
247 throw std::runtime_error(
248 stringutils::concat(
"Create sd_event failed. error code: ", rc));
252 EventLoopSDEvent::~EventLoopSDEvent() { sd_event_unref(event_); };
259 int r = sd_event_loop(event_);
265 int IOEventCallback(sd_event_source * ,
int fd, uint32_t revents,
272 auto callback = source->callback_;
274 (*callback)(source, fd, EpollFlagsToIOEventFlags(revents));
275 return result ? 0 : -1;
276 }
catch (
const std::exception &e) {
277 FCITX_FATAL() << e.what();
282 std::unique_ptr<EventSourceIO>
283 EventLoopSDEvent::addIOEvent(
int fd,
IOEventFlags flags, IOCallback callback) {
284 auto source = std::make_unique<SDEventSourceIO>(std::move(callback));
285 sd_event_source *sdEventSource;
286 if (
int err = sd_event_add_io(event_, &sdEventSource, fd,
287 IOEventFlagsToEpollFlags(flags),
288 IOEventCallback, source.get());
292 source->setEventSource(sdEventSource);
296 int TimeEventCallback(sd_event_source * , uint64_t usec,
303 auto callback = source->callback_;
304 auto result = (*callback)(source, usec);
305 return result ? 0 : -1;
306 }
catch (
const std::exception &e) {
308 FCITX_ERROR() << e.what();
314 std::unique_ptr<EventSourceTime>
315 EventLoopSDEvent::addTimeEvent(clockid_t clock, uint64_t usec,
316 uint64_t accuracy, TimeCallback callback) {
317 auto source = std::make_unique<SDEventSourceTime>(std::move(callback));
318 sd_event_source *sdEventSource;
319 if (
int err = sd_event_add_time(event_, &sdEventSource, clock, usec,
320 accuracy, TimeEventCallback, source.get());
324 source->setEventSource(sdEventSource);
328 int StaticEventCallback(sd_event_source * ,
void *userdata) {
334 auto callback = source->callback_;
335 auto result = (*callback)(source);
336 return result ? 0 : -1;
337 }
catch (
const std::exception &e) {
339 FCITX_ERROR() << e.what();
345 std::unique_ptr<EventSource>
346 EventLoopSDEvent::addExitEvent(EventCallback callback) {
347 auto source = std::make_unique<SDEventSource>(std::move(callback));
348 sd_event_source *sdEventSource;
349 if (
int err = sd_event_add_exit(event_, &sdEventSource, StaticEventCallback,
354 source->setEventSource(sdEventSource);
358 std::unique_ptr<EventSource>
359 EventLoopSDEvent::addDeferEvent(EventCallback callback) {
360 auto source = std::make_unique<SDEventSource>(std::move(callback));
361 sd_event_source *sdEventSource;
362 if (
int err = sd_event_add_defer(event_, &sdEventSource,
363 StaticEventCallback, source.get());
367 source->setEventSource(sdEventSource);
371 std::unique_ptr<EventSource>
372 EventLoopSDEvent::addPostEvent(EventCallback callback) {
373 auto source = std::make_unique<SDEventSource>(std::move(callback));
374 sd_event_source *sdEventSource;
375 if (
int err = sd_event_add_post(event_, &sdEventSource, StaticEventCallback,
380 source->setEventSource(sdEventSource);
388 if (safePipe(selfpipe)) {
391 fd_[0].give(selfpipe[0]);
392 fd_[1].give(selfpipe[1]);
393 ioEvent_ =
event->addIOEvent(
394 fd_[0].fd(), IOEventFlag::In,
395 [
this, callback = std::move(callback)](
EventSource *,
int fd,
405 bool isEnabled()
const override {
return ioEvent_->isEnabled(); }
406 void setEnabled(
bool enabled)
override { ioEvent_->setEnabled(enabled); }
407 bool isOneShot()
const override {
return ioEvent_->isOneShot(); }
408 void setOneShot()
override { ioEvent_->setOneShot(); }
417 std::unique_ptr<EventSourceIO> ioEvent_;
420 std::unique_ptr<EventSourceAsync>
421 EventLoopSDEvent::addAsyncEvent(EventCallback callback) {
422 return std::make_unique<SDEventSourceAsync>(
this, std::move(callback));
Class wrap around the unix fd.
Simple file system related API for checking file status.
void send() override
Trigger the event from other thread.
Utility class to handle unix file descriptor.
void * nativeHandle() override
Return the internal native handle to the event loop.
A thread-safe event source can be triggered from other threads.
bool exec() override
Execute event loop.
ssize_t safeWrite(int fd, const void *data, size_t maxlen)
a simple wrapper around write(), ignore EINTR.
const char * implementation() const override
Return a static implementation name of event loop.
ssize_t safeRead(int fd, void *data, size_t maxlen)
a simple wrapper around read(), ignore EINTR.
void exit() override
Quit event loop.