Hi All,

This patch adds some level of thread safety to ecore.
It does not add thread awareness (i.e. adding a timer from a thread will not
wake a sleeping main loop).

In my experience, developers either are ignorant of the problems of threads, 
or expect libraries to magically work with threads.

I understand that some people think that thread safety is not necessary, but
IMO, the performance cost and complexity is easily outweighed by the benefit
of meeting developer expectation.

thanks,

Mike
>From a60fdaaa7830531a974e51cebc6efe45719e17bf Mon Sep 17 00:00:00 2001
From: Mike McCormack <mj.mccorm...@samsung.com>
Date: Wed, 6 Jul 2011 20:20:11 +0900
Subject: [PATCH] ecore: Add basic thread safety

Signed-off-by: Mike McCormack <mj.mccorm...@samsung.com>
---
 ecore/src/lib/ecore/ecore_events.c       |    2 +
 ecore/src/lib/ecore/ecore_idle_enterer.c |    6 +-
 ecore/src/lib/ecore/ecore_idle_exiter.c  |    7 ++-
 ecore/src/lib/ecore/ecore_idler.c        |    7 ++-
 ecore/src/lib/ecore/ecore_main.c         |   87 ++++++++++++++-----
 ecore/src/lib/ecore/ecore_private.h      |    3 +
 ecore/src/lib/ecore/ecore_thread.c       |   27 ++++++
 ecore/src/lib/ecore/ecore_timer.c        |  141 ++++++++++++++++++++----------
 8 files changed, 208 insertions(+), 72 deletions(-)

diff --git a/ecore/src/lib/ecore/ecore_events.c b/ecore/src/lib/ecore/ecore_events.c
index c1f4658..d2ee983 100644
--- a/ecore/src/lib/ecore/ecore_events.c
+++ b/ecore/src/lib/ecore/ecore_events.c
@@ -690,7 +690,9 @@ _ecore_event_call(void)
                        handle_count++;
 
                        eh->references++;
+                       _ecore_unlock();
                        ret = eh->func(eh->data, e->type, e->event);
+                       _ecore_lock();
                        eh->references--;
 
                        if (!ret)
diff --git a/ecore/src/lib/ecore/ecore_idle_enterer.c b/ecore/src/lib/ecore/ecore_idle_enterer.c
index 9802895..9244cc5 100644
--- a/ecore/src/lib/ecore/ecore_idle_enterer.c
+++ b/ecore/src/lib/ecore/ecore_idle_enterer.c
@@ -154,8 +154,12 @@ _ecore_idle_enterer_call(void)
         Ecore_Idle_Enterer *ie = (Ecore_Idle_Enterer *)idle_enterer_current;
         if (!ie->delete_me)
           {
+             Eina_Bool ret;
              ie->references++;
-             if (!ie->func(ie->data))
+             _ecore_unlock();
+             ret = ie->func(ie->data);
+             _ecore_lock();
+             if (!ret)
                {
                   if (!ie->delete_me) ecore_idle_enterer_del(ie);
                }
diff --git a/ecore/src/lib/ecore/ecore_idle_exiter.c b/ecore/src/lib/ecore/ecore_idle_exiter.c
index c8abb87..1006e8d 100644
--- a/ecore/src/lib/ecore/ecore_idle_exiter.c
+++ b/ecore/src/lib/ecore/ecore_idle_exiter.c
@@ -126,8 +126,13 @@ _ecore_idle_exiter_call(void)
         Ecore_Idle_Exiter *ie = (Ecore_Idle_Exiter *)idle_exiter_current;
         if (!ie->delete_me)
           {
+             Eina_Bool ret;
+
              ie->references++;
-             if (!ie->func(ie->data))
+             _ecore_unlock();
+             ret = ie->func(ie->data);
+             _ecore_lock();
+             if (!ret)
                {
                   if (!ie->delete_me) ecore_idle_exiter_del(ie);
                }
diff --git a/ecore/src/lib/ecore/ecore_idler.c b/ecore/src/lib/ecore/ecore_idler.c
index af43c31..db77dcf 100644
--- a/ecore/src/lib/ecore/ecore_idler.c
+++ b/ecore/src/lib/ecore/ecore_idler.c
@@ -160,8 +160,13 @@ _ecore_idler_call(void)
         Ecore_Idler *ie = (Ecore_Idler *)idler_current;
         if (!ie->delete_me)
           {
+             Eina_Bool ret;
+
              ie->references++;
-             if (!ie->func(ie->data))
+             _ecore_unlock();
+             ret = ie->func(ie->data);
+             _ecore_lock();
+             if (!ret)
                {
                   if (!ie->delete_me) ecore_idler_del(ie);
                }
diff --git a/ecore/src/lib/ecore/ecore_main.c b/ecore/src/lib/ecore/ecore_main.c
index 53d7a8a..cf644d6 100644
--- a/ecore/src/lib/ecore/ecore_main.c
+++ b/ecore/src/lib/ecore/ecore_main.c
@@ -488,6 +488,7 @@ _ecore_main_gsource_prepare(GSource *source __UNUSED__, gint *next_time)
 {
    gboolean ready = FALSE;
 
+   _ecore_lock();
    in_main_loop++;
 
    if (!ecore_idling && !_ecore_glib_idle_enterer_called)
@@ -566,6 +567,7 @@ _ecore_main_gsource_prepare(GSource *source __UNUSED__, gint *next_time)
 
    in_main_loop--;
    INF("leave, timeout = %d", *next_time);
+   _ecore_unlock();
 
    /* ready if we're not running (about to quit) */
    return ready;
@@ -576,6 +578,7 @@ _ecore_main_gsource_check(GSource *source __UNUSED__)
 {
    gboolean ret = FALSE;
 
+   _ecore_lock();
    in_main_loop++;
 
    /* check if old timers expired */
@@ -615,6 +618,7 @@ _ecore_main_gsource_check(GSource *source __UNUSED__)
      ret = (0.0 == _ecore_timer_next_get());
 
    in_main_loop--;
+   _ecore_unlock();
 
    return ret;
 }
@@ -626,6 +630,7 @@ _ecore_main_gsource_dispatch(GSource *source __UNUSED__, GSourceFunc callback __
    gboolean events_ready, timers_ready, idlers_ready;
    double next_time;
 
+   _ecore_lock();
    _ecore_time_loop_time = ecore_time_get();
    _ecore_timer_enable_new();
    next_time = _ecore_timer_next_get();
@@ -684,6 +689,7 @@ _ecore_main_gsource_dispatch(GSource *source __UNUSED__, GSourceFunc callback __
      }
 
    in_main_loop--;
+   _ecore_unlock();
 
    return TRUE; /* what should be returned here? */
 }
@@ -822,9 +828,10 @@ _ecore_main_loop_shutdown(void)
 EAPI void
 ecore_main_loop_iterate(void)
 {
-   ECORE_MAIN_LOOP_ASSERT();
 #ifndef USE_G_MAIN_LOOP
+   _ecore_lock();
    _ecore_main_loop_iterate_internal(1);
+   _ecore_unlock();
 #else
    g_main_context_iteration(NULL, 1);
 #endif
@@ -851,12 +858,13 @@ ecore_main_loop_iterate(void)
 EAPI void
 ecore_main_loop_begin(void)
 {
-   ECORE_MAIN_LOOP_ASSERT();
 #ifndef USE_G_MAIN_LOOP
+   _ecore_lock();
    in_main_loop++;
    while (do_quit == 0) _ecore_main_loop_iterate_internal(0);
    do_quit = 0;
    in_main_loop--;
+   _ecore_unlock();
 #else
    ecore_main_loop = g_main_loop_new(NULL, FALSE);
    g_main_loop_run(ecore_main_loop);
@@ -968,11 +976,11 @@ EAPI Ecore_Fd_Handler *
 ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, Ecore_Fd_Cb func, const void *data,
                           Ecore_Fd_Cb buf_func, const void *buf_data)
 {
-   Ecore_Fd_Handler *fdh;
+   Ecore_Fd_Handler *fdh = NULL;
 
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
-   if ((fd < 0) || (flags == 0) || (!func)) return NULL;
+   if ((fd < 0) || (flags == 0) || (!func)) goto unlock;
 
    fdh = calloc(1, sizeof(Ecore_Fd_Handler));
    if (!fdh) return NULL;
@@ -985,7 +993,7 @@ ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, Ecore_Fd_Cb func
         int err = errno;
         ERR("Failed to add poll on fd %d (errno = %d: %s)!", fd, err, strerror(err));
         free(fdh);
-        return NULL;
+        goto unlock;
      }
    fdh->read_active = EINA_FALSE;
    fdh->write_active = EINA_FALSE;
@@ -1000,6 +1008,9 @@ ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, Ecore_Fd_Cb func
    fd_handlers = (Ecore_Fd_Handler *)
       eina_inlist_append(EINA_INLIST_GET(fd_handlers),
                          EINA_INLIST_GET(fdh));
+unlock:
+   _ecore_unlock();
+
    return fdh;
 }
 
@@ -1047,18 +1058,20 @@ ecore_main_win32_handler_add(void *h __UNUSED__, Ecore_Win32_Handle_Cb func __UN
 EAPI void *
 ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   void *ret = NULL;
+
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
      {
         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
                          "ecore_main_fd_handler_del");
-        return NULL;
+        goto unlock;
      }
    if (fd_handler->delete_me)
      {
         ERR("fdh %p deleted twice", fd_handler);
-        return NULL;
+        goto unlock;
      }
 
    _ecore_main_fdh_poll_del(fd_handler);
@@ -1068,7 +1081,10 @@ ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
      fd_handlers_with_prep = eina_list_remove(fd_handlers_with_prep, fd_handler);
    if (fd_handler->buf_func && fd_handlers_with_buffer)
      fd_handlers_with_buffer = eina_list_remove(fd_handlers_with_buffer, fd_handler);
-   return fd_handler->data;
+   ret = fd_handler->data;
+unlock:
+   _ecore_unlock();
+   return ret;
 }
 
 #ifdef _WIN32
@@ -1114,13 +1130,13 @@ ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler __UNUSED__)
 EAPI void
 ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Prep_Cb func, const void *data)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
      {
         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
                          "ecore_main_fd_handler_prepare_callback_set");
-        return;
+        goto unlock;
      }
    fd_handler->prep_func = func;
    fd_handler->prep_data = (void *)data;
@@ -1128,6 +1144,8 @@ ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, Ecore_F
       (fd_handlers_with_prep && (!eina_list_data_find(fd_handlers_with_prep, fd_handler))))
      /* FIXME: THIS WILL NOT SCALE WITH LOTS OF PREP FUNCTIONS!!! */
      fd_handlers_with_prep = eina_list_append(fd_handlers_with_prep, fd_handler);
+unlock:
+   _ecore_unlock();
 }
 
 /**
@@ -1139,13 +1157,20 @@ ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, Ecore_F
 EAPI int
 ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler)
 {
+   int fd = -1;
+
+   _ecore_lock();
+
    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
      {
         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
                          "ecore_main_fd_handler_fd_get");
-        return -1;
+        goto unlock;
      }
-   return fd_handler->fd;
+   fd = fd_handler->fd;
+unlock:
+   _ecore_unlock();
+   return fd;
 }
 
 /**
@@ -1162,17 +1187,19 @@ ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_
 {
    int ret = EINA_FALSE;
 
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
      {
         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
                          "ecore_main_fd_handler_active_get");
-        return EINA_FALSE;
+        goto unlock;
      }
    if ((flags & ECORE_FD_READ) && (fd_handler->read_active)) ret = EINA_TRUE;
    if ((flags & ECORE_FD_WRITE) && (fd_handler->write_active)) ret = EINA_TRUE;
    if ((flags & ECORE_FD_ERROR) && (fd_handler->error_active)) ret = EINA_TRUE;
+unlock:
+   _ecore_unlock();
    return ret;
 }
 
@@ -1187,13 +1214,13 @@ ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_
 {
    int ret;
 
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
      {
         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
                          "ecore_main_fd_handler_active_set");
-        return;
+        goto unlock;
      }
    fd_handler->flags = flags;
    ret = _ecore_main_fdh_poll_modify(fd_handler);
@@ -1201,6 +1228,8 @@ ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_
      {
         ERR("Failed to mod epoll fd %d: %s!", fd_handler->fd, strerror(ret));
      }
+unlock:
+   _ecore_unlock();
 }
 
 /**
@@ -1276,7 +1305,9 @@ _ecore_main_prepare_handlers(void)
         if (!fdh->delete_me && fdh->prep_func)
           {
              fdh->references++;
+             _ecore_unlock();
              fdh->prep_func(fdh->prep_data, fdh);
+             _ecore_lock();
              fdh->references--;
           }
         else
@@ -1424,9 +1455,13 @@ _ecore_main_fd_handlers_bads_rem(void)
              ERR("Found bad fd at index %d", fdh->fd);
              if (fdh->flags & ECORE_FD_ERROR)
                {
+                  Eina_Bool ret;
                   ERR("Fd set for error! calling user");
                   fdh->references++;
-                  if (!fdh->func(fdh->data, fdh))
+                  _ecore_unlock();
+                  ret = fdh->func(fdh->data, fdh);
+                  _ecore_lock();
+                  if (!ret)
                     {
                        ERR("Fd function err returned 0, remove it");
                        if (!fdh->delete_me)
@@ -1546,8 +1581,12 @@ _ecore_main_fd_handlers_call(void)
                  (fdh->write_active) ||
                  (fdh->error_active))
                {
+                  Eina_Bool ret;
                   fdh->references++;
-                  if (!fdh->func(fdh->data, fdh))
+                  _ecore_unlock();
+                  ret = fdh->func(fdh->data, fdh);
+                  _ecore_lock();
+                  if (!ret)
                     {
                        if (!fdh->delete_me)
                          {
@@ -1595,10 +1634,16 @@ _ecore_main_fd_handlers_buf_call(void)
           }
         if ((!fdh->delete_me) && fdh->buf_func)
           {
+             Eina_Bool r;
              fdh->references++;
-             if (fdh->buf_func(fdh->buf_data, fdh))
+             _ecore_unlock();
+             r = fdh->buf_func(fdh->buf_data, fdh);
+             _ecore_lock();
+             if (r)
                {
+                  _ecore_unlock();
                   ret |= fdh->func(fdh->data, fdh);
+                  _ecore_lock();
                   fdh->read_active = EINA_TRUE;
                   _ecore_try_add_to_call_list(fdh);
                }
diff --git a/ecore/src/lib/ecore/ecore_private.h b/ecore/src/lib/ecore/ecore_private.h
index 8e5be10..8dd9e23 100644
--- a/ecore/src/lib/ecore/ecore_private.h
+++ b/ecore/src/lib/ecore/ecore_private.h
@@ -199,6 +199,9 @@ void _ecore_main_loop_shutdown(void);
 
 void _ecore_throttle(void);
 
+void _ecore_lock(void);
+void _ecore_unlock(void);
+
 extern int    _ecore_fps_debug;
 extern double _ecore_time_loop_time;
 extern Eina_Bool _ecore_glib_always_integrate;
diff --git a/ecore/src/lib/ecore/ecore_thread.c b/ecore/src/lib/ecore/ecore_thread.c
index 4449484..dc9ae9a 100644
--- a/ecore/src/lib/ecore/ecore_thread.c
+++ b/ecore/src/lib/ecore/ecore_thread.c
@@ -3,6 +3,7 @@
 #endif
 
 #include <sys/time.h>
+#include <assert.h>
 
 #ifdef HAVE_EVIL
 # include <Evil.h>
@@ -389,6 +390,7 @@ static LRWK(_ecore_thread_global_hash_lock);
 static LK(_ecore_thread_global_hash_mutex);
 static CD(_ecore_thread_global_hash_cond);
 
+static LK(_ecore_main_loop_mutex);
 static Eina_Bool have_main_loop_thread = 0;
 
 static Eina_Trash *_ecore_thread_worker_trash = NULL;
@@ -792,6 +794,7 @@ _ecore_thread_init(void)
    LKI(_ecore_pending_job_threads_mutex);
    LRWKI(_ecore_thread_global_hash_lock);
    LKI(_ecore_thread_global_hash_mutex);
+   LKI(_ecore_main_loop_mutex);
    CDI(_ecore_thread_global_hash_cond);
 #endif
 }
@@ -871,6 +874,30 @@ _ecore_thread_assert_main_loop_thread(const char *function)
      }
 }
 
+static int lock_count;
+
+void
+_ecore_lock(void)
+{
+#ifdef EFL_HAVE_THREADS
+  LKL(_ecore_main_loop_mutex);
+  lock_count++;
+  assert(lock_count == 1);
+  //fprintf(stderr, "lock %d!\n", lock_count);
+#endif
+}
+
+void
+_ecore_unlock(void)
+{
+#ifdef EFL_HAVE_THREADS
+  //fprintf(stderr, "unlock %d!\n", lock_count);
+  lock_count--;
+  assert(lock_count == 0);
+  LKU(_ecore_main_loop_mutex);
+#endif
+}
+
 EAPI Ecore_Thread *
 ecore_thread_run(Ecore_Thread_Cb func_blocking,
                  Ecore_Thread_Cb func_end,
diff --git a/ecore/src/lib/ecore/ecore_timer.c b/ecore/src/lib/ecore/ecore_timer.c
index a4bc1a4..0e7cadb 100644
--- a/ecore/src/lib/ecore/ecore_timer.c
+++ b/ecore/src/lib/ecore/ecore_timer.c
@@ -39,6 +39,7 @@ struct _Ecore_Timer
 
 static void _ecore_timer_set(Ecore_Timer *timer, double at, double in, Ecore_Task_Cb func, void *data);
 static int _ecore_timer_cmp(const void *d1, const void *d2);
+static void *_ecore_timer_del(Ecore_Timer *timer);
 
 static int          timers_added = 0;
 static int          timers_delete_me = 0;
@@ -107,14 +108,17 @@ ecore_timer_precision_get(void)
 EAPI void
 ecore_timer_precision_set(double value)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
    if (value < 0.0)
      {
         ERR("Precision %f less than zero, ignored", value);
-        return;
+        goto unlock;
      }
    precision = value;
+
+unlock:
+   _ecore_unlock();
 }
 
 /**
@@ -139,14 +143,13 @@ EAPI Ecore_Timer *
 ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
 {
    double now;
-   Ecore_Timer *timer;
-
-   ECORE_MAIN_LOOP_ASSERT();
+   Ecore_Timer *timer = NULL;
 
-   if (!func) return NULL;
+   _ecore_lock();
+   if (!func) goto unlock;
    if (in < 0.0) in = 0.0;
    timer = calloc(1, sizeof(Ecore_Timer));
-   if (!timer) return NULL;
+   if (!timer) goto unlock;
    ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
    now = ecore_time_get();
 
@@ -156,6 +159,8 @@ ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
 #endif
 
    _ecore_timer_set(timer, now + in, in, func, (void *)data);
+unlock:
+   _ecore_unlock();
    return timer;
 }
 
@@ -175,14 +180,14 @@ EAPI Ecore_Timer *
 ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data)
 {
    double now;
-   Ecore_Timer *timer;
+   Ecore_Timer *timer = NULL;
 
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
-   if (!func) return NULL;
+   if (!func) goto unlock;
    if (in < 0.0) in = 0.0;
    timer = calloc(1, sizeof(Ecore_Timer));
-   if (!timer) return NULL;
+   if (!timer) goto unlock;
    ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
    now = ecore_loop_time_get();
 
@@ -192,6 +197,8 @@ ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data)
 #endif
 
    _ecore_timer_set(timer, now + in, in, func, (void *)data);
+unlock:
+   _ecore_unlock();
    return timer;
 }
 
@@ -207,32 +214,22 @@ ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data)
 EAPI void *
 ecore_timer_del(Ecore_Timer *timer)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   void *data = NULL;
+
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
      {
         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
                          "ecore_timer_del");
-        return NULL;
+        goto unlock;
      }
 
-   if (timer->frozen && !timer->references)
-     {
-        void *data = timer->data;
-
-        suspended = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
-
-        if (timer->delete_me)
-          timers_delete_me--;
-
-        free(timer);
-        return data;
-     }
+   data = _ecore_timer_del(timer);
 
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(timer->delete_me, NULL);
-   timer->delete_me = 1;
-   timers_delete_me++;
-   return timer->data;
+unlock:
+   _ecore_unlock();
+   return data;
 }
 
 /**
@@ -245,15 +242,17 @@ ecore_timer_del(Ecore_Timer *timer)
 EAPI void
 ecore_timer_interval_set(Ecore_Timer *timer, double in)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
      {
         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
                          "ecore_timer_interval_set");
-        return;
+        goto unlock;
      }
    timer->in = in;
+unlock:
+   _ecore_unlock();
 }
 
 /**
@@ -265,16 +264,22 @@ ecore_timer_interval_set(Ecore_Timer *timer, double in)
 EAPI double
 ecore_timer_interval_get(Ecore_Timer *timer)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   double interval;
+
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
      {
         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
                          "ecore_timer_interval_get");
-        return -1.0;
+        interval = -1.0;
+        goto unlock;
      }
 
-   return timer->in;
+   interval = timer->in;
+unlock:
+   _ecore_unlock();
+   return interval;
 }
 
 /**
@@ -287,13 +292,13 @@ ecore_timer_interval_get(Ecore_Timer *timer)
 EAPI void
 ecore_timer_delay(Ecore_Timer *timer, double add)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
      {
         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
                          "ecore_timer_delay");
-        return;
+        goto unlock;
      }
 
    if (timer->frozen)
@@ -305,6 +310,8 @@ ecore_timer_delay(Ecore_Timer *timer, double add)
         timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
         _ecore_timer_set(timer, timer->at + add, timer->in, timer->func, timer->data);
      }
+unlock:
+   _ecore_unlock();
 }
 
 /**
@@ -317,21 +324,26 @@ EAPI double
 ecore_timer_pending_get(Ecore_Timer *timer)
 {
    double        now;
+   double        ret = 0.0;
 
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
      {
         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
                          "ecore_timer_pending_get");
-        return 0;
+        goto unlock;
      }
 
    now = ecore_time_get();
 
    if (timer->frozen)
-     return timer->pending;
-   return timer->at - now;
+     ret = timer->pending;
+   else
+     ret = timer->at - now;
+unlock:
+   _ecore_unlock();
+   return ret;
 }
 
 /**
@@ -353,18 +365,18 @@ ecore_timer_freeze(Ecore_Timer *timer)
 {
    double now;
 
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
      {
         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
                          "ecore_timer_freeze");
-        return ;
+        goto unlock;
      }
 
    /* Timer already frozen */
    if (timer->frozen)
-     return ;
+     goto unlock;
 
    timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
    suspended = (Ecore_Timer *) eina_inlist_prepend(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
@@ -374,6 +386,8 @@ ecore_timer_freeze(Ecore_Timer *timer)
    timer->pending = timer->at - now;
    timer->at = 0.0;
    timer->frozen = 1;
+unlock:
+   _ecore_unlock();
 }
 
 /**
@@ -394,23 +408,25 @@ ecore_timer_thaw(Ecore_Timer *timer)
 {
    double now;
 
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
      {
         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
                          "ecore_timer_thaw");
-        return ;
+        goto unlock;
      }
 
    /* Timer not frozen */
    if (!timer->frozen)
-     return ;
+     goto unlock;
 
    suspended = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
    now = ecore_time_get();
 
    _ecore_timer_set(timer, timer->pending + now, timer->in, timer->func, timer->data);
+unlock:
+   _ecore_unlock();
 }
 
 EAPI char *
@@ -424,6 +440,7 @@ ecore_timer_dump(void)
    int living_timer = 0;
    int unknow_timer = 0;
 
+   _ecore_lock();
    result = eina_strbuf_new();
 
    EINA_INLIST_FOREACH(timers, tm)
@@ -459,6 +476,7 @@ ecore_timer_dump(void)
 
    out = eina_strbuf_string_steal(result);
    eina_strbuf_free(result);
+   _ecore_unlock();
 
    return out;
 #else
@@ -474,6 +492,28 @@ ecore_timer_dump(void)
  * @}
  */
 
+static void *
+_ecore_timer_del(Ecore_Timer *timer)
+{
+   if (timer->frozen && !timer->references)
+     {
+        void *data = timer->data;
+
+        suspended = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
+
+        if (timer->delete_me)
+          timers_delete_me--;
+
+        free(timer);
+        return data;
+     }
+
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(timer->delete_me, NULL);
+   timer->delete_me = 1;
+   timers_delete_me++;
+   return timer->data;
+}
+
 void
 _ecore_timer_shutdown(void)
 {
@@ -644,6 +684,7 @@ _ecore_timer_reschedule(Ecore_Timer *timer, double when)
      _ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data);
 }
 
+/* assume that we hold the ecore lock when entering this function */
 int
 _ecore_timer_call(double when)
 {
@@ -672,6 +713,7 @@ _ecore_timer_call(double when)
    while (timer_current)
      {
         Ecore_Timer *timer = timer_current;
+        Eina_Bool cont;
 
         if (timer->at > when)
           {
@@ -686,9 +728,12 @@ _ecore_timer_call(double when)
           }
 
         timer->references++;
-        if (!timer->func(timer->data))
+        _ecore_unlock();
+        cont = timer->func(timer->data);
+        _ecore_lock();
+        if (!cont)
           {
-             if (!timer->delete_me) ecore_timer_del(timer);
+             if (!timer->delete_me) _ecore_timer_del(timer);
           }
         timer->references--;
 
-- 
1.7.0.4

------------------------------------------------------------------------------
Got Input?   Slashdot Needs You.
Take our quick survey online.  Come on, we don't ask for help often.
Plus, you'll get a chance to win $100 to spend on ThinkGeek.
http://p.sf.net/sfu/slashdot-survey
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to