From: Mike McCormack <mj.mccormack@samsung.com>
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sat, 14 Aug 2010 11:19:03 +0000 (11:19 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sat, 14 Aug 2010 11:19:03 +0000 (11:19 +0000)
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.

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@51113 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.ac
src/lib/ecore/ecore.c
src/lib/ecore/ecore_main.c
src/lib/ecore/ecore_private.h

index 81049af..03dddf2 100644 (file)
@@ -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
index 9f65413..5bf12bc 100644 (file)
@@ -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"))
index d53218d..3168077 100644 (file)
 # include <sys/epoll.h>
 #endif
 
+#ifdef USE_G_MAIN_LOOP
+#include <glib.h>
+#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,18 +848,10 @@ _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)
           {
              if (fdh->flags & ECORE_FD_READ)
@@ -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
index c3e6725..1708459 100644 (file)
@@ -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;