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