From 3bdbb34d643161c30ef7c50b1ee8cfac4f4e4cba Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Sat, 14 Aug 2010 11:19:03 +0000 Subject: [PATCH] From: Mike McCormack This patch implements the ecore main loop in terms of the GTK main loop, so ecore is a layer on top of glib. Compared the the current glib integration in ecore, this has the added advantage of allowing use of EFL libraries in GTK. SVN revision: 51113 --- legacy/ecore/configure.ac | 16 ++ legacy/ecore/src/lib/ecore/ecore.c | 5 +- legacy/ecore/src/lib/ecore/ecore_main.c | 253 +++++++++++++++++++-- legacy/ecore/src/lib/ecore/ecore_private.h | 3 + 4 files changed, 257 insertions(+), 20 deletions(-) diff --git a/legacy/ecore/configure.ac b/legacy/ecore/configure.ac index 81049af986..03dddf226a 100644 --- a/legacy/ecore/configure.ac +++ b/legacy/ecore/configure.ac @@ -247,6 +247,21 @@ AC_ARG_ENABLE(glib-integration-always, if test "x${want_glib_integration_always}" = "xyes" ; then AC_DEFINE([GLIB_INTEGRATION_ALWAYS], [1], [Always integrate glib if support compiled]) + want_glib=yes +fi + +want_g_main_loop=no +AC_ARG_ENABLE(g-main-loop, + AC_HELP_STRING([--enable-g-main-loop], [ecore_main_loop based on g_main_loop]), + [want_g_main_loop=$enableval]) + +if test "x${want_g_main_loop}" = "xyes" ; then + AC_DEFINE([USE_G_MAIN_LOOP], [1], [Use g_main_loop in ecore]) + want_glib=yes +fi + +if test "x${want_glib_integration_always}" = "xyes" -a "x${want_g_main_loop}" = "xyes"; then + AC_MSG_ERROR([--enable-glib-integration-always and --enable-glib-main-loop are mutually exclusive]) fi # abstract sockets (ecore_con.c) @@ -1393,6 +1408,7 @@ echo " Ecore........................: always" echo " Thread support.............: $have_pthread" echo " GLib support...............: $have_glib" echo " Always integrate GLib......: $want_glib_integration_always" +echo " Use g_main_loop............: $want_g_main_loop" echo " Gathering memory statistic.: $have_mallinfo" echo " Ecore_Con....................: $have_ecore_con" if test "x$have_ecore_con" = "xyes" ; then diff --git a/legacy/ecore/src/lib/ecore/ecore.c b/legacy/ecore/src/lib/ecore/ecore.c index 9f654131b3..5bf12bc10d 100644 --- a/legacy/ecore/src/lib/ecore/ecore.c +++ b/legacy/ecore/src/lib/ecore/ecore.c @@ -111,13 +111,13 @@ ecore_init(void) } if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1; if (_ecore_fps_debug) _ecore_fps_debug_init(); + _ecore_main_loop_init(); _ecore_signal_init(); _ecore_exe_init(); _ecore_thread_init(); _ecore_glib_init(); _ecore_job_init(); _ecore_loop_time = ecore_time_get(); - _ecore_main_loop_init(); #if HAVE_MALLINFO if (getenv("ECORE_MEM_STAT")) @@ -127,7 +127,7 @@ ecore_init(void) } #endif -#ifdef GLIB_INTEGRATION_ALWAYS +#if defined(GLIB_INTEGRATION_ALWAYS) if (_ecore_glib_always_integrate) ecore_main_loop_glib_integrate(); #endif @@ -172,6 +172,7 @@ ecore_shutdown(void) _ecore_event_shutdown(); _ecore_main_shutdown(); _ecore_signal_shutdown(); + _ecore_main_loop_shutdown(); #if HAVE_MALLINFO if (getenv("ECORE_MEM_STAT")) diff --git a/legacy/ecore/src/lib/ecore/ecore_main.c b/legacy/ecore/src/lib/ecore/ecore_main.c index d53218d2de..31680771b2 100644 --- a/legacy/ecore/src/lib/ecore/ecore_main.c +++ b/legacy/ecore/src/lib/ecore/ecore_main.c @@ -53,6 +53,10 @@ # include #endif +#ifdef USE_G_MAIN_LOOP +#include +#endif + struct _Ecore_Fd_Handler { EINA_INLIST; @@ -87,13 +91,16 @@ struct _Ecore_Win32_Handler static int _ecore_main_select(double timeout); +static void _ecore_main_prepare_handlers(void); static void _ecore_main_fd_handlers_cleanup(void); #ifndef _WIN32 static void _ecore_main_fd_handlers_bads_rem(void); #endif static void _ecore_main_fd_handlers_call(void); static int _ecore_main_fd_handlers_buf_call(void); +#ifndef USE_G_MAIN_LOOP static void _ecore_main_loop_iterate_internal(int once_only); +#endif #ifdef _WIN32 static int _ecore_main_win32_select(int nfds, fd_set *readfds, fd_set *writefds, @@ -125,14 +132,14 @@ static double t2 = 0.0; static int epoll_fd = -1; #endif -void _ecore_main_loop_init(void) -{ -#ifdef HAVE_EPOLL - epoll_fd = epoll_create(1); - if (epoll_fd < 0) - CRIT("Failed to create epoll fd!"); +#ifdef USE_G_MAIN_LOOP +static GSource *ecore_epoll_source; +static GPollFD ecore_epoll_fd; +static guint ecore_epoll_id; +static GMainLoop* ecore_main_loop; +static gboolean ecore_idling; +static gboolean ecore_fds_ready; #endif -} static inline int _ecore_poll_events_from_fdh(Ecore_Fd_Handler *fdh) { @@ -226,10 +233,194 @@ static inline int _ecore_main_fdh_epoll_mark_active(void) fdh->error_active = 1; } - return 0; + return ret; } #endif +#ifdef USE_G_MAIN_LOOP + +/* like we are about to enter main_loop_select in _ecore_main_select */ +static gboolean +_ecore_main_gsource_prepare(GSource *source, gint *next_time) +{ + double t = _ecore_timer_next_get(); + gboolean running; + + INF("enter, next timeout in %.1f", t); + in_main_loop++; + + if (!ecore_idling) + { + while (_ecore_timer_call(_ecore_loop_time)); + _ecore_timer_cleanup(); + + /* when idling, busy loop checking the fds only */ + if (!ecore_idling) _ecore_idle_enterer_call(); + } + + /* don't check fds if somebody quit */ + running = g_main_loop_is_running(ecore_main_loop); + if (running) + { + /* only set idling state in dispatch */ + if (ecore_idling && !_ecore_idler_exist()) + { + if (_ecore_timers_exists()) + { + double t = _ecore_timer_next_get(); + *next_time = (t / 1000.0); + } + else + *next_time = -1; + } + else + *next_time = 0; + + _ecore_main_prepare_handlers(); + } + + in_main_loop--; + INF("leave, timeout = %d", *next_time); + + /* ready if we're not running (about to quit) */ + return !running; +} + +static gboolean +_ecore_main_gsource_check(GSource *source) +{ + INF("enter"); + in_main_loop++; + + ecore_fds_ready = (_ecore_main_fdh_epoll_mark_active() > 0); + _ecore_main_fd_handlers_cleanup(); + + _ecore_loop_time = ecore_time_get(); + _ecore_timer_enable_new(); + + in_main_loop--; + INF("leave"); + + return TRUE; /* always dispatch */ +} + +/* like we just came out of main_loop_select in _ecore_main_select */ +static gboolean +_ecore_main_gsource_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) +{ + gboolean events_ready, timers_ready, idlers_ready, signals_ready; + double next_time = _ecore_timer_next_get(); + + events_ready = _ecore_event_exist(); + timers_ready = _ecore_timers_exists() && (0.0 <= next_time); + idlers_ready = _ecore_idler_exist(); + signals_ready = (_ecore_signal_count_get() > 0); + + in_main_loop++; + INF("enter idling=%d fds=%d events=%d signals=%d timers=%d (next=%.2f) idlers=%d", + ecore_idling, ecore_fds_ready, events_ready, signals_ready, + _ecore_timers_exists(), next_time, idlers_ready); + + if (ecore_idling && events_ready) + { + INF("calling idle exiters"); + _ecore_idle_exiter_call(); + ecore_idling = 0; + } + else if (!ecore_idling && !events_ready) + { + INF("start idling"); + ecore_idling = 1; + } + + if (ecore_idling) + { + INF("calling idler"); + _ecore_idler_call(); + + events_ready = _ecore_event_exist(); + timers_ready = _ecore_timers_exists() && (0.0 <= next_time); + idlers_ready = _ecore_idler_exist(); + + if ((ecore_fds_ready || events_ready || timers_ready || idlers_ready || signals_ready)) + { + INF("calling idle exiters"); + _ecore_idle_exiter_call(); + ecore_idling = 0; + } + } + + /* process events */ + if (!ecore_idling) + { + INF("work"); + _ecore_main_fd_handlers_call(); + _ecore_main_fd_handlers_buf_call(); + while (_ecore_signal_count_get()) _ecore_signal_call(); + _ecore_event_call(); + _ecore_main_fd_handlers_cleanup(); + } + + in_main_loop--; + + INF("leave"); + + return TRUE; /* what should be returned here? */ +} + +static void +_ecore_main_gsource_finalize(GSource *source) +{ + INF("finalize"); +} + +static GSourceFuncs ecore_gsource_funcs = { + .prepare = _ecore_main_gsource_prepare, + .check = _ecore_main_gsource_check, + .dispatch = _ecore_main_gsource_dispatch, + .finalize = _ecore_main_gsource_finalize, +}; + +#endif + +void +_ecore_main_loop_init(void) +{ + INF("enter"); +#ifdef HAVE_EPOLL + epoll_fd = epoll_create(1); + if (epoll_fd < 0) + CRIT("Failed to create epoll fd!"); +#endif + +#ifdef USE_G_MAIN_LOOP + ecore_epoll_source = g_source_new(&ecore_gsource_funcs, sizeof (GSource)); + if (!ecore_epoll_source) + CRIT("Failed to create glib source for epoll!"); + ecore_epoll_fd.fd = epoll_fd; + ecore_epoll_fd.events = G_IO_IN; + ecore_epoll_fd.revents = 0; + g_source_add_poll(ecore_epoll_source, &ecore_epoll_fd); + ecore_epoll_id = g_source_attach(ecore_epoll_source, NULL); + if (ecore_epoll_id <= 0) + CRIT("Failed to attach glib source to default context"); +#endif + INF("leave"); +} + +void +_ecore_main_loop_shutdown(void) +{ +#ifdef USE_G_MAIN_LOOP + g_source_destroy(ecore_epoll_source); +#endif + +#ifdef HAVE_EPOLL + close(epoll_fd); +#endif +} + + /** * @defgroup Ecore_Main_Loop_Group Main Loop Functions * @@ -258,7 +449,11 @@ static inline int _ecore_main_fdh_epoll_mark_active(void) EAPI void ecore_main_loop_iterate(void) { +#ifndef USE_G_MAIN_LOOP _ecore_main_loop_iterate_internal(1); +#else + g_main_context_iteration(NULL, 1); +#endif } /** @@ -271,10 +466,15 @@ ecore_main_loop_iterate(void) EAPI void ecore_main_loop_begin(void) { +#ifndef USE_G_MAIN_LOOP in_main_loop++; while (do_quit == 0) _ecore_main_loop_iterate_internal(0); do_quit = 0; in_main_loop--; +#else + ecore_main_loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(ecore_main_loop); +#endif } /** @@ -285,7 +485,13 @@ ecore_main_loop_begin(void) EAPI void ecore_main_loop_quit(void) { +#ifndef USE_G_MAIN_LOOP do_quit = 1; +#else + INF("enter"); + g_main_loop_quit(ecore_main_loop); + INF("leave"); +#endif } /** @@ -372,7 +578,7 @@ ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, Ecore_Fd_Cb func fdh->flags = flags; if (0 > _ecore_main_fdh_epoll_add(fdh)) { - ERR("Failed to add epoll fd %d!", fd); + ERR("Failed to add epoll fd %d (errno = %d)!", fd, errno); free(fdh); return NULL; } @@ -587,6 +793,23 @@ _ecore_main_shutdown(void) #endif } +static void +_ecore_main_prepare_handlers(void) +{ + Ecore_Fd_Handler *fdh; + + /* call the prepare callback for all handlers */ + EINA_INLIST_FOREACH(fd_handlers, fdh) + { + if (!fdh->delete_me && fdh->prep_func) + { + fdh->references++; + fdh->prep_func (fdh->prep_data, fdh); + fdh->references--; + } + } +} + static int _ecore_main_select(double timeout) { @@ -625,16 +848,8 @@ _ecore_main_select(double timeout) FD_ZERO(&exfds); /* call the prepare callback for all handlers */ + _ecore_main_prepare_handlers(); #ifndef HAVE_EPOLL - EINA_INLIST_FOREACH(fd_handlers, fdh) - { - if ((!fdh->delete_me) && (fdh->prep_func)) - { - fdh->references++; - fdh->prep_func(fdh->prep_data, fdh); - fdh->references--; - } - } EINA_INLIST_FOREACH(fd_handlers, fdh) { if (!fdh->delete_me) @@ -886,6 +1101,7 @@ _ecore_main_fd_handlers_buf_call(void) return ret; } +#ifndef USE_G_MAIN_LOOP static void _ecore_main_loop_iterate_internal(int once_only) { @@ -1034,6 +1250,7 @@ _ecore_main_loop_iterate_internal(int once_only) if (once_only) _ecore_idle_enterer_call(); in_main_loop--; } +#endif #ifdef _WIN32 static int diff --git a/legacy/ecore/src/lib/ecore/ecore_private.h b/legacy/ecore/src/lib/ecore/ecore_private.h index c3e6725d77..170845941b 100644 --- a/legacy/ecore/src/lib/ecore/ecore_private.h +++ b/legacy/ecore/src/lib/ecore/ecore_private.h @@ -196,6 +196,9 @@ void _ecore_glib_shutdown(void); void _ecore_job_init(void); void _ecore_job_shutdown(void); +void _ecore_main_loop_init(void); +void _ecore_main_loop_shutdown(void); + extern int _ecore_fps_debug; extern double _ecore_loop_time; extern Eina_Bool _ecore_glib_always_integrate;