On Tue, Apr 8, 2008 at 7:02 PM, Gustavo Sverzut Barbieri
<[EMAIL PROTECTED]> wrote:
> On Tue, Apr 8, 2008 at 11:05 AM, Cedric BAIL <[EMAIL PROTECTED]> wrote:
>  > Hi,
>  >
>  >    This patch doesn't break anything at this time :-) It's a
>  >  standalone feature that just add the possibility to evas to receive
>  >  events from another thread. It introduce 3 new API.

>  I'm not sure the fd must be set to non-block, this might cause more
>  trouble than good. I'd make it blocker for now and handle things
>  properly using select(), or believe that when the file descriptor is
>  ready to read (from ecore_fd_main...) we can read everything (ie: no
>  partial writes, no threads will die with incomplete writes).

I would like to have more opinion on that matter. I still like the
idea of non blocking as it give the possibility to call
evas_async_events_process from pure evas program.

>  >  * Retrieve the fd that need to be monitored by ecore :
>  >  EAPI int evas_async_events_fd_get();
>  missing (void)

>  >  * Process all pending event in the pipe (This function could be called
>  >  without any event in the pipe) :
>  >  EAPI int evas_async_events_process();
>  missing (void), also true for init, shutdown...

Oops !

>  also, "do ... while (check == sizeof(current))" logic is wrong, you
>  should "check += read(..., todo)" and also change where to load the
>  rest of it.
>
>  Actually I would rewrite it as:
>
>  int todo = sizeof(current);
>  char *p = (char *)&current;
>  do
>   {
>      int n;
>      n = read(_fd_read, p, todo);
>      if (n == -1)
>        {
>          if (errno == EAGAIN || errno == EINTR)
>            continue;
>          else
>            HANDLE_ERROR();
>        }
>      todo -= n;
>      p += n;
>   } while (todo > 0)

I guess it will not work with non blocking fd. I did correct it by
taking non blocking fd into account.

>  >  * Push an event inside the pipe from another thread :
>  >  EAPI Evas_Bool evas_async_events_put(Evas_Object *obj,
>  >  Evas_Callback_Type type, void *event_info);

>  Write logic is also wrong.
>
>    &new + offset
>
>  given that new is of type Evas_Event_Async is not what you want. This
>  pointer arithmetic is like vector indexing, so it would be like:
>
>     new[offset]
>
>  You need to cast it to some type that is the size of a byte, like char:
>
>     ((char *)&new) + offset
>
>  is fine. But I would rewrite it like I did for read.

Oops, corrected.

>  >  I currently don't have any code using it, but I plan to use this for
>  >  the coming background loading of image. So please review it.

>  done :-)

Thanks a lot for this good and fast review !

>  I'm not sure about evas_init() doing this. Nothing against it, but
>  maybe some purist wouldn't like to have pthread mutexes created.

I arleady though about some other possibilities :
 - make it optional in configure
 - only start it when required, but that's much more complex
 - only initialise it from required sub system (like later the cache
subsystem), but this will render useless the call to
evas_async_events_process in some case.

So more opinion are welcome :-) And for keeping you interested to the
subject, here is the updated patch.

-- 
Cedric BAIL
diff --git a/src/lib/Evas.h b/src/lib/Evas.h
index e78e9a9..e1e05a1 100644
--- a/src/lib/Evas.h
+++ b/src/lib/Evas.h
@@ -815,6 +815,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             (Evas_Object *obj, 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..117ef0f
--- /dev/null
+++ b/src/lib/canvas/evas_async_events.c
@@ -0,0 +1,128 @@
+#include "evas_common.h"
+#include "evas_private.h"
+
+#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;
+
+typedef struct _Evas_Event_Async	Evas_Event_Async;
+struct _Evas_Event_Async
+{
+   Evas_Object		*obj;
+   Evas_Callback_Type	 type;
+   void			*event_info;
+};
+
+int
+evas_async_events_init(void)
+{
+   if (_init_evas_event++ == 0)
+     {
+	int	filedes[2];
+
+	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);
+
+	pthread_mutex_init(&_mutex, NULL);
+     }
+
+   return _init_evas_event;
+}
+
+int
+evas_async_events_shutdown(void)
+{
+   if (--_init_evas_event == 0)
+     {
+	close(_fd_read);
+	close(_fd_write);
+	_fd_read = -1;
+	_fd_write = -1;
+
+	pthread_mutex_destroy(&_mutex);
+     }
+
+   return _init_evas_event;
+}
+
+EAPI int
+evas_async_events_fd_get(void)
+{
+   return _fd_read;
+}
+
+EAPI int
+evas_async_events_process(void)
+{
+   Evas_Event_Async	current;
+   int			check;
+   int			size = 0;
+   int			count = 0;
+
+   if (_fd_read != -1)
+     do
+       {
+	  check = read(_fd_read, &current, sizeof(current) - size);
+
+	  if (check > 0)
+	    {
+	       size += check;
+	       if (size == sizeof(current))
+		 {
+		    size = 0;
+		    count++;
+		    evas_object_event_callback_call(current.obj, current.type, current.event_info);
+		 }
+	    }
+       }
+     while (check > 0 || errno == EINTR);
+
+   return count;
+}
+
+EAPI Evas_Bool
+evas_async_events_put(Evas_Object *obj, Evas_Callback_Type type, void *event_info)
+{
+   Evas_Event_Async	new;
+   Evas_Bool		result;
+
+   result = 0;
+
+   new.obj = obj;
+   new.type = type;
+   new.event_info = event_info;
+
+   pthread_mutex_lock(&_mutex);
+   if (_fd_write != -1)
+     {
+	ssize_t	check;
+	int	offset = 0;
+
+	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;
+     }
+   pthread_mutex_unlock(&_mutex);
+
+   return result;
+}
+
diff --git a/src/lib/canvas/evas_main.c b/src/lib/canvas/evas_main.c
index 7313a33..ca1b8dc 100644
--- a/src/lib/canvas/evas_main.c
+++ b/src/lib/canvas/evas_main.c
@@ -7,8 +7,12 @@ static int initcount = 0;
 EAPI int
 evas_init(void)
 {
+   if (evas_async_events_init() == 0)
+     return 0;
+
    if (initcount == 0)
      evas_module_init();
+
    return ++initcount;
 }
 
@@ -22,6 +26,7 @@ evas_shutdown(void)
 	evas_common_shutdown();
 	evas_module_shutdown();
      }
+   evas_async_events_shutdown();
    return initcount;
 }
 
diff --git a/src/lib/include/evas_private.h b/src/lib/include/evas_private.h
index 5927d25..5afc647 100644
--- a/src/lib/include/evas_private.h
+++ b/src/lib/include/evas_private.h
@@ -795,6 +795,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