|
Packit |
086201 |
/*
|
|
Packit |
086201 |
* Copyright 2011 Red Hat, Inc.
|
|
Packit |
086201 |
*
|
|
Packit |
086201 |
* Permission is hereby granted, free of charge, to any person
|
|
Packit |
086201 |
* obtaining a copy of this software and associated documentation files
|
|
Packit |
086201 |
* (the "Software"), to deal in the Software without restriction,
|
|
Packit |
086201 |
* including without limitation the rights to use, copy, modify, merge,
|
|
Packit |
086201 |
* publish, distribute, sublicense, and/or sell copies of the Software,
|
|
Packit |
086201 |
* and to permit persons to whom the Software is furnished to do so,
|
|
Packit |
086201 |
* subject to the following conditions:
|
|
Packit |
086201 |
*
|
|
Packit |
086201 |
* The above copyright notice and this permission notice shall be
|
|
Packit |
086201 |
* included in all copies or substantial portions of the Software.
|
|
Packit |
086201 |
*
|
|
Packit |
086201 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
086201 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
086201 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
086201 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
086201 |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
086201 |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
086201 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
086201 |
* SOFTWARE.
|
|
Packit |
086201 |
*/
|
|
Packit |
086201 |
|
|
Packit |
086201 |
#include <errno.h>
|
|
Packit |
086201 |
|
|
Packit |
086201 |
#include <verto-glib.h>
|
|
Packit |
086201 |
#define VERTO_MODULE_TYPES
|
|
Packit |
086201 |
typedef struct {
|
|
Packit |
086201 |
GMainContext *context;
|
|
Packit |
086201 |
GMainLoop *loop;
|
|
Packit |
086201 |
} verto_mod_ctx;
|
|
Packit |
086201 |
typedef GSource verto_mod_ev;
|
|
Packit |
086201 |
#include <verto-module.h>
|
|
Packit |
086201 |
|
|
Packit |
086201 |
/* While glib has signal support in >=2.29, it does not support many
|
|
Packit |
086201 |
common signals (like USR*). Therefore, signal support is disabled
|
|
Packit |
086201 |
until they support them (should be soonish) */
|
|
Packit |
086201 |
#if GLIB_MAJOR_VERSION >= 999
|
|
Packit |
086201 |
#if GLIB_MINOR_VERSION >= 29
|
|
Packit |
086201 |
#ifdef G_OS_UNIX /* Not supported on Windows */
|
|
Packit |
086201 |
#include <glib-unix.h>
|
|
Packit |
086201 |
#define HAS_SIGNAL VERTO_EV_TYPE_SIGNAL
|
|
Packit |
086201 |
#endif
|
|
Packit |
086201 |
#endif /* GLIB_MINOR_VERSION >= 29 */
|
|
Packit |
086201 |
#endif /* GLIB_MAJOR_VERSION >= 2 */
|
|
Packit |
086201 |
#ifndef HAS_SIGNAL
|
|
Packit |
086201 |
#define HAS_SIGNAL 0
|
|
Packit |
086201 |
#endif
|
|
Packit |
086201 |
|
|
Packit |
086201 |
#define VERTO_GLIB_SUPPORTED_TYPES (VERTO_EV_TYPE_IO \
|
|
Packit |
086201 |
| VERTO_EV_TYPE_TIMEOUT \
|
|
Packit |
086201 |
| VERTO_EV_TYPE_IDLE \
|
|
Packit |
086201 |
| HAS_SIGNAL \
|
|
Packit |
086201 |
| VERTO_EV_TYPE_CHILD)
|
|
Packit |
086201 |
|
|
Packit |
086201 |
typedef gboolean
|
|
Packit |
086201 |
(*GIOCallback)(gpointer data, GIOCondition condition);
|
|
Packit |
086201 |
|
|
Packit |
086201 |
typedef struct GIOSource {
|
|
Packit |
086201 |
GSource source;
|
|
Packit |
086201 |
GPollFD fd;
|
|
Packit |
086201 |
gboolean autoclose;
|
|
Packit |
086201 |
} GIOSource;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static gboolean
|
|
Packit |
086201 |
prepare(GSource *source, gint *timeout)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
(void) source;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
*timeout = -1;
|
|
Packit |
086201 |
return FALSE;
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static gboolean
|
|
Packit |
086201 |
check(GSource *source)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
GIOSource *src = (GIOSource*) source;
|
|
Packit |
086201 |
return src->fd.revents & src->fd.events;
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static gboolean
|
|
Packit |
086201 |
dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
GIOSource *src = (GIOSource*) source;
|
|
Packit |
086201 |
return ((GIOCallback) callback)(user_data, src->fd.revents);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static void
|
|
Packit |
086201 |
finalize(GSource *source)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
GIOSource *src = (GIOSource*) source;
|
|
Packit |
086201 |
if (src->autoclose)
|
|
Packit |
086201 |
close(src->fd.fd);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static GSourceFuncs funcs = { prepare, check, dispatch, finalize, NULL, NULL };
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static void *
|
|
Packit |
086201 |
glib_convert_(GMainContext *mc, GMainLoop *ml)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
verto_mod_ctx *l = NULL;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
l = g_new0(verto_mod_ctx, 1);
|
|
Packit |
086201 |
if (l) {
|
|
Packit |
086201 |
if (mc) {
|
|
Packit |
086201 |
/* Steal references */
|
|
Packit |
086201 |
l->context = mc;
|
|
Packit |
086201 |
l->loop = ml ? ml : g_main_loop_new(l->context, FALSE);
|
|
Packit |
086201 |
|
|
Packit |
086201 |
if (g_main_context_default() == mc)
|
|
Packit |
086201 |
g_main_context_ref(mc);
|
|
Packit |
086201 |
} else {
|
|
Packit |
086201 |
l->context = g_main_context_ref(g_main_context_default());
|
|
Packit |
086201 |
l->loop = g_main_loop_new(l->context, FALSE);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
} else {
|
|
Packit |
086201 |
g_main_loop_unref(ml);
|
|
Packit |
086201 |
g_main_context_unref(mc);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
return l;
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static verto_mod_ctx *
|
|
Packit |
086201 |
glib_ctx_new(void) {
|
|
Packit |
086201 |
return glib_convert_(g_main_context_new(), NULL);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static verto_mod_ctx *
|
|
Packit |
086201 |
glib_ctx_default(void) {
|
|
Packit |
086201 |
return glib_convert_(g_main_context_default(), NULL);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static void
|
|
Packit |
086201 |
glib_ctx_free(verto_mod_ctx *ctx)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
g_main_loop_unref(ctx->loop);
|
|
Packit |
086201 |
g_main_context_unref(ctx->context);
|
|
Packit |
086201 |
g_free(ctx);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static void
|
|
Packit |
086201 |
glib_ctx_run(verto_mod_ctx *ctx)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
g_main_loop_run(ctx->loop);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static void
|
|
Packit |
086201 |
glib_ctx_run_once(verto_mod_ctx *ctx)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
g_main_context_iteration(ctx->context, TRUE);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static gboolean
|
|
Packit |
086201 |
break_callback(gpointer loop)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
g_main_loop_quit(loop);
|
|
Packit |
086201 |
return FALSE;
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static void
|
|
Packit |
086201 |
glib_ctx_break(verto_mod_ctx *ctx)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
GSource *src = g_timeout_source_new(0);
|
|
Packit |
086201 |
g_assert(src);
|
|
Packit |
086201 |
g_source_set_callback(src, break_callback, ctx->loop, NULL);
|
|
Packit |
086201 |
g_source_set_priority(src, G_PRIORITY_HIGH);
|
|
Packit |
086201 |
g_assert(g_source_attach(src, ctx->context) != 0);
|
|
Packit |
086201 |
g_source_unref(src);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static gboolean
|
|
Packit |
086201 |
glib_callback(gpointer data)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
gboolean persists = verto_get_flags(data) & VERTO_EV_FLAG_PERSIST;
|
|
Packit |
086201 |
verto_fire(data);
|
|
Packit |
086201 |
return persists;
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static gboolean
|
|
Packit |
086201 |
glib_callback_io(gpointer data, GIOCondition condition)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
verto_ev_flag state = VERTO_EV_FLAG_NONE;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
if (condition & (G_IO_IN | G_IO_PRI))
|
|
Packit |
086201 |
state |= VERTO_EV_FLAG_IO_READ;
|
|
Packit |
086201 |
if (condition & G_IO_OUT)
|
|
Packit |
086201 |
state |= VERTO_EV_FLAG_IO_WRITE;
|
|
Packit |
086201 |
if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
|
|
Packit |
086201 |
state |= VERTO_EV_FLAG_IO_ERROR;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
verto_set_fd_state(data, state);
|
|
Packit |
086201 |
return glib_callback(data);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static void
|
|
Packit |
086201 |
glib_callback_child(GPid pid, gint status, gpointer data)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
(void) pid;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
verto_set_proc_status(data, status);
|
|
Packit |
086201 |
verto_fire(data);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static void
|
|
Packit |
086201 |
glib_ctx_set_flags(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
(void) ctx;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
if (verto_get_flags(ev) & VERTO_EV_FLAG_PRIORITY_HIGH)
|
|
Packit |
086201 |
g_source_set_priority(evpriv, G_PRIORITY_HIGH);
|
|
Packit |
086201 |
else if (verto_get_flags(ev) & VERTO_EV_FLAG_PRIORITY_MEDIUM)
|
|
Packit |
086201 |
g_source_set_priority(evpriv, G_PRIORITY_DEFAULT_IDLE);
|
|
Packit |
086201 |
else if (verto_get_flags(ev) & VERTO_EV_FLAG_PRIORITY_LOW)
|
|
Packit |
086201 |
g_source_set_priority(evpriv, G_PRIORITY_LOW);
|
|
Packit |
086201 |
|
|
Packit |
086201 |
if (verto_get_type(ev) == VERTO_EV_TYPE_IO) {
|
|
Packit |
086201 |
((GIOSource*) evpriv)->fd.events = 0;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ)
|
|
Packit |
086201 |
((GIOSource*) evpriv)->fd.events |= G_IO_IN | G_IO_PRI | G_IO_ERR |
|
|
Packit |
086201 |
G_IO_HUP | G_IO_NVAL;
|
|
Packit |
086201 |
if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE)
|
|
Packit |
086201 |
((GIOSource*) evpriv)->fd.events |= G_IO_OUT | G_IO_ERR |
|
|
Packit |
086201 |
G_IO_HUP | G_IO_NVAL;
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static verto_mod_ev *
|
|
Packit |
086201 |
glib_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
verto_mod_ev *evpriv = NULL;
|
|
Packit |
086201 |
verto_ev_type type = verto_get_type(ev);
|
|
Packit |
086201 |
|
|
Packit |
086201 |
*flags |= verto_get_flags(ev) & VERTO_EV_FLAG_PERSIST;
|
|
Packit |
086201 |
*flags |= verto_get_flags(ev) & VERTO_EV_FLAG_IO_CLOSE_FD;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
switch (type) {
|
|
Packit |
086201 |
case VERTO_EV_TYPE_IO:
|
|
Packit |
086201 |
evpriv = g_source_new(&funcs, sizeof(GIOSource));
|
|
Packit |
086201 |
if (evpriv) {
|
|
Packit |
086201 |
((GIOSource*) evpriv)->fd.fd = verto_get_fd(ev);
|
|
Packit |
086201 |
((GIOSource*) evpriv)->autoclose =
|
|
Packit |
086201 |
*flags & VERTO_EV_FLAG_IO_CLOSE_FD;
|
|
Packit |
086201 |
g_source_add_poll(evpriv, &((GIOSource*) evpriv)->fd);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
break;
|
|
Packit |
086201 |
case VERTO_EV_TYPE_TIMEOUT:
|
|
Packit |
086201 |
evpriv = g_timeout_source_new(verto_get_interval(ev));
|
|
Packit |
086201 |
break;
|
|
Packit |
086201 |
case VERTO_EV_TYPE_IDLE:
|
|
Packit |
086201 |
evpriv = g_idle_source_new();
|
|
Packit |
086201 |
break;
|
|
Packit |
086201 |
case VERTO_EV_TYPE_CHILD:
|
|
Packit |
086201 |
evpriv = g_child_watch_source_new(verto_get_proc(ev));
|
|
Packit |
086201 |
break;
|
|
Packit |
086201 |
case VERTO_EV_TYPE_SIGNAL:
|
|
Packit |
086201 |
/* While glib has signal support in >=2.29, it does not support many
|
|
Packit |
086201 |
common signals (like USR*). Therefore, signal support is disabled
|
|
Packit |
086201 |
until they support them (should be soonish) */
|
|
Packit |
086201 |
#if GLIB_MAJOR_VERSION >= 999
|
|
Packit |
086201 |
#if GLIB_MINOR_VERSION >= 29
|
|
Packit |
086201 |
#ifdef G_OS_UNIX /* Not supported on Windows */
|
|
Packit |
086201 |
evpriv = g_unix_signal_source_new(verto_get_signal(ev));
|
|
Packit |
086201 |
break;
|
|
Packit |
086201 |
#endif
|
|
Packit |
086201 |
#endif /* GLIB_MINOR_VERSION >= 29 */
|
|
Packit |
086201 |
#endif /* GLIB_MAJOR_VERSION >= 2 */
|
|
Packit |
086201 |
default:
|
|
Packit |
086201 |
return NULL; /* Not supported */
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
if (!evpriv)
|
|
Packit |
086201 |
goto error;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
if (type == VERTO_EV_TYPE_IO)
|
|
Packit |
086201 |
g_source_set_callback(evpriv, (GSourceFunc) glib_callback_io,
|
|
Packit |
086201 |
(void *) ev, NULL);
|
|
Packit |
086201 |
else if (type == VERTO_EV_TYPE_CHILD)
|
|
Packit |
086201 |
g_source_set_callback(evpriv, (GSourceFunc) glib_callback_child,
|
|
Packit |
086201 |
(void *) ev, NULL);
|
|
Packit |
086201 |
else
|
|
Packit |
086201 |
g_source_set_callback(evpriv, glib_callback, (void *) ev, NULL);
|
|
Packit |
086201 |
|
|
Packit |
086201 |
glib_ctx_set_flags(ctx, ev, evpriv);
|
|
Packit |
086201 |
|
|
Packit |
086201 |
g_source_set_can_recurse(evpriv, FALSE);
|
|
Packit |
086201 |
if (g_source_attach(evpriv, ctx->context) == 0)
|
|
Packit |
086201 |
goto error;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
return evpriv;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
error:
|
|
Packit |
086201 |
if (evpriv) {
|
|
Packit |
086201 |
g_source_destroy(evpriv);
|
|
Packit |
086201 |
g_source_unref(evpriv);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
return NULL;
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
static void
|
|
Packit |
086201 |
glib_ctx_del(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
(void) ctx;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
if (!ev)
|
|
Packit |
086201 |
return;
|
|
Packit |
086201 |
|
|
Packit |
086201 |
g_source_destroy(evpriv);
|
|
Packit |
086201 |
g_source_unref(evpriv);
|
|
Packit |
086201 |
}
|
|
Packit |
086201 |
|
|
Packit |
086201 |
#define glib_ctx_reinitialize NULL
|
|
Packit |
086201 |
VERTO_MODULE(glib, g_main_context_default, VERTO_GLIB_SUPPORTED_TYPES);
|
|
Packit |
086201 |
|
|
Packit |
086201 |
verto_ctx *
|
|
Packit |
086201 |
verto_convert_glib(GMainContext *mc, GMainLoop *ml)
|
|
Packit |
086201 |
{
|
|
Packit |
086201 |
return verto_convert(glib, 0, glib_convert_(mc, ml));
|
|
Packit |
086201 |
}
|