ecore: add ecore_pipe_wait.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 9 Jun 2011 14:54:24 +0000 (14:54 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 9 Jun 2011 14:54:24 +0000 (14:54 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@60135 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
src/lib/ecore/Ecore.h
src/lib/ecore/ecore_main.c
src/lib/ecore/ecore_pipe.c
src/lib/ecore/ecore_private.h

index 45c2a93..12008fc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
        * Add ecore_pipe_freeze/thaw to suspend and restart watching the pipe
        inside the main loop.
+
+2011-06-09  Cedric Bail
+
+       * Add ecore_pipe_wait (should only called from outside of the main loop).
index 240acf6..19d9540 100644 (file)
@@ -788,6 +788,7 @@ extern "C" {
    EAPI void         ecore_pipe_read_close(Ecore_Pipe *p);
    EAPI void         ecore_pipe_thaw(Ecore_Pipe *p);
    EAPI void         ecore_pipe_freeze(Ecore_Pipe *p);
+   EAPI int          ecore_pipe_wait(Ecore_Pipe *p, int message_count, double wait);
 
   /**
    * @}
index c25e6f7..61556e7 100644 (file)
@@ -147,9 +147,9 @@ static Eina_Bool            win32_handlers_delete_me = EINA_FALSE;
 #endif
 
 #ifdef _WIN32
-static Ecore_Select_Function main_loop_select = _ecore_main_win32_select;
+Ecore_Select_Function main_loop_select = _ecore_main_win32_select;
 #else
-static Ecore_Select_Function main_loop_select = select;
+Ecore_Select_Function main_loop_select = select;
 #endif
 
 #ifndef USE_G_MAIN_LOOP
index 6f4fd2a..eadc561 100644 (file)
@@ -5,6 +5,28 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
+#include <math.h>
+
+#ifdef HAVE_ISFINITE
+# define ECORE_FINITE(t) isfinite(t)
+#else
+# ifdef _MSC_VER
+#  define ECORE_FINITE(t) _finite(t)
+# else
+#  define ECORE_FINITE(t) finite(t)
+# endif
+#endif
+
+#define FIX_HZ 1
+
+#ifdef FIX_HZ
+# ifndef _MSC_VER
+#  include <sys/param.h>
+# endif
+# ifndef HZ
+#  define HZ 100
+# endif
+#endif
 
 #ifdef HAVE_EVIL
 # include <Evil.h>
@@ -60,6 +82,7 @@ struct _Ecore_Pipe
    int               handling;
    size_t            already_read;
    void             *passed_data;
+   int               message;
    Eina_Bool         delete_me : 1;
 };
 
@@ -414,6 +437,94 @@ ecore_pipe_thaw(Ecore_Pipe *p)
 }
 
 /**
+ * @brief Wait from another thread on the read side of a pipe.
+ *
+ * @param p The pipe to watch on.
+ * @param message_count The minimal number of message to wait before exiting.
+ * @param wait The amount of time in second to wait before exiting.
+ * @return the number of message catched during that wait call.
+ *
+ * Negative value for @p wait means infite wait.
+ */
+EAPI int
+ecore_pipe_wait(Ecore_Pipe *p, int message_count, double wait)
+{
+   struct timeval tv, *t;
+   fd_set rset;
+   double end = 0.0;
+   double timeout;
+   int ret;
+   int total = 0;
+
+   if (p->fd_read == PIPE_FD_INVALID)
+     return -1;
+
+   FD_ZERO(&rset);
+   FD_SET(p->fd_read, &rset);
+
+   if (wait >= 0.0)
+     end = ecore_time_get() + wait;
+   timeout = wait;
+
+   while (message_count > 0 && (timeout > 0.0 || wait <= 0.0))
+     {
+        if (wait >= 0.0)
+          {
+             /* finite() tests for NaN, too big, too small, and infinity.  */
+             if ((!ECORE_FINITE(timeout)) || (timeout == 0.0))
+               {
+                  tv.tv_sec = 0;
+                  tv.tv_usec = 0;
+               }
+             else if (timeout > 0.0)
+               {
+                  int sec, usec;
+#ifdef FIX_HZ
+                  timeout += (0.5 / HZ);
+                  sec = (int)timeout;
+                  usec = (int)((timeout - (double)sec) * 1000000);
+#else
+                  sec = (int)timeout;
+                  usec = (int)((timeout - (double)sec) * 1000000);
+#endif
+                  tv.tv_sec = sec;
+                  tv.tv_usec = usec;
+               }
+             t = &tv;
+          }
+        else
+          {
+             t = NULL;
+          }
+
+        ret = main_loop_select(p->fd_read + 1, &rset, NULL, NULL, t);
+
+        if (ret > 0)
+          {
+             _ecore_pipe_read(p, NULL);
+             message_count -= p->message;
+             total += p->message;
+             p->message = 0;
+          }
+        else if (ret == 0)
+          {
+             break;
+          }
+        else if (errno != EINTR)
+          {
+             close(p->fd_read);
+             p->fd_read = PIPE_FD_INVALID;
+             break;
+          }
+
+        if (wait >= 0.0)
+          timeout = end - ecore_time_get();
+     }
+
+   return total;
+}
+
+/**
  * Close the write end of an Ecore_Pipe object created with ecore_pipe_add().
  *
  * @param p The Ecore_Pipe object.
@@ -642,6 +753,7 @@ _ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
              p->passed_data = NULL;
              p->already_read = 0;
              p->len = 0;
+             p->message++;
           }
         else if (ret >= 0)
           {
index 7e2afa0..a0a000b 100644 (file)
@@ -198,5 +198,6 @@ void _ecore_main_loop_shutdown(void);
 extern int    _ecore_fps_debug;
 extern double _ecore_time_loop_time;
 extern Eina_Bool _ecore_glib_always_integrate;
+extern Ecore_Select_Function main_loop_select;
 
 #endif