9 #include "event_libuv.h" 20 #include "eventloopinterface.h" 24 #define FCITX_LIBUV_DEBUG() FCITX_LOGC(::fcitx::libuv_logcategory, Debug) 28 std::unique_ptr<EventLoopInterface> createDefaultEventLoop() {
29 return std::make_unique<EventLoopLibUV>();
32 const char *defaultEventLoopImplementation() {
return "libuv"; }
34 FCITX_DEFINE_LOG_CATEGORY(libuv_logcategory,
"libuv");
36 static int IOEventFlagsToLibUVFlags(IOEventFlags flags) {
38 if (flags & IOEventFlag::In) {
39 result |= UV_READABLE;
41 if (flags & IOEventFlag::Out) {
42 result |= UV_WRITABLE;
44 if (flags & IOEventFlag::Hup) {
45 result |= UV_DISCONNECT;
50 static IOEventFlags LibUVFlagsToIOEventFlags(
int flags) {
51 return ((flags & UV_READABLE) ? IOEventFlag::In : IOEventFlags()) |
52 ((flags & UV_WRITABLE) ? IOEventFlag::Out : IOEventFlags()) |
53 ((flags & UV_DISCONNECT) ? IOEventFlag::Hup : IOEventFlags());
56 void IOEventCallback(uv_poll_t *handle,
int status,
int events);
57 void TimeEventCallback(uv_timer_t *handle);
58 void PostEventCallback(uv_prepare_t *handle);
60 void AsyncEventCallback(uv_async_t *handle) {
61 auto *source =
static_cast<LibUVSourceAsync *
>(
62 static_cast<LibUVSourceBase *
>(handle->data));
64 if (!source->isEnabled()) {
69 auto sourceRef = source->watch();
70 if (source->isOneShot()) {
71 source->setEnabled(
false);
73 auto callback = source->callback_;
74 auto ret = (*callback)(source);
75 if (sourceRef.isValid()) {
77 source->setEnabled(
false);
80 }
catch (
const std::exception &e) {
82 FCITX_FATAL() << e.what();
90 [](uv_handle_t *handle,
void *) {
91 if (handle && !uv_is_closing(handle)) {
93 static_cast<LibUVSourceBase *>(handle->data)->cleanup();
98 int r = uv_loop_close(&loop_);
99 FCITX_DEBUG() <<
"UVLoop close: " << r;
104 r = uv_run(&loop_, UV_RUN_ONCE);
107 r = uv_loop_close(&loop_);
108 FCITX_DEBUG() <<
"UVLoop close r2: " << r;
111 bool LibUVSourceTime::setup(uv_loop_t *loop, uv_timer_t *timer) {
112 if (
int err = uv_timer_init(loop, timer); err < 0) {
113 FCITX_LIBUV_DEBUG() <<
"Failed to init timer with error: " << err;
116 auto curr = now(clock_);
117 uint64_t timeout = time_ > curr ? (time_ - curr) : 0;
119 timeout = timeout / 1000 + (timeout % 1000 != 0);
120 if (
int err = uv_timer_start(timer, &TimeEventCallback, timeout, 0);
122 FCITX_LIBUV_DEBUG() <<
"Failed to start timer with error: " << err;
128 bool LibUVSourcePost::setup(uv_loop_t *loop, uv_prepare_t *prepare) {
129 if (
int err = uv_prepare_init(loop, prepare); err < 0) {
130 FCITX_LIBUV_DEBUG() <<
"Failed to init prepare with error: " << err;
133 if (
int err = uv_prepare_start(prepare, &PostEventCallback); err < 0) {
134 FCITX_LIBUV_DEBUG() <<
"Failed to start prepare with error: " << err;
140 bool LibUVSourceAsync::setup(uv_loop_t *loop, uv_async_t *async) {
141 if (
int err = uv_async_init(loop, async, &AsyncEventCallback); err < 0) {
142 FCITX_LIBUV_DEBUG() <<
"Failed to init async with error: " << err;
149 uv_async_send(reinterpret_cast<uv_async_t *>(handle_));
152 bool LibUVSourceIO::setup(uv_loop_t *loop, uv_poll_t *poll) {
153 if (
int err = uv_poll_init(loop, poll, fd_); err < 0) {
155 <<
"Failed to init poll for fd: " << fd_ <<
" with error: " << err;
158 const auto flags = IOEventFlagsToLibUVFlags(flags_);
159 if (
int err = uv_poll_start(poll, flags, &IOEventCallback); err < 0) {
160 FCITX_LIBUV_DEBUG() <<
"Failed to start poll with error: " << err;
166 EventLoopLibUV::EventLoopLibUV() : loop_(std::make_shared<UVLoop>()) {}
171 return static_cast<uv_loop_t *
>(*loop_);
175 int r = uv_run(*loop_, UV_RUN_DEFAULT);
176 for (
auto iter = exitEvents_.begin(); iter != exitEvents_.end();) {
177 if (
auto *event = iter->get()) {
178 if (event->isEnabled()) {
180 if (event->isOneShot()) {
181 event->setEnabled(
false);
183 event->callback_(event);
184 }
catch (
const std::exception &e) {
186 FCITX_FATAL() << e.what();
190 if (!iter->isValid()) {
191 iter = exitEvents_.erase(iter);
201 void IOEventCallback(uv_poll_t *handle,
int status,
int events) {
204 auto sourceRef = source->watch();
206 if (source->isOneShot()) {
207 source->setEnabled(
false);
209 auto flags = LibUVFlagsToIOEventFlags(events);
211 flags |= IOEventFlag::Err;
213 auto callback = source->callback_;
214 bool ret = (*callback)(source, source->fd(), flags);
215 if (sourceRef.isValid()) {
217 source->setEnabled(
false);
220 }
catch (
const std::exception &e) {
222 FCITX_FATAL() << e.what();
226 std::unique_ptr<EventSourceIO>
227 EventLoopLibUV::addIOEvent(
int fd,
IOEventFlags flags, IOCallback callback) {
229 std::make_unique<LibUVSourceIO>(std::move(callback), loop_, fd, flags);
233 void TimeEventCallback(uv_timer_t *handle) {
238 auto sourceRef = source->watch();
239 if (source->isOneShot()) {
240 source->setEnabled(
false);
242 auto callback = source->callback_;
243 bool ret = (*callback)(source, source->time());
244 if (sourceRef.isValid()) {
246 source->setEnabled(
false);
248 if (source->isEnabled()) {
249 source->resetEvent();
252 }
catch (
const std::exception &e) {
254 FCITX_FATAL() << e.what();
258 std::unique_ptr<EventSourceTime>
259 EventLoopLibUV::addTimeEvent(clockid_t clock, uint64_t usec, uint64_t accuracy,
260 TimeCallback callback) {
261 auto source = std::make_unique<LibUVSourceTime>(std::move(callback), loop_,
262 usec, clock, accuracy);
266 std::unique_ptr<EventSource>
267 EventLoopLibUV::addExitEvent(EventCallback callback) {
268 auto source = std::make_unique<LibUVSourceExit>(std::move(callback));
269 exitEvents_.push_back(source->watch());
273 std::unique_ptr<EventSource>
274 EventLoopLibUV::addDeferEvent(EventCallback callback) {
276 CLOCK_MONOTONIC, 0, 0,
278 return callback(source);
282 void PostEventCallback(uv_prepare_t *handle) {
287 auto sourceRef = source->watch();
288 if (source->isOneShot()) {
289 source->setEnabled(
false);
291 auto callback = source->callback_;
292 auto ret = (*callback)(source);
293 if (sourceRef.isValid()) {
295 source->setEnabled(
false);
298 }
catch (
const std::exception &e) {
300 FCITX_FATAL() << e.what();
304 std::unique_ptr<EventSource>
305 EventLoopLibUV::addPostEvent(EventCallback callback) {
306 auto source = std::make_unique<LibUVSourcePost>(std::move(callback), loop_);
310 std::unique_ptr<EventSourceAsync>
311 EventLoopLibUV::addAsyncEvent(EventCallback callback) {
313 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.