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 *)¤t;
> 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, ¤t, 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