On Thu, Apr 24, 2008 at 11:15 PM, Gustavo Sverzut Barbieri
<[EMAIL PROTECTED]> wrote:
> On Thu, Apr 24, 2008 at 1:57 PM, Cedric BAIL <[EMAIL PROTECTED]> wrote:
>  > On Wed, Apr 23, 2008 at 4:45 PM, The Rasterman Carsten Haitzler
>  >  <[EMAIL PROTECTED]> wrote:
>  >  > On Tue, 15 Apr 2008 13:15:13 -0300 "Gustavo Sverzut Barbieri"
>  >  >  <[EMAIL PROTECTED]> babbled:
>  >  >  > For simplicity, I would just process one message per callback from
>  >  >  > ecore_fd_main... but we can also use a poll/select inside this
>  >  >  > function and do what you want, without the need to fcntl to
>  >  >  > NONBLOCKING.
>  >  >
>  >  >  just read a buffer of messages - if we don't get a complete message, 
> store the
>  >  >  partial one and keep it until the next call to process events then 
> complete the
>  >  >  message fetch.
>  >
>  >  Ok. Here is an updated patch. The fd is still nonblocking and on
>  >  partial read, it should be able to just restart cleany at a later
>  >  time. You will now pass a function pointer so that you can call
>  >  whatever kind of code you want (I doubt we really need something else
>  >  than evas_object_event_callback). I also make it optional. Some more
>  >  comments ?
>
>  configure: s/build_async/build_async_events/g; make it default on (use
>  "auto" to check for pthread, "yes" would fail without pthread and "no"
>  is... well no).
>
>    +static pthread_mutex_t _mutex;
>
>  i think it's safer to just initialize the mutex here using (and remove
>  the destroy call):
>
>    static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
>
>  evas_async_events_process(void):
>
>    +   if (_fd_read != -1)
>    +     do
>
>  reverse this logic: if (_d_read == -1) return 0;
>  this will avoid the unnecessary nesting and would remove the bug that
>  it have today: "check" might be uninitialized in this function.
>     Actually write the whole function like (more beautiful imho):
>
>    if (_fd_read == -1)
>      return -1;
>
>    count = 0;
>    while ((check = read(_fd_read, ((char *)&current) + size,
>  sizeof(current) - size)) > 0)
>      {
>         size += check;
>         if (size < sizeof(current))
>           continue;
>
>         if (current.func)
>           current.func(current.target, current.type, current.event_info);
>          size = 0;
>           count++;
>      }
>    if (check < 0) {
>        ...;
>        _fd_read = -1;
>    }
>    return count;
>
>
>  For evas_async_events_put, also reverse the logic, I'd write:
>
>    if (!func) return 0;
>    if (_fd_write == -1) return 0;
>
>    ...
>    pthread_mutex_lock(&_mutex);
>    do { ... } while ( ... )
>    pthread_mutex_unlock(&_mutex);
>
>  this would not do unneeded locks and avoid nested code.
>  Also, note that the function return "Evas_Bool" but in the version
>  without BUILD_ASYNC_EVENTS you return -1.
>
>
>  Aside these minor, mostly cosmetic, things, it's ready for inclusion :-)

Thanks a lot for taking the time to do the review. Here is a final
patch, and if nobody oppose, I will commit it during next week.

-- 
Cedric BAIL
diff --git a/configure.in b/configure.in
index a08df81..775394f 100644
--- a/configure.in
+++ b/configure.in
@@ -1129,13 +1129,17 @@ AM_CONDITIONAL(BUILD_LOADER_PMAPS, test x$have_pmaps = xyes)
 pthread_cflags=""
 pthread_libs=""
 build_pthreads="no"
+has_pthreads="no"
 # sched_getaffinity pthread_attr_setaffinity_np
 AC_CHECK_HEADERS(pthread.h sched.h,
       [
         AC_CHECK_LIB(pthread, pthread_attr_setaffinity_np,
           [
             AC_CHECK_LIB(pthread, pthread_barrier_wait,
-              [ build_pthreads="yes" ],
+              [
+	        build_pthreads="yes"
+	      	has_pthreads="yes"
+	      ],
               [ build_pthreads="no" ]
             )
           ],
@@ -1173,6 +1177,26 @@ AC_ARG_ENABLE(pthreads,
 )
 
 #######################################
+## Async events
+build_async_events="auto"
+AC_MSG_CHECKING(whether to build Async Events support)
+AC_ARG_ENABLE(async-events,
+  AC_HELP_STRING([--enable-async-events], [enable async events support]),
+  [ build_async_events=$enableval ]
+)
+AC_MSG_RESULT($build_async_events)
+
+AC_MSG_CHECKING(whether we can build Async Events support)
+if test \( "x$build_async_events" = "xyes" -o "x$build_async_events" = "xauto" \) -a "x$has_pthreads" = "xyes"; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE(BUILD_ASYNC_EVENTS, 1, [Build async events support])
+  build_async_events="yes"
+else
+  AC_MSG_RESULT(no)
+  build_async_events="no"
+fi
+
+#######################################
 ## MMX
 build_cpu_mmx="no"
 case $host_cpu in
@@ -1760,6 +1784,8 @@ echo "  SSE.....................: $build_cpu_sse"
 echo "  ALTIVEC.................: $build_cpu_altivec"
 echo "  Thread Support..........: $build_pthreads"
 echo
+echo "Async Events..............: $build_async_events"
+echo
 echo "ARGB Software Engine Options:"
 echo "  Sampling Scaler.........: $scaler_sample"
 echo "  Smooth Scaler...........: $scaler_smooth"
diff --git a/src/lib/Evas.h b/src/lib/Evas.h
index 22fb29f..18ba377 100644
--- a/src/lib/Evas.h
+++ b/src/lib/Evas.h
@@ -823,6 +823,10 @@ extern "C" {
    EAPI void              evas_object_event_callback_add    (Evas_Object *obj, Evas_Callback_Type type, void (*func) (void *data, Evas *e, Evas_Object *obj, void *event_info), const void *data);
    EAPI void             *evas_object_event_callback_del    (Evas_Object *obj, Evas_Callback_Type type, void (*func) (void *data, Evas *e, Evas_Object *obj, void *event_info));
 
+   EAPI int		  evas_async_events_fd_get          (void);
+   EAPI int		  evas_async_events_process	    (void);
+   EAPI Evas_Bool	  evas_async_events_put             (void *target, Evas_Callback_Type type, void *event_info, void (*func)(void *target, Evas_Callback_Type type, void *event_info));
+
    EAPI void              evas_object_intercept_show_callback_add        (Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), const void *data);
    EAPI void             *evas_object_intercept_show_callback_del        (Evas_Object *obj, void (*func) (void *data, Evas_Object *obj));
    EAPI void              evas_object_intercept_hide_callback_add        (Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), const void *data);
diff --git a/src/lib/canvas/Makefile.am b/src/lib/canvas/Makefile.am
index 9dda0e1..db66ba6 100644
--- a/src/lib/canvas/Makefile.am
+++ b/src/lib/canvas/Makefile.am
@@ -37,6 +37,7 @@ evas_font_dir.c \
 evas_rectangle.c \
 evas_render.c \
 evas_smart.c \
-evas_stack.c
+evas_stack.c \
+evas_async_events.c
 
 libevas_canvas_la_DEPENDENCIES = $(top_builddir)/config.h
diff --git a/src/lib/canvas/evas_async_events.c b/src/lib/canvas/evas_async_events.c
new file mode 100644
index 0000000..069a158
--- /dev/null
+++ b/src/lib/canvas/evas_async_events.c
@@ -0,0 +1,170 @@
+#include "config.h"
+#include "evas_common.h"
+#include "evas_private.h"
+
+#ifdef BUILD_ASYNC_EVENTS
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <errno.h>
+
+static int _fd_write = -1;
+static int _fd_read = -1;
+
+static int _init_evas_event = 0;
+static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
+
+typedef struct _Evas_Event_Async	Evas_Event_Async;
+struct _Evas_Event_Async
+{
+   void			(*func)(void *target, Evas_Callback_Type type, void *event_info);
+   void			 *target;
+   Evas_Callback_Type	  type;
+   void			 *event_info;
+};
+
+#endif
+
+int
+evas_async_events_init(void)
+{
+#ifdef BUILD_ASYNC_EVENTS
+   int filedes[2];
+
+   _init_evas_event++;
+   if (_init_evas_event > 1) return _init_evas_event;
+
+   if (pipe(filedes) == -1)
+     {
+	_init_evas_event = 0;
+	return 0;
+     }
+
+   _fd_read = filedes[0];
+   _fd_write = filedes[1];
+
+   fcntl(_fd_read, F_SETFL, O_NONBLOCK);
+
+   return _init_evas_event;
+#else
+   return 0;
+#endif
+}
+
+int
+evas_async_events_shutdown(void)
+{
+#ifdef BUILD_ASYNC_EVENTS
+   _init_evas_event--;
+   if (_init_evas_event > 0) return _init_evas_event;
+
+   close(_fd_read);
+   close(_fd_write);
+   _fd_read = -1;
+   _fd_write = -1;
+
+   return _init_evas_event;
+#else
+   return 0;
+#endif
+}
+
+EAPI int
+evas_async_events_fd_get(void)
+{
+#ifdef BUILD_ASYNC_EVENTS
+   return _fd_read;
+#else
+   return -1;
+#endif
+}
+
+EAPI int
+evas_async_events_process(void)
+{
+#ifdef BUILD_ASYNC_EVENTS
+   static Evas_Event_Async current;
+   static int size = 0;
+   int check;
+   int count = 0;
+
+   if (_fd_read == -1) return 0;
+
+   do
+     {
+	check = read(_fd_read, ((char*) &current) + size, sizeof(current) - size);
+
+	if (check > 0)
+	  {
+	     size += check;
+	     if (size == sizeof(current))
+	       {
+		  if (current.func) current.func(current.target, current.type, current.event_info);
+		  size = 0;
+		  count++;
+	       }
+	  }
+     }
+   while (check > 0);
+
+   if (check < 0)
+     switch (errno)
+       {
+	case EBADF:
+	case EINVAL:
+	case EIO:
+	case EISDIR:
+	   _fd_read = -1;
+       }
+
+   return count;
+#else
+   return 0;
+#endif
+}
+
+EAPI Evas_Bool
+evas_async_events_put(void *target, Evas_Callback_Type type, void *event_info, void (*func)(void *target, Evas_Callback_Type type, void *event_info))
+{
+#ifdef BUILD_ASYNC_EVENTS
+   Evas_Event_Async new;
+   ssize_t check;
+   int	offset = 0;
+   Evas_Bool result = 0;
+
+   if (!func) return 0;
+   if (_fd_write == -1) return 0;
+
+   new.func = func;
+   new.target = target;
+   new.type = type;
+   new.event_info = event_info;
+
+   pthread_mutex_lock(&_mutex);
+
+   do {
+      check = write(_fd_write, ((char*)&new) + offset, sizeof(new) - offset);
+      offset += check;
+   } while (offset != sizeof(new) && (errno == EINTR || errno == EAGAIN));
+
+   if (offset == sizeof(new))
+     result = 1;
+   else
+     switch (errno)
+       {
+	case EBADF:
+	case EINVAL:
+	case EIO:
+	case EPIPE:
+	   _fd_write = -1;
+       }
+
+   pthread_mutex_unlock(&_mutex);
+
+   return result;
+#else
+   return 0;
+#endif
+}
+
diff --git a/src/lib/include/evas_private.h b/src/lib/include/evas_private.h
index 317e985..e832180 100644
--- a/src/lib/include/evas_private.h
+++ b/src/lib/include/evas_private.h
@@ -828,6 +828,9 @@ void evas_module_use(Evas_Module *em);
 void evas_module_clean(void);
 void evas_module_shutdown(void);
 
+int evas_async_events_init(void);
+int evas_async_events_shutdown(void);
+
 void _evas_walk(Evas *e);
 void _evas_unwalk(Evas *e);
        
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to