16 #include <sys/epoll.h> 17 #include "eventloopinterface.h" 24 #if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) 25 #define __INCLUDE_LEVEL__ 2 27 #include <systemd/sd-event.h> 32 uint32_t IOEventFlagsToEpollFlags(IOEventFlags flags) {
34 if (flags & IOEventFlag::In) {
37 if (flags & IOEventFlag::Out) {
40 if (flags & IOEventFlag::Err) {
43 if (flags & IOEventFlag::Hup) {
46 if (flags & IOEventFlag::EdgeTrigger) {
52 IOEventFlags EpollFlagsToIOEventFlags(uint32_t flags) {
53 return ((flags & EPOLLIN) ? IOEventFlag::In : IOEventFlags()) |
54 ((flags & EPOLLOUT) ? IOEventFlag::Out : IOEventFlags()) |
55 ((flags & EPOLLERR) ? IOEventFlag::Err : IOEventFlags()) |
56 ((flags & EPOLLHUP) ? IOEventFlag::Hup : IOEventFlags()) |
57 ((flags & EPOLLET) ? IOEventFlag::EdgeTrigger : IOEventFlags());
71 FCITX_NODISCARD std::unique_ptr<EventSourceIO>
72 addIOEvent(
int fd,
IOEventFlags flags, IOCallback callback)
override;
73 FCITX_NODISCARD std::unique_ptr<EventSourceTime>
74 addTimeEvent(clockid_t clock, uint64_t usec, uint64_t accuracy,
75 TimeCallback callback)
override;
76 FCITX_NODISCARD std::unique_ptr<EventSource>
77 addExitEvent(EventCallback callback)
override;
78 FCITX_NODISCARD std::unique_ptr<EventSource>
79 addDeferEvent(EventCallback callback)
override;
80 FCITX_NODISCARD std::unique_ptr<EventSource>
81 addPostEvent(EventCallback callback)
override;
82 FCITX_NODISCARD std::unique_ptr<EventSourceAsync>
83 addAsyncEvent(EventCallback callback)
override;
87 sd_event *event_ =
nullptr;
90 std::unique_ptr<EventLoopInterface> createDefaultEventLoop() {
91 return std::make_unique<EventLoopSDEvent>();
94 const char *defaultEventLoopImplementation() {
return "sd-event"; }
96 template <
typename Interface>
101 sd_event_source_set_enabled(eventSource_, SD_EVENT_OFF);
102 sd_event_source_set_userdata(eventSource_,
nullptr);
103 sd_event_source_unref(eventSource_);
107 void setEventSource(sd_event_source *event) { eventSource_ = event; }
109 bool isEnabled()
const override {
111 if (
int err = sd_event_source_get_enabled(eventSource_, &result);
115 return result != SD_EVENT_OFF;
118 void setEnabled(
bool enabled)
override {
119 sd_event_source_set_enabled(eventSource_,
120 enabled ? SD_EVENT_ON : SD_EVENT_OFF);
123 bool isOneShot()
const override {
125 if (
int err = sd_event_source_get_enabled(eventSource_, &result);
129 return result == SD_EVENT_ONESHOT;
132 void setOneShot()
override {
133 sd_event_source_set_enabled(eventSource_, SD_EVENT_ONESHOT);
137 sd_event_source *eventSource_;
142 : callback_(std::make_shared<EventCallback>(std::move(_callback))) {}
144 std::shared_ptr<EventCallback> callback_;
149 : callback_(std::make_shared<IOCallback>(std::move(_callback))) {}
151 int fd()
const override {
152 int ret = sd_event_source_get_io_fd(eventSource_);
159 void setFd(
int fd)
override {
160 int ret = sd_event_source_set_io_fd(eventSource_, fd);
168 int ret = sd_event_source_get_io_events(eventSource_, &events);
172 return EpollFlagsToIOEventFlags(events);
176 int ret = sd_event_source_set_io_events(
177 eventSource_, IOEventFlagsToEpollFlags(flags));
185 int ret = sd_event_source_get_io_revents(eventSource_, &revents);
189 return EpollFlagsToIOEventFlags(revents);
192 std::shared_ptr<IOCallback> callback_;
197 : callback_(std::make_shared<TimeCallback>(std::move(_callback))) {}
199 uint64_t time()
const override {
201 int err = sd_event_source_get_time(eventSource_, &time);
208 void setTime(uint64_t time)
override {
209 int ret = sd_event_source_set_time(eventSource_, time);
215 uint64_t accuracy()
const override {
217 int err = sd_event_source_get_time_accuracy(eventSource_, &time);
224 void setAccuracy(uint64_t time)
override {
225 int ret = sd_event_source_set_time_accuracy(eventSource_, time);
231 clockid_t clock()
const override {
233 int err = sd_event_source_get_time_clock(eventSource_, &clock);
240 std::shared_ptr<TimeCallback> callback_;
243 EventLoopSDEvent::EventLoopSDEvent() {
244 if (
int rc = sd_event_new(&event_); rc < 0) {
245 throw std::runtime_error(
246 stringutils::concat(
"Create sd_event failed. error code: ", rc));
250 EventLoopSDEvent::~EventLoopSDEvent() { sd_event_unref(event_); };
257 int r = sd_event_loop(event_);
263 int IOEventCallback(sd_event_source * ,
int fd, uint32_t revents,
270 auto callback = source->callback_;
272 (*callback)(source, fd, EpollFlagsToIOEventFlags(revents));
273 return result ? 0 : -1;
274 }
catch (
const std::exception &e) {
275 FCITX_FATAL() << e.what();
280 std::unique_ptr<EventSourceIO>
281 EventLoopSDEvent::addIOEvent(
int fd,
IOEventFlags flags, IOCallback callback) {
282 auto source = std::make_unique<SDEventSourceIO>(std::move(callback));
283 sd_event_source *sdEventSource;
284 if (
int err = sd_event_add_io(event_, &sdEventSource, fd,
285 IOEventFlagsToEpollFlags(flags),
286 IOEventCallback, source.get());
290 source->setEventSource(sdEventSource);
294 int TimeEventCallback(sd_event_source * , uint64_t usec,
301 auto callback = source->callback_;
302 auto result = (*callback)(source, usec);
303 return result ? 0 : -1;
304 }
catch (
const std::exception &e) {
306 FCITX_ERROR() << e.what();
312 std::unique_ptr<EventSourceTime>
313 EventLoopSDEvent::addTimeEvent(clockid_t clock, uint64_t usec,
314 uint64_t accuracy, TimeCallback callback) {
315 auto source = std::make_unique<SDEventSourceTime>(std::move(callback));
316 sd_event_source *sdEventSource;
317 if (
int err = sd_event_add_time(event_, &sdEventSource, clock, usec,
318 accuracy, TimeEventCallback, source.get());
322 source->setEventSource(sdEventSource);
326 int StaticEventCallback(sd_event_source * ,
void *userdata) {
332 auto callback = source->callback_;
333 auto result = (*callback)(source);
334 return result ? 0 : -1;
335 }
catch (
const std::exception &e) {
337 FCITX_ERROR() << e.what();
343 std::unique_ptr<EventSource>
344 EventLoopSDEvent::addExitEvent(EventCallback callback) {
345 auto source = std::make_unique<SDEventSource>(std::move(callback));
346 sd_event_source *sdEventSource;
347 if (
int err = sd_event_add_exit(event_, &sdEventSource, StaticEventCallback,
352 source->setEventSource(sdEventSource);
356 std::unique_ptr<EventSource>
357 EventLoopSDEvent::addDeferEvent(EventCallback callback) {
358 auto source = std::make_unique<SDEventSource>(std::move(callback));
359 sd_event_source *sdEventSource;
360 if (
int err = sd_event_add_defer(event_, &sdEventSource,
361 StaticEventCallback, source.get());
365 source->setEventSource(sdEventSource);
369 std::unique_ptr<EventSource>
370 EventLoopSDEvent::addPostEvent(EventCallback callback) {
371 auto source = std::make_unique<SDEventSource>(std::move(callback));
372 sd_event_source *sdEventSource;
373 if (
int err = sd_event_add_post(event_, &sdEventSource, StaticEventCallback,
378 source->setEventSource(sdEventSource);
386 if (safePipe(selfpipe)) {
389 fd_[0].give(selfpipe[0]);
390 fd_[1].give(selfpipe[1]);
391 ioEvent_ =
event->addIOEvent(
392 fd_[0].fd(), IOEventFlag::In,
393 [
this, callback = std::move(callback)](
EventSource *,
int fd,
403 bool isEnabled()
const override {
return ioEvent_->isEnabled(); }
404 void setEnabled(
bool enabled)
override { ioEvent_->setEnabled(enabled); }
405 bool isOneShot()
const override {
return ioEvent_->isOneShot(); }
406 void setOneShot()
override { ioEvent_->setOneShot(); }
415 std::unique_ptr<EventSourceIO> ioEvent_;
418 std::unique_ptr<EventSourceAsync>
419 EventLoopSDEvent::addAsyncEvent(EventCallback callback) {
420 return std::make_unique<SDEventSourceAsync>(
this, std::move(callback));
Class wrap around the unix fd.
void send() override
Trigger the event from other thread.
Utility class to handle unix file decriptor.
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.