#define MURPHY_LOOP_WAIT_TIME_THREAD 1
-static GMutex g_murphy_glue_callback_lock;
-static GMutex g_murphy_glue_internal_lock;
-static GCond g_murphy_loop_cond;
-
typedef struct {
GMainLoop *gml;
GThread *worker;
+ GMutex glue_callback_lock;
+ GMutex glue_internal_lock;
+ GCond loop_cond;
+ gint ref_count;
} glib_glue_t;
static guint add_io_watch(void *glue_data, GSourceFunc cb, GIOCondition mask, GIOChannel *ioc, void *user_data);
static void remove_source(void *glue_data, guint id);
+static glib_glue_t* glue_new()
+{
+ glib_glue_t *glue = NULL;
+ glue = mrp_allocz(sizeof(*glue));
+ if (NULL != glue) {
+ g_mutex_init(&glue->glue_callback_lock);
+ g_mutex_init(&glue->glue_internal_lock);
+ g_cond_init(&glue->loop_cond);
+ glue->ref_count = 1;
+ }
+ return glue;
+}
+
+static glib_glue_t* glue_ref(glib_glue_t *glue)
+{
+ g_return_val_if_fail(glue != NULL, NULL);
+ g_return_val_if_fail(g_atomic_int_get(&glue->ref_count) > 0, NULL);
+
+ g_atomic_int_inc(&glue->ref_count);
+
+ return glue;
+}
+
+static void glue_unref(glib_glue_t *glue)
+{
+ g_return_if_fail(glue != NULL);
+ g_return_if_fail(g_atomic_int_get(&glue->ref_count) > 0);
+
+ if (!g_atomic_int_dec_and_test(&glue->ref_count))
+ return;
+
+ g_mutex_clear(&glue->glue_callback_lock);
+ g_mutex_clear(&glue->glue_internal_lock);
+ g_cond_clear(&glue->loop_cond);
+ mrp_free(glue);
+}
+
static guint add_timeout(void *glue_data, GSourceFunc cb, unsigned int msecs, void *user_data)
{
guint id = 0;
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;
+ glib_glue_t *glue = (glib_glue_t *)io->glue_data;
+ glue_ref(glue);
+ g_mutex_lock(&glue->glue_callback_lock);
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);
+ g_mutex_unlock(&glue->glue_callback_lock);
+ glue_unref(glue);
return TRUE;
}
GIOCondition mask = 0;
GIOChannel *ioc;
io_t *io;
+ glib_glue_t *glue = (glib_glue_t *)glue_data;
- g_mutex_lock(&g_murphy_glue_internal_lock);
+ g_mutex_lock(&glue->glue_internal_lock);
ioc = g_io_channel_unix_new(fd);
if (ioc == NULL) {
- g_mutex_unlock(&g_murphy_glue_internal_lock);
+ g_mutex_unlock(&glue->glue_internal_lock);
return NULL;
}
io->user_data = user_data;
io->glue_data = glue_data;
- g_mutex_unlock(&g_murphy_glue_internal_lock);
+ g_mutex_unlock(&glue->glue_internal_lock);
return io;
}
else {
}
}
- g_mutex_unlock(&g_murphy_glue_internal_lock);
+ g_mutex_unlock(&glue->glue_internal_lock);
return NULL;
}
static void del_io(void *glue_data, void *id)
{
io_t *io = (io_t *)id;
+ glib_glue_t *glue = (glib_glue_t *)glue_data;
- g_mutex_lock(&g_murphy_glue_internal_lock);
+ g_mutex_lock(&glue->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);
+ g_mutex_unlock(&glue->glue_internal_lock);
}
return FALSE;
}
- g_mutex_lock(&g_murphy_glue_callback_lock);
tmr_t *t = (tmr_t *)user_data;
+ glib_glue_t *glue = (glib_glue_t *)t->glue_data;
+ glue_ref(glue);
+ g_mutex_lock(&glue->glue_callback_lock);
if (t->cb == NULL) {
- g_mutex_unlock(&g_murphy_glue_callback_lock);
+ g_mutex_unlock(&glue->glue_callback_lock);
+ glue_unref(glue);
return FALSE;
}
t->cb(t->glue_data, t, t->user_data);
- g_mutex_unlock(&g_murphy_glue_callback_lock);
+ g_mutex_unlock(&glue->glue_callback_lock);
+ glue_unref(glue);
return TRUE;
}
void *user_data)
{
tmr_t *t;
+ glib_glue_t *glue = (glib_glue_t *)glue_data;
- g_mutex_lock(&g_murphy_glue_internal_lock);
+ g_mutex_lock(&glue->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);
+ g_mutex_unlock(&glue->glue_internal_lock);
return t;
}
else
mrp_free(t);
}
- g_mutex_unlock(&g_murphy_glue_internal_lock);
+ g_mutex_unlock(&glue->glue_internal_lock);
return NULL;
}
static void del_timer(void *glue_data, void *id)
{
tmr_t *t = (tmr_t *)id;
+ glib_glue_t *glue = (glib_glue_t *)glue_data;
- g_mutex_lock(&g_murphy_glue_internal_lock);
+ g_mutex_lock(&glue->glue_internal_lock);
remove_source(glue_data, t->gl_t);
mrp_free(t);
- g_mutex_unlock(&g_murphy_glue_internal_lock);
+ g_mutex_unlock(&glue->glue_internal_lock);
}
static void mod_timer(void *glue_data, void *id, unsigned int msecs)
{
tmr_t *t = (tmr_t *)id;
+ glib_glue_t *glue = (glib_glue_t *)glue_data;
- g_mutex_lock(&g_murphy_glue_internal_lock);
+ g_mutex_lock(&glue->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);
+ g_mutex_unlock(&glue->glue_internal_lock);
}
return FALSE;
}
- g_mutex_lock(&g_murphy_glue_callback_lock);
dfr_t *d = (dfr_t *)user_data;
+ glib_glue_t *glue = (glib_glue_t *)d->glue_data;
+ glue_ref(glue);
+ g_mutex_lock(&glue->glue_callback_lock);
if (d->cb == NULL) {
- g_mutex_unlock(&g_murphy_glue_callback_lock);
+ g_mutex_unlock(&glue->glue_callback_lock);
+ glue_unref(glue);
return FALSE;
}
d->cb(d->glue_data, d, d->user_data);
- g_mutex_unlock(&g_murphy_glue_callback_lock);
+ g_mutex_unlock(&glue->glue_callback_lock);
+ glue_unref(glue);
return TRUE;
}
void *user_data)
{
dfr_t *d;
+ glib_glue_t *glue = (glib_glue_t *)glue_data;
- g_mutex_lock(&g_murphy_glue_internal_lock);
+ g_mutex_lock(&glue->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);
+ g_mutex_unlock(&glue->glue_internal_lock);
return d;
}
else
mrp_free(d);
}
- g_mutex_unlock(&g_murphy_glue_internal_lock);
+ g_mutex_unlock(&glue->glue_internal_lock);
return NULL;
}
static void del_defer(void *glue_data, void *id)
{
dfr_t *d = (dfr_t *)id;
+ glib_glue_t *glue = (glib_glue_t *)glue_data;
- g_mutex_lock(&g_murphy_glue_internal_lock);
+ g_mutex_lock(&glue->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);
+ g_mutex_unlock(&glue->glue_internal_lock);
}
static void mod_defer(void *glue_data, void *id, int enabled)
{
dfr_t *d = (dfr_t *)id;
+ glib_glue_t *glue = (glib_glue_t *)glue_data;
if (d == NULL) {
return;
}
- g_mutex_lock(&g_murphy_glue_internal_lock);
+ g_mutex_lock(&glue->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);
+ g_mutex_unlock(&glue->glue_internal_lock);
}
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);
- g_mutex_lock(&g_murphy_glue_internal_lock);
+ g_mutex_lock(&glue->glue_internal_lock);
if (loop_ctx && def_ctx != loop_ctx) {
GSource *idle = g_idle_source_new();
gint64 end_time = 0;
g_source_attach(idle, g_main_loop_get_context(glue->gml));
g_source_unref(idle);
end_time = g_get_monotonic_time() + MURPHY_LOOP_WAIT_TIME_THREAD * G_TIME_SPAN_SECOND;
- if (g_cond_wait_until(&g_murphy_loop_cond, &g_murphy_glue_internal_lock, end_time)) {
+ if (g_cond_wait_until(&glue->loop_cond, &glue->glue_internal_lock, end_time)) {
g_thread_join(glue->worker);
glue->worker = NULL;
}
glue->gml = NULL;
}
- mrp_free(glue);
- g_mutex_unlock(&g_murphy_glue_internal_lock);
+ g_mutex_unlock(&glue->glue_internal_lock);
+ glue_unref(glue);
}
g_main_context_pop_thread_default (thread_main_context);
- g_mutex_lock(&g_murphy_glue_internal_lock);
- g_cond_signal(&g_murphy_loop_cond);
- g_mutex_unlock(&g_murphy_glue_internal_lock);
+ g_mutex_lock(&glue->glue_internal_lock);
+ g_cond_signal(&glue->loop_cond);
+ g_mutex_unlock(&glue->glue_internal_lock);
return NULL;
}
{
glib_glue_t *glue;
- glue = mrp_allocz(sizeof(*glue));
+ glue = glue_new();
if (glue != NULL) {
glue->gml = g_main_loop_ref(gml);
if (loop_ctx && def_ctx != loop_ctx) {
glue->worker = g_thread_try_new(NULL, thread_main, glue, NULL);
if (glue->worker == NULL) {
- g_main_loop_unref(gml);
- mrp_free(glue);
+ mrp_log_error("Thread creation failed");
return FALSE;
}
}
return TRUE;
}
- else {
- g_main_loop_unref(gml);
- mrp_free(glue);
- }
+ mrp_log_error("Failed to set operation to superloop");
+ g_main_loop_unref(gml);
+ glue_unref(glue);
}
return FALSE;
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);
- g_cond_init(&g_murphy_loop_cond);
-}
-
-
-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);
- g_cond_clear(&g_murphy_loop_cond);
-}