diff --git a/legacy/ecore/ChangeLog b/legacy/ecore/ChangeLog index 45c2a93529..12008fc80b 100644 --- a/legacy/ecore/ChangeLog +++ b/legacy/ecore/ChangeLog @@ -210,3 +210,7 @@ * 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). diff --git a/legacy/ecore/src/lib/ecore/Ecore.h b/legacy/ecore/src/lib/ecore/Ecore.h index 240acf609d..19d9540ecd 100644 --- a/legacy/ecore/src/lib/ecore/Ecore.h +++ b/legacy/ecore/src/lib/ecore/Ecore.h @@ -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); /** * @} diff --git a/legacy/ecore/src/lib/ecore/ecore_main.c b/legacy/ecore/src/lib/ecore/ecore_main.c index c25e6f78a3..61556e76dc 100644 --- a/legacy/ecore/src/lib/ecore/ecore_main.c +++ b/legacy/ecore/src/lib/ecore/ecore_main.c @@ -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 diff --git a/legacy/ecore/src/lib/ecore/ecore_pipe.c b/legacy/ecore/src/lib/ecore/ecore_pipe.c index 6f4fd2a5d9..eadc5615b1 100644 --- a/legacy/ecore/src/lib/ecore/ecore_pipe.c +++ b/legacy/ecore/src/lib/ecore/ecore_pipe.c @@ -5,6 +5,28 @@ #include #include #include +#include + +#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 +# endif +# ifndef HZ +# define HZ 100 +# endif +#endif #ifdef HAVE_EVIL # include @@ -60,6 +82,7 @@ struct _Ecore_Pipe int handling; size_t already_read; void *passed_data; + int message; Eina_Bool delete_me : 1; }; @@ -413,6 +436,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(). * @@ -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) { diff --git a/legacy/ecore/src/lib/ecore/ecore_private.h b/legacy/ecore/src/lib/ecore/ecore_private.h index 7e2afa0872..a0a000bf77 100644 --- a/legacy/ecore/src/lib/ecore/ecore_private.h +++ b/legacy/ecore/src/lib/ecore/ecore_private.h @@ -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