#include <murphy/common/mainloop.h>
+static GMutex g_murphy_glue_callback_lock;
+static GMutex g_murphy_glue_internal_lock;
+
+
typedef struct {
GMainLoop *gml;
+ GThread *worker;
} glib_glue_t;
static gboolean io_cb(GIOChannel *ioc, GIOCondition cond, gpointer user_data)
{
+ g_mutex_lock(&g_murphy_glue_callback_lock);
io_t *io = (io_t *)user_data;
mrp_io_event_t events = MRP_IO_EVENT_NONE;
int fd = g_io_channel_unix_get_fd(ioc);
io->cb(io->glue_data, io, fd, events, io->user_data);
+ g_mutex_unlock(&g_murphy_glue_callback_lock);
return TRUE;
}
GIOChannel *ioc;
io_t *io;
+ g_mutex_lock(&g_murphy_glue_internal_lock);
ioc = g_io_channel_unix_new(fd);
- if (ioc == NULL)
+ if (ioc == NULL) {
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
return NULL;
+ }
io = mrp_allocz(sizeof(*io));
io->user_data = user_data;
io->glue_data = glue_data;
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
return io;
}
else {
}
}
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
return NULL;
}
{
io_t *io = (io_t *)id;
+ g_mutex_lock(&g_murphy_glue_internal_lock);
remove_source(glue_data, io->gl_iow);
g_io_channel_unref(io->gl_ioc);
mrp_free(io);
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
}
static gboolean timer_cb(gpointer user_data)
{
- if (user_data == NULL)
+ if (user_data == NULL) {
return FALSE;
+ }
+ g_mutex_lock(&g_murphy_glue_callback_lock);
tmr_t *t = (tmr_t *)user_data;
- if (t->cb == NULL)
+ if (t->cb == NULL) {
+ g_mutex_unlock(&g_murphy_glue_callback_lock);
return FALSE;
+ }
t->cb(t->glue_data, t, t->user_data);
+ g_mutex_unlock(&g_murphy_glue_callback_lock);
return TRUE;
}
{
tmr_t *t;
+ g_mutex_lock(&g_murphy_glue_internal_lock);
t = mrp_allocz(sizeof(*t));
if (t != NULL) {
t->user_data = user_data;
t->glue_data = glue_data;
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
return t;
}
else
mrp_free(t);
}
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
return NULL;
}
{
tmr_t *t = (tmr_t *)id;
+ g_mutex_lock(&g_murphy_glue_internal_lock);
remove_source(glue_data, t->gl_t);
mrp_free(t);
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
}
{
tmr_t *t = (tmr_t *)id;
+ g_mutex_lock(&g_murphy_glue_internal_lock);
if (t != NULL) {
remove_source(glue_data, t->gl_t);
t->gl_t = add_timeout(glue_data, (GSourceFunc)timer_cb, msecs, t);
}
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
}
static gboolean defer_cb(void *user_data)
{
- if (user_data == NULL)
+ if (user_data == NULL) {
return FALSE;
+ }
+ g_mutex_lock(&g_murphy_glue_callback_lock);
dfr_t *d = (dfr_t *)user_data;
- if (d->cb == NULL)
+ if (d->cb == NULL) {
+ g_mutex_unlock(&g_murphy_glue_callback_lock);
return FALSE;
+ }
d->cb(d->glue_data, d, d->user_data);
+ g_mutex_unlock(&g_murphy_glue_callback_lock);
return TRUE;
}
{
dfr_t *d;
+ g_mutex_lock(&g_murphy_glue_internal_lock);
d = mrp_allocz(sizeof(*d));
if (d != NULL) {
d->user_data = user_data;
d->glue_data = glue_data;
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
return d;
}
else
mrp_free(d);
}
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
return NULL;
}
{
dfr_t *d = (dfr_t *)id;
+ g_mutex_lock(&g_murphy_glue_internal_lock);
if (d->gl_t != 0)
remove_source(glue_data, d->gl_t);
mrp_free(d);
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
}
{
dfr_t *d = (dfr_t *)id;
- if (d == NULL)
+ if (d == NULL) {
return;
+ }
+ g_mutex_lock(&g_murphy_glue_internal_lock);
if (enabled && !d->gl_t) {
d->gl_t = add_timeout(glue_data, (GSourceFunc)defer_cb, 0, d);
}
remove_source(glue_data, d->gl_t);
d->gl_t = 0;
}
+ g_mutex_unlock(&g_murphy_glue_internal_lock);
}
static void unregister(void *data)
{
glib_glue_t *glue = (glib_glue_t *)data;
+ GMainContext *def_ctx = g_main_context_default();
+ GMainContext *loop_ctx = g_main_loop_get_context(glue->gml);
+ if (loop_ctx && def_ctx != loop_ctx) {
+ GSource *idle = g_idle_source_new();
+
+ g_source_set_callback(idle, (GSourceFunc) g_main_loop_quit,
+ glue->gml, NULL);
+
+ g_source_attach(idle, g_main_loop_get_context(glue->gml));
+ g_source_unref(idle);
+ g_thread_join(glue->worker);
+ g_thread_unref(glue->worker);
+ glue->worker = NULL;
+ }
- g_main_loop_unref(glue->gml);
+ if (glue->gml) {
+ g_main_loop_unref(glue->gml);
+ glue->gml = NULL;
+ }
mrp_free(glue);
}
.unregister = unregister,
};
+static gpointer
+thread_main (gpointer data)
+{
+ glib_glue_t *glue = (glib_glue_t *)data;
+ GMainContext *thread_main_context = g_main_loop_get_context(glue->gml);
+
+ /* Set up the thread’s context and run it. */
+ g_main_context_push_thread_default (thread_main_context);
+
+ g_main_loop_run (glue->gml);
+
+ g_main_context_pop_thread_default (thread_main_context);
+
+ return NULL;
+}
int mrp_mainloop_register_with_glib(mrp_mainloop_t *ml, GMainLoop *gml)
{
if (glue != NULL) {
glue->gml = g_main_loop_ref(gml);
- if (mrp_set_superloop(ml, &glib_ops, glue))
+ if (mrp_set_superloop(ml, &glib_ops, glue)) {
+ /* Create new thread for context iteration only in case when
+ * glue context isn't default */
+ GMainContext *def_ctx = g_main_context_default();
+ GMainContext *loop_ctx = g_main_loop_get_context(glue->gml);
+ if (loop_ctx && def_ctx != loop_ctx)
+ glue->worker = g_thread_new(NULL, thread_main, glue);
return TRUE;
+ }
else {
g_main_loop_unref(gml);
mrp_free(glue);
return NULL;
}
+
+
+MRP_INIT static void mrp_main_loop_init_lock()
+{
+ g_mutex_init(&g_murphy_glue_callback_lock);
+ g_mutex_init(&g_murphy_glue_internal_lock);
+}
+
+
+MRP_EXIT static void mrp_main_loop_clear_lock()
+{
+ g_mutex_clear(&g_murphy_glue_callback_lock);
+ g_mutex_clear(&g_murphy_glue_internal_lock);
+}