2008年2月13日 星期三

Integrate Ecore_main_loop into gMainLoop

If we want to write a program with two kinds of event driven GUI libraries, we have to run each event processing function. There are some ways to do that.

When I was writing a program with EFL and glib, I met this problem.

There are two ways come up to me:
1. Write a multi thread program and each runs a main loop.
2. Put one main loop into another.

When I tried first one by writing two threads to dealing this problem, it works well, but I am very worry about the entropy of this program. It's too high, and complicated. I have to write spin lock to protect data.


static gpointer pk_thread(gpointer data) {
PConnect * pc = (PConnect *)data;
pc->loop = g_main_loop_new (NULL, FALSE);
debug("g_main_loop_run starts\n");
g_main_loop_run(pc->loop);
}

PConnect * pconnect_initial() {
PConnect * pc = (PConnect *)malloc (sizeof(PConnect));
memset(pc, 0, sizeof(PConnect));
if (! g_thread_supported ()) {
g_thread_init (NULL);
}
dbus_g_thread_init();
g_type_init ();
pc->thread = g_thread_create(pk_thread, (gpointer)pc, FALSE, &pc->error);
return pk_dbus_initial(pc);
}


The IPC becomes a nightmare.



After thinking for a while, I tried to merge ecore main loop into glib main loop.
Learning from Integrating QT/GTK
Both Ecore and Glib provides iterator event processing, so that I can wrap the ecore_main_loop_iterate into a GSource.

Make GMainLoop do a ecore_main_loop_iterate() once at each event processing by making preparing and checking always returns true.

Filename: mainlooptesting.c

#include <stdio.h>
#include <glib.h>
#include <Ecore.h>


static gboolean GEvas_prepare (GSource *source, gint *timeout_) {
return TRUE;
}

static gboolean GEvas_check(GSource *source) {
return TRUE;
}

static gboolean GEvas_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) {
ecore_main_loop_iterate ();
return TRUE;
}

static GSourceFuncs Iterator_funcs = {
GEvas_prepare,
GEvas_check,
GEvas_dispatch,
NULL,
NULL,
NULL
};

int evas_timer(void *data) {
printf("evas_timer ran!!!\n");
return 1;
}
gboolean glib_timer(gpointer data) {
printf("glib_timer ran!!!\n");
return TRUE;
}

int main (void) {
GMainContext *context = g_main_context_default();
GSource *source = g_source_new(&Iterator_funcs,sizeof(GSource));
GMainLoop *loop = g_main_loop_new (context,FALSE);
g_source_attach((GSource *)source, context);

ecore_timer_add(1.0f,evas_timer,NULL);
g_timeout_add(500,glib_timer,NULL);

g_main_run(loop);
}


I test each main loop by adding a timer event, and the following are results.
./a.out
glib_timer ran!!!
glib_timer ran!!!
evas_timer ran!!!
glib_timer ran!!!
glib_timer ran!!!
evas_timer ran!!!
glib_timer ran!!!
glib_timer ran!!!
evas_timer ran!!!
glib_timer ran!!!
glib_timer ran!!!
evas_timer ran!!!
^C

Works \^_^/