9 #include "event_libuv.h" 10 #include <sys/types.h> 21 #include "eventloopinterface.h" 29 #define FCITX_LIBUV_DEBUG() FCITX_LOGC(::fcitx::libuv_logcategory, Debug) 35 FCITX_DEFINE_LOG_CATEGORY(libuv_logcategory,
"libuv");
39 std::unique_ptr<EventLoopInterface> createDefaultEventLoop() {
40 return std::make_unique<EventLoopLibUV>();
43 const char *defaultEventLoopImplementation() {
return "libuv"; }
45 static int IOEventFlagsToLibUVFlags(IOEventFlags flags) {
47 if (flags & IOEventFlag::In) {
48 result |= UV_READABLE;
50 if (flags & IOEventFlag::Out) {
51 result |= UV_WRITABLE;
53 if (flags & IOEventFlag::Hup) {
54 result |= UV_DISCONNECT;
59 static IOEventFlags LibUVFlagsToIOEventFlags(
int flags) {
60 return ((flags & UV_READABLE) ? IOEventFlag::In : IOEventFlags()) |
61 ((flags & UV_WRITABLE) ? IOEventFlag::Out : IOEventFlags()) |
62 ((flags & UV_DISCONNECT) ? IOEventFlag::Hup : IOEventFlags());
65 void IOEventCallback(uv_poll_t *handle,
int status,
int events);
66 void TimeEventCallback(uv_timer_t *handle);
67 void PostEventCallback(uv_prepare_t *handle);
69 void AsyncEventCallback(uv_async_t *handle) {
70 auto *source =
static_cast<LibUVSourceAsync *
>(
71 static_cast<LibUVSourceBase *
>(handle->data));
73 if (!source->isEnabled()) {
78 auto sourceRef = source->watch();
79 if (source->isOneShot()) {
80 source->setEnabled(
false);
82 auto callback = source->callback_;
83 auto ret = (*callback)(source);
84 if (sourceRef.isValid()) {
86 source->setEnabled(
false);
89 }
catch (
const std::exception &e) {
91 FCITX_FATAL() << e.what();
99 [](uv_handle_t *handle,
void *) {
100 if (handle && !uv_is_closing(handle)) {
102 static_cast<LibUVSourceBase *>(handle->data)->cleanup();
107 int r = uv_loop_close(&loop_);
108 FCITX_DEBUG() <<
"UVLoop close: " << r;
113 r = uv_run(&loop_, UV_RUN_ONCE);
116 r = uv_loop_close(&loop_);
117 FCITX_DEBUG() <<
"UVLoop close r2: " << r;
120 bool LibUVSourceTime::setup(uv_loop_t *loop, uv_timer_t *timer) {
121 if (
int err = uv_timer_init(loop, timer); err < 0) {
122 FCITX_LIBUV_DEBUG() <<
"Failed to init timer with error: " << err;
125 auto curr = now(clock_);
126 uint64_t timeout = time_ > curr ? (time_ - curr) : 0;
128 timeout = timeout / 1000 + (timeout % 1000 != 0);
129 if (
int err = uv_timer_start(timer, &TimeEventCallback, timeout, 0);
131 FCITX_LIBUV_DEBUG() <<
"Failed to start timer with error: " << err;
137 bool LibUVSourcePost::setup(uv_loop_t *loop, uv_prepare_t *prepare) {
138 if (
int err = uv_prepare_init(loop, prepare); err < 0) {
139 FCITX_LIBUV_DEBUG() <<
"Failed to init prepare with error: " << err;
142 if (
int err = uv_prepare_start(prepare, &PostEventCallback); err < 0) {
143 FCITX_LIBUV_DEBUG() <<
"Failed to start prepare with error: " << err;
149 bool LibUVSourceAsync::setup(uv_loop_t *loop, uv_async_t *async) {
150 if (
int err = uv_async_init(loop, async, &AsyncEventCallback); err < 0) {
151 FCITX_LIBUV_DEBUG() <<
"Failed to init async with error: " << err;
158 uv_async_send(reinterpret_cast<uv_async_t *>(handle_));
161 bool LibUVSourceIO::setup(uv_loop_t *loop, uv_poll_t *poll) {
162 if (
int err = uv_poll_init(loop, poll, fd_); err < 0) {
164 <<
"Failed to init poll for fd: " << fd_ <<
" with error: " << err;
167 const auto flags = IOEventFlagsToLibUVFlags(flags_);
168 if (
int err = uv_poll_start(poll, flags, &IOEventCallback); err < 0) {
169 FCITX_LIBUV_DEBUG() <<
"Failed to start poll with error: " << err;
175 EventLoopLibUV::EventLoopLibUV() : loop_(std::make_shared<UVLoop>()) {}
180 return static_cast<uv_loop_t *
>(*loop_);
184 int r = uv_run(*loop_, UV_RUN_DEFAULT);
185 for (
auto iter = exitEvents_.begin(); iter != exitEvents_.end();) {
186 if (
auto *event = iter->get()) {
187 if (event->isEnabled()) {
189 if (event->isOneShot()) {
190 event->setEnabled(
false);
192 event->callback_(event);
193 }
catch (
const std::exception &e) {
195 FCITX_FATAL() << e.what();
199 if (!iter->isValid()) {
200 iter = exitEvents_.erase(iter);
210 void IOEventCallback(uv_poll_t *handle,
int status,
int events) {
213 auto sourceRef = source->watch();
215 if (source->isOneShot()) {
216 source->setEnabled(
false);
218 auto flags = LibUVFlagsToIOEventFlags(events);
220 flags |= IOEventFlag::Err;
222 auto callback = source->callback_;
223 bool ret = (*callback)(source, source->fd(), flags);
224 if (sourceRef.isValid()) {
226 source->setEnabled(
false);
229 }
catch (
const std::exception &e) {
231 FCITX_FATAL() << e.what();
235 std::unique_ptr<EventSourceIO>
236 EventLoopLibUV::addIOEvent(
int fd,
IOEventFlags flags, IOCallback callback) {
238 std::make_unique<LibUVSourceIO>(std::move(callback), loop_, fd, flags);
242 void TimeEventCallback(uv_timer_t *handle) {
247 auto sourceRef = source->watch();
248 if (source->isOneShot()) {
249 source->setEnabled(
false);
251 auto callback = source->callback_;
252 bool ret = (*callback)(source, source->time());
253 if (sourceRef.isValid()) {
255 source->setEnabled(
false);
257 if (source->isEnabled()) {
258 source->resetEvent();
261 }
catch (
const std::exception &e) {
263 FCITX_FATAL() << e.what();
267 std::unique_ptr<EventSourceTime>
268 EventLoopLibUV::addTimeEvent(clockid_t clock, uint64_t usec, uint64_t accuracy,
269 TimeCallback callback) {
270 auto source = std::make_unique<LibUVSourceTime>(std::move(callback), loop_,
271 usec, clock, accuracy);
275 std::unique_ptr<EventSource>
276 EventLoopLibUV::addExitEvent(EventCallback callback) {
277 auto source = std::make_unique<LibUVSourceExit>(std::move(callback));
278 exitEvents_.push_back(source->watch());
282 std::unique_ptr<EventSource>
283 EventLoopLibUV::addDeferEvent(EventCallback callback) {
285 CLOCK_MONOTONIC, 0, 0,
287 return callback(source);
291 void PostEventCallback(uv_prepare_t *handle) {
296 auto sourceRef = source->watch();
297 if (source->isOneShot()) {
298 source->setEnabled(
false);
300 auto callback = source->callback_;
301 auto ret = (*callback)(source);
302 if (sourceRef.isValid()) {
304 source->setEnabled(
false);
307 }
catch (
const std::exception &e) {
309 FCITX_FATAL() << e.what();
313 std::unique_ptr<EventSource>
314 EventLoopLibUV::addPostEvent(EventCallback callback) {
315 auto source = std::make_unique<LibUVSourcePost>(std::move(callback), loop_);
319 std::unique_ptr<EventSourceAsync>
320 EventLoopLibUV::addAsyncEvent(EventCallback callback) {
322 std::make_unique<LibUVSourceAsync>(std::move(callback), loop_);
Utitliy classes for statically tracking the life of a object.
void * nativeHandle() override
Return the internal native handle to the event loop.
void send() override
Trigger the event from other thread.
void exit() override
Quit event loop.
bool exec() override
Execute event loop.
const char * implementation() const override
Return a static implementation name of event loop.