/* * Copyright (c) 2009-2011, Salvatore Sanfilippo * * SPDX-FileCopyrightText: 2024 Hiredict Contributors * SPDX-FileCopyrightText: 2024 Salvatore Sanfilippo * * SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: LGPL-3.0-or-later * */ #ifndef __HIREDICT_GLIB_H__ #define __HIREDICT_GLIB_H__ #include #include "../hiredict.h" #include "../async.h" typedef struct { GSource source; redictAsyncContext *ac; GPollFD poll_fd; } RedictSource; static void redict_source_add_read (gpointer data) { RedictSource *source = (RedictSource *)data; g_return_if_fail(source); source->poll_fd.events |= G_IO_IN; g_main_context_wakeup(g_source_get_context((GSource *)data)); } static void redict_source_del_read (gpointer data) { RedictSource *source = (RedictSource *)data; g_return_if_fail(source); source->poll_fd.events &= ~G_IO_IN; g_main_context_wakeup(g_source_get_context((GSource *)data)); } static void redict_source_add_write (gpointer data) { RedictSource *source = (RedictSource *)data; g_return_if_fail(source); source->poll_fd.events |= G_IO_OUT; g_main_context_wakeup(g_source_get_context((GSource *)data)); } static void redict_source_del_write (gpointer data) { RedictSource *source = (RedictSource *)data; g_return_if_fail(source); source->poll_fd.events &= ~G_IO_OUT; g_main_context_wakeup(g_source_get_context((GSource *)data)); } static void redict_source_cleanup (gpointer data) { RedictSource *source = (RedictSource *)data; g_return_if_fail(source); redict_source_del_read(source); redict_source_del_write(source); /* * It is not our responsibility to remove ourself from the * current main loop. However, we will remove the GPollFD. */ if (source->poll_fd.fd >= 0) { g_source_remove_poll((GSource *)data, &source->poll_fd); source->poll_fd.fd = -1; } } static gboolean redict_source_prepare (GSource *source, gint *timeout_) { RedictSource *redict = (RedictSource *)source; *timeout_ = -1; return !!(redict->poll_fd.events & redict->poll_fd.revents); } static gboolean redict_source_check (GSource *source) { RedictSource *redict = (RedictSource *)source; return !!(redict->poll_fd.events & redict->poll_fd.revents); } static gboolean redict_source_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { RedictSource *redict = (RedictSource *)source; if ((redict->poll_fd.revents & G_IO_OUT)) { redictAsyncHandleWrite(redict->ac); redict->poll_fd.revents &= ~G_IO_OUT; } if ((redict->poll_fd.revents & G_IO_IN)) { redictAsyncHandleRead(redict->ac); redict->poll_fd.revents &= ~G_IO_IN; } if (callback) { return callback(user_data); } return TRUE; } static void redict_source_finalize (GSource *source) { RedictSource *redict = (RedictSource *)source; if (redict->poll_fd.fd >= 0) { g_source_remove_poll(source, &redict->poll_fd); redict->poll_fd.fd = -1; } } static GSource * redict_source_new (redictAsyncContext *ac) { static GSourceFuncs source_funcs = { .prepare = redict_source_prepare, .check = redict_source_check, .dispatch = redict_source_dispatch, .finalize = redict_source_finalize, }; redictContext *c = &ac->c; RedictSource *source; g_return_val_if_fail(ac != NULL, NULL); source = (RedictSource *)g_source_new(&source_funcs, sizeof *source); if (source == NULL) return NULL; source->ac = ac; source->poll_fd.fd = c->fd; source->poll_fd.events = 0; source->poll_fd.revents = 0; g_source_add_poll((GSource *)source, &source->poll_fd); ac->ev.addRead = redict_source_add_read; ac->ev.delRead = redict_source_del_read; ac->ev.addWrite = redict_source_add_write; ac->ev.delWrite = redict_source_del_write; ac->ev.cleanup = redict_source_cleanup; ac->ev.data = source; return (GSource *)source; } #endif /* __HIREDICT_GLIB_H__ */