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 \^_^/
1 則留言:
Although this way we can run GMainLoop and e_main_loop in the same thread and at the same time, GMainLoop has to polling all the time. It will cost a lot CPU power. I don't think it's good enough as a library usage.
But if you does not care about a program is always polling, it work normally so far as I see.
張貼留言