ecore: Add main loop thread safety
authormike_m <mike_m@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 28 Jul 2011 12:01:16 +0000 (12:01 +0000)
committermike_m <mike_m@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 28 Jul 2011 12:01:16 +0000 (12:01 +0000)
Thread safety is disabled by default.
Enable it with --enable-thread-safety

Should cover timers, events, animators, idlers and fd handlers.

Tested with Enlightenment and elementary_test.

Signed-off-by: Mike McCormack <mj.mccormack@samsung.com>
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@61851 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.ac
src/lib/ecore/ecore_anim.c
src/lib/ecore/ecore_events.c
src/lib/ecore/ecore_idle_enterer.c
src/lib/ecore/ecore_idle_exiter.c
src/lib/ecore/ecore_idler.c
src/lib/ecore/ecore_main.c
src/lib/ecore/ecore_private.h
src/lib/ecore/ecore_signal.c
src/lib/ecore/ecore_thread.c
src/lib/ecore/ecore_timer.c

index db0f34e..fa7ab9d 100644 (file)
@@ -1161,6 +1161,22 @@ EFL_CHECK_THREADS(
    ],
    [have_threads="no"])
 
+### enable thread safety if we have threads, unless specifically asked not to
+if test "x${have_threads}" = "xno"
+then
+  want_thread_safety="no"
+else
+  want_thread_safety="no"  # to be changed to yes when ready
+  AC_ARG_ENABLE(thread-safety,
+    AC_HELP_STRING([--enable-thread-safety], [enable or disable thread safety]),
+    [want_thread_safety=$enableval])
+fi
+
+if test "x${want_thread_safety}" = "xyes"
+then
+   AC_DEFINE([HAVE_THREAD_SAFETY], [1], [Define to enable thread safety])
+fi
+
 ### Checks for types
 AC_CHECK_SIZEOF(int, 4)
 AC_CHECK_SIZEOF(long, 4)
@@ -1706,6 +1722,7 @@ echo " Core:"
 echo
 echo "  Ecore........................: always"
 echo "    Thread support.............: $have_threads"
+echo "    Thread safety..............: $want_thread_safety"
 echo "    GLib support...............: $have_glib"
 echo "    Always integrate GLib......: $want_glib_integration_always"
 echo "    Use g_main_loop............: $want_g_main_loop"
index 8aa36bb..e795b46 100644 (file)
@@ -54,10 +54,10 @@ _begin_tick(void)
              double t_loop = ecore_loop_time_get();
              double sync_0 = 0.0;
              double d = -fmod(t_loop - sync_0, animators_frametime);
-             
-             timer = ecore_timer_loop_add(animators_frametime, 
-                                          _ecore_animator, NULL);
-             ecore_timer_delay(timer, d);
+
+             timer = _ecore_timer_loop_add(animators_frametime,
+                                                    _ecore_animator, NULL);
+             _ecore_timer_delay(timer, d);
           }
         break;
       case ECORE_ANIMATOR_SOURCE_CUSTOM:
@@ -78,7 +78,7 @@ _end_tick(void)
       case ECORE_ANIMATOR_SOURCE_TIMER:
         if (timer)
           {
-             ecore_timer_del(timer);
+             _ecore_timer_del(timer);
              timer = NULL;
           }
         break;
@@ -99,7 +99,17 @@ _do_tick(void)
      {
         if (!animator->delete_me && !animator->suspended)
           {
-             if (!animator->func(animator->data))
+             Ecore_Task_Cb func;
+             void *data;
+             Eina_Bool ret;
+
+             func = animator->func;
+             data = animator->data;
+             _ecore_unlock();
+             ret = func(data);
+             _ecore_lock();
+
+             if (!ret)
                {
                   animator->delete_me = EINA_TRUE;
                   animators_delete_me++;
@@ -136,18 +146,19 @@ _do_tick(void)
 EAPI Ecore_Animator *
 ecore_animator_add(Ecore_Task_Cb func, const void *data)
 {
-   Ecore_Animator *animator;
+   Ecore_Animator *animator = NULL;
 
-   ECORE_MAIN_LOOP_ASSERT();
-
-   if (!func) return NULL;
+   _ecore_lock();
+   if (!func) goto unlock;
    animator = calloc(1, sizeof(Ecore_Animator));
-   if (!animator) return NULL;
+   if (!animator) goto unlock;
    ECORE_MAGIC_SET(animator, ECORE_MAGIC_ANIMATOR);
    animator->func = func;
    animator->data = (void *)data;
    animators = (Ecore_Animator *)eina_inlist_append(EINA_INLIST_GET(animators), EINA_INLIST_GET(animator));
    _begin_tick();
+unlock:
+   _ecore_unlock();
    return animator;
 }
 
@@ -156,8 +167,7 @@ ecore_animator_timeline_add(double runtime, Ecore_Timeline_Cb func, const void *
 {
    Ecore_Animator *animator;
 
-   ECORE_MAIN_LOOP_ASSERT();
-
+   _ecore_lock();
    if (runtime <= 0.0) runtime = 0.0;
    animator = ecore_animator_add(_ecore_animator_run, NULL);
    animator->data = animator;
@@ -165,6 +175,7 @@ ecore_animator_timeline_add(double runtime, Ecore_Timeline_Cb func, const void *
    animator->run_data = (void *)data;
    animator->start = ecore_loop_time_get();
    animator->run = runtime;
+   _ecore_unlock();
    return animator;
 }
 
@@ -227,6 +238,7 @@ _pos_map_spring(double pos, int bounces, double decfac)
 EAPI double
 ecore_animator_pos_map(double pos, Ecore_Pos_Map map, double v1, double v2)
 {
+   /* purely functional - locking not required */
    if (pos > 1.0) pos = 1.0;
    else if (pos < 0.0) pos = 0.0;
    switch (map)
@@ -273,31 +285,42 @@ ecore_animator_pos_map(double pos, Ecore_Pos_Map map, double v1, double v2)
 EAPI void *
 ecore_animator_del(Ecore_Animator *animator)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   void *data = NULL;
 
+   _ecore_lock();
    if (!ECORE_MAGIC_CHECK(animator, ECORE_MAGIC_ANIMATOR))
      {
         ECORE_MAGIC_FAIL(animator, ECORE_MAGIC_ANIMATOR,
                          "ecore_animator_del");
-        return NULL;
+        goto unlock;
+     }
+   if (animator->delete_me)
+     {
+        data = animator->data;
+        goto unlock;
      }
-   if (animator->delete_me) return animator->data;
    animator->delete_me = EINA_TRUE;
    animators_delete_me++;
-   if (animator->run_func) return animator->run_data;
-   return animator->data;
+   if (animator->run_func)
+     data = animator->run_data;
+   else
+     data = animator->data;
+unlock:
+   _ecore_unlock();
+   return data;
 }
 
 EAPI void
 ecore_animator_frametime_set(double frametime)
 {
-   ECORE_MAIN_LOOP_ASSERT();
-
+   _ecore_lock();
    if (frametime < 0.0) frametime = 0.0;
-   if (animators_frametime == frametime) return;
+   if (animators_frametime == frametime) goto unlock;
    animators_frametime = frametime;
    _end_tick();
    if (animators) _begin_tick();
+unlock:
+   _ecore_unlock();
 }
 
 EAPI double
@@ -309,79 +332,79 @@ ecore_animator_frametime_get(void)
 EAPI void
 ecore_animator_freeze(Ecore_Animator *animator)
 {
-   ECORE_MAIN_LOOP_ASSERT();
-
+   _ecore_lock();
    if (!ECORE_MAGIC_CHECK(animator, ECORE_MAGIC_ANIMATOR))
      {
         ECORE_MAGIC_FAIL(animator, ECORE_MAGIC_ANIMATOR,
                          "ecore_animator_del");
-        return;
+        goto unlock;
      }
-   if (animator->delete_me) return;
+   if (animator->delete_me) goto unlock;
    animator->suspended = EINA_TRUE;
+unlock:
+   _ecore_unlock();
 }
 
 EAPI void
 ecore_animator_thaw(Ecore_Animator *animator)
 {
-   ECORE_MAIN_LOOP_ASSERT();
-
+   _ecore_lock();
    if (!ECORE_MAGIC_CHECK(animator, ECORE_MAGIC_ANIMATOR))
      {
         ECORE_MAGIC_FAIL(animator, ECORE_MAGIC_ANIMATOR,
                          "ecore_animator_del");
-        return;
+        goto unlock;
      }
-   if (animator->delete_me) return;
+   if (animator->delete_me) goto unlock;
    animator->suspended = EINA_FALSE;
+unlock:
+   _ecore_unlock();
 }
 
 EAPI void
 ecore_animator_source_set(Ecore_Animator_Source source)
 {
-   ECORE_MAIN_LOOP_ASSERT();
-
+   _ecore_lock();
    src = source;
    _end_tick();
    if (animators) _begin_tick();
+   _ecore_unlock();
 }
 
 EAPI Ecore_Animator_Source
 ecore_animator_source_get(void)
 {
-   ECORE_MAIN_LOOP_ASSERT();
-
    return src;
 }
 
 EAPI void
 ecore_animator_custom_source_tick_begin_callback_set(Ecore_Cb func, const void *data)
 {
-   ECORE_MAIN_LOOP_ASSERT();
-
+   _ecore_lock();
    begin_tick_cb = func;
    begin_tick_data = data;
    _end_tick();
    if (animators) _begin_tick();
+   _ecore_unlock();
 }
 
 EAPI void
 ecore_animator_custom_source_tick_end_callback_set(Ecore_Cb func, const void *data)
 {
-   ECORE_MAIN_LOOP_ASSERT();
-
+   _ecore_lock();
    end_tick_cb = func;
    end_tick_data = data;
    _end_tick();
    if (animators) _begin_tick();
+   _ecore_unlock();
 }
 
 EAPI void
 ecore_animator_custom_tick(void)
 {
-   ECORE_MAIN_LOOP_ASSERT();
-
+   _ecore_lock();
    if (src == ECORE_ANIMATOR_SOURCE_CUSTOM) _do_tick();
+   _ecore_unlock();
 }
 
 void
@@ -421,5 +444,9 @@ _ecore_animator_run(void *data)
 static Eina_Bool
 _ecore_animator(void *data __UNUSED__)
 {
-   return _do_tick();
+   Eina_Bool r;
+   _ecore_lock();
+   r = _do_tick();
+   _ecore_unlock();
+   return r;
 }
index c1f4658..7f21771 100644 (file)
@@ -140,14 +140,14 @@ static void *_ecore_event_del(Ecore_Event *event);
 EAPI Ecore_Event_Handler *
 ecore_event_handler_add(int type, Ecore_Event_Handler_Cb func, const void *data)
 {
-   Ecore_Event_Handler *eh;
+   Ecore_Event_Handler *eh = NULL;
 
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
-   if (!func) return NULL;
-   if ((type <= ECORE_EVENT_NONE) || (type >= event_id_max)) return NULL;
+   if (!func) goto unlock;
+   if ((type <= ECORE_EVENT_NONE) || (type >= event_id_max)) goto unlock;
    eh = calloc(1, sizeof(Ecore_Event_Handler));
-   if (!eh) return NULL;
+   if (!eh) goto unlock;
    ECORE_MAGIC_SET(eh, ECORE_MAGIC_EVENT_HANDLER);
    eh->type = type;
    eh->func = func;
@@ -168,7 +168,7 @@ ecore_event_handler_add(int type, Ecore_Event_Handler_Cb func, const void *data)
              if (!new_handlers)
                {
                   free(eh);
-                  return NULL;
+                  goto unlock;
                }
              event_handlers = new_handlers;
              for (i = p_alloc_num; i < event_handlers_alloc_num; i++)
@@ -179,6 +179,9 @@ ecore_event_handler_add(int type, Ecore_Event_Handler_Cb func, const void *data)
      event_handlers_add_list = (Ecore_Event_Handler *)eina_inlist_append(EINA_INLIST_GET(event_handlers_add_list), EINA_INLIST_GET(eh));
    else if (type < event_handlers_alloc_num)
      event_handlers[type] = (Ecore_Event_Handler *)eina_inlist_append(EINA_INLIST_GET(event_handlers[type]), EINA_INLIST_GET(eh));
+
+unlock:
+   _ecore_unlock();
    return eh;
 }
 
@@ -195,18 +198,23 @@ ecore_event_handler_add(int type, Ecore_Event_Handler_Cb func, const void *data)
 EAPI void *
 ecore_event_handler_del(Ecore_Event_Handler *event_handler)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   void *data = NULL;
 
+   _ecore_lock();
    if (!ECORE_MAGIC_CHECK(event_handler, ECORE_MAGIC_EVENT_HANDLER))
      {
         ECORE_MAGIC_FAIL(event_handler, ECORE_MAGIC_EVENT_HANDLER,
                          "ecore_event_handler_del");
-        return NULL;
+        goto unlock;
      }
    EINA_SAFETY_ON_TRUE_RETURN_VAL(event_handler->delete_me, NULL);
    event_handler->delete_me = 1;
    event_handlers_delete_list = eina_list_append(event_handlers_delete_list, event_handler);
-   return event_handler->data;
+   data = event_handler->data;
+unlock:
+   _ecore_unlock();
+
+   return data;
 }
 
 /**
@@ -220,14 +228,18 @@ ecore_event_handler_del(Ecore_Event_Handler *event_handler)
 EAPI void *
 ecore_event_handler_data_get(Ecore_Event_Handler *eh)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   void *data = NULL;
 
+   _ecore_lock();
    if (!ECORE_MAGIC_CHECK(eh, ECORE_MAGIC_EVENT_HANDLER))
      {
         ECORE_MAGIC_FAIL(eh, ECORE_MAGIC_EVENT_HANDLER, "ecore_event_handler_data_get");
-        return NULL;
+        goto unlock;
      }
-   return eh->data;
+   data = eh->data;
+unlock:
+   _ecore_unlock();
+   return data;
 }
 
 /**
@@ -242,17 +254,19 @@ ecore_event_handler_data_get(Ecore_Event_Handler *eh)
 EAPI void *
 ecore_event_handler_data_set(Ecore_Event_Handler *eh, const void *data)
 {
-   void *old;
-
-   ECORE_MAIN_LOOP_ASSERT();
+   void *old = NULL;
 
+   _ecore_lock();
    if (!ECORE_MAGIC_CHECK(eh, ECORE_MAGIC_EVENT_HANDLER))
      {
         ECORE_MAGIC_FAIL(eh, ECORE_MAGIC_EVENT_HANDLER, "ecore_event_handler_data_set");
-        return NULL;
+        goto unlock;
      }
    old = eh->data;
    eh->data = (void *)data;
+unlock:
+   _ecore_unlock();
+
    return old;
 }
 
@@ -283,13 +297,18 @@ _ecore_event_generic_free (void *data __UNUSED__, void *event)
 EAPI Ecore_Event *
 ecore_event_add(int type, void *ev, Ecore_End_Cb func_free, void *data)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   Ecore_Event *event = NULL;
 
-/*   if (!ev) return NULL;*/
-   if (type <= ECORE_EVENT_NONE) return NULL;
-   if (type >= event_id_max) return NULL;
+   _ecore_lock();
+
+/*   if (!ev) goto unlock; */
+   if (type <= ECORE_EVENT_NONE) goto unlock;
+   if (type >= event_id_max) goto unlock;
    if ((ev) && (!func_free)) func_free = _ecore_event_generic_free;
-   return _ecore_event_add(type, ev, func_free, data);
+   event = _ecore_event_add(type, ev, func_free, data);
+unlock:
+   _ecore_unlock();
+   return event;
 }
 
 /**
@@ -306,16 +325,20 @@ ecore_event_add(int type, void *ev, Ecore_End_Cb func_free, void *data)
 EAPI void *
 ecore_event_del(Ecore_Event *event)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   void *data = NULL;
 
+   _ecore_lock();
    if (!ECORE_MAGIC_CHECK(event, ECORE_MAGIC_EVENT))
      {
         ECORE_MAGIC_FAIL(event, ECORE_MAGIC_EVENT, "ecore_event_del");
-        return NULL;
+        goto unlock;
      }
    EINA_SAFETY_ON_TRUE_RETURN_VAL(event->delete_me, NULL);
    event->delete_me = 1;
-   return event->data;
+   data = event->data;
+unlock:
+   _ecore_unlock();
+   return data;
 }
 
 /**
@@ -331,10 +354,13 @@ ecore_event_del(Ecore_Event *event)
 EAPI int
 ecore_event_type_new(void)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   int id;
 
-   event_id_max++;
-   return event_id_max - 1;
+   _ecore_lock();
+   id = event_id_max++;
+   _ecore_unlock();
+
+   return id;
 }
 
 /**
@@ -360,19 +386,20 @@ ecore_event_type_new(void)
 EAPI Ecore_Event_Filter *
 ecore_event_filter_add(Ecore_Data_Cb func_start, Ecore_Filter_Cb func_filter, Ecore_End_Cb func_end, const void *data)
 {
-   Ecore_Event_Filter *ef;
-
-   ECORE_MAIN_LOOP_ASSERT();
+   Ecore_Event_Filter *ef = NULL;
 
-   if (!func_filter) return NULL;
+   _ecore_lock();
+   if (!func_filter) goto unlock;
    ef = calloc(1, sizeof(Ecore_Event_Filter));
-   if (!ef) return NULL;
+   if (!ef) goto unlock;
    ECORE_MAGIC_SET(ef, ECORE_MAGIC_EVENT_FILTER);
    ef->func_start = func_start;
    ef->func_filter = func_filter;
    ef->func_end = func_end;
    ef->data = (void *)data;
    event_filters = (Ecore_Event_Filter *) eina_inlist_append(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(ef));
+unlock:
+   _ecore_unlock();
    return ef;
 }
 
@@ -388,17 +415,22 @@ ecore_event_filter_add(Ecore_Data_Cb func_start, Ecore_Filter_Cb func_filter, Ec
 EAPI void *
 ecore_event_filter_del(Ecore_Event_Filter *ef)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   void *data = NULL;
 
+   _ecore_lock();
    if (!ECORE_MAGIC_CHECK(ef, ECORE_MAGIC_EVENT_FILTER))
      {
         ECORE_MAGIC_FAIL(ef, ECORE_MAGIC_EVENT_FILTER, "ecore_event_filter_del");
-        return NULL;
+        goto unlock;
      }
    EINA_SAFETY_ON_TRUE_RETURN_VAL(ef->delete_me, NULL);
    ef->delete_me = 1;
    event_filters_delete_me = 1;
-   return ef->data;
+   data = ef->data;
+unlock:
+   _ecore_unlock();
+
+   return data;
 }
 
 /**
@@ -524,7 +556,20 @@ _ecore_event_del(Ecore_Event *event)
    void *data;
 
    data = event->data;
-   if (event->func_free) event->func_free(event->data, event->event);
+   if (event->func_free)
+     {
+        Ecore_End_Cb func_free;
+        void *ev;
+        void *data;
+
+        func_free = event->func_free;
+        ev = event->event;
+        data = event->data;
+
+        _ecore_unlock();
+        func_free(data, ev);
+        _ecore_lock();
+     }
    events = (Ecore_Event *) eina_inlist_remove(EINA_INLIST_GET(events), EINA_INLIST_GET(event));
    ECORE_MAGIC_SET(event, ECORE_MAGIC_NONE);
    free(event);
@@ -578,7 +623,18 @@ _ecore_event_filters_apply()
              ef->references++;
 
              if (ef->func_start)
-               ef->loop_data = ef->func_start(ef->data);
+               {
+                  Ecore_Data_Cb func_start;
+                  void *data;
+                  void *r;
+
+                  func_start = ef->func_start;
+                  data = ef->data;
+                  _ecore_unlock();
+                  r = func_start(data);
+                  _ecore_lock();
+                  ef->loop_data = r;
+               }
 
              if (!event_filter_event_current)
                {
@@ -594,9 +650,23 @@ _ecore_event_filters_apply()
              while (event_filter_event_current)
                {
                   Ecore_Event *e = event_filter_event_current;
-
-                  if (!ef->func_filter(ef->data, ef->loop_data,
-                                       e->type, e->event))
+                  Ecore_Filter_Cb func_filter;
+                  void *loop_data;
+                  void *data;
+                  int type;
+                  void *event;
+                  Eina_Bool r;
+
+                  func_filter = ef->func_filter;
+                  data = ef->data;
+                  loop_data = ef->loop_data;
+                  type = e->type;
+                  event = e->event;
+
+                  _ecore_unlock();
+                  r = func_filter(data, loop_data, type, event);
+                  _ecore_lock();
+                  if (!r)
                     {
                        ecore_event_del(e);
                     }
@@ -605,7 +675,19 @@ _ecore_event_filters_apply()
                     event_filter_event_current = (Ecore_Event *)EINA_INLIST_GET(event_filter_event_current)->next;
                }
              if (ef->func_end)
-               ef->func_end(ef->data, ef->loop_data);
+               {
+                  Ecore_End_Cb func_end;
+                  void *loop_data;
+                  void *data;
+
+                  func_end = ef->func_end;
+                  data = ef->data;
+                  loop_data = ef->loop_data;
+
+                  _ecore_unlock();
+                  ef->func_end(ef->data, ef->loop_data);
+                  _ecore_lock();
+               }
 
              ef->references--;
           }
@@ -685,12 +767,22 @@ _ecore_event_call(void)
                   eh = event_handler_current;
                   if (!eh->delete_me)
                     {
+                       Ecore_Event_Handler_Cb func;
+                       void *data;
+                       int type;
+                       void *event;
                        Eina_Bool ret;
 
                        handle_count++;
 
+                       func = eh->func;
+                       data = eh->data;
+                       type = e->type;
+                       event = e->event;
                        eh->references++;
-                       ret = eh->func(eh->data, e->type, e->event);
+                       _ecore_unlock();
+                       ret = func(data, type, event);
+                       _ecore_lock();
                        eh->references--;
 
                        if (!ret)
index 9802895..c4a1915 100644 (file)
@@ -23,6 +23,9 @@ static Ecore_Idle_Enterer *idle_enterers = NULL;
 static Ecore_Idle_Enterer *idle_enterer_current = NULL;
 static int                 idle_enterers_delete_me = 0;
 
+static void *
+_ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer);
+
 /**
  * @addtogroup Ecore_Group Ecore - Main Loop and Job Functions.
  *
@@ -48,17 +51,19 @@ static int                 idle_enterers_delete_me = 0;
 EAPI Ecore_Idle_Enterer *
 ecore_idle_enterer_add(Ecore_Task_Cb func, const void *data)
 {
-   Ecore_Idle_Enterer *ie;
+   Ecore_Idle_Enterer *ie = NULL;
 
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
-   if (!func) return NULL;
+   if (!func) goto unlock;
    ie = calloc(1, sizeof(Ecore_Idle_Enterer));
-   if (!ie) return NULL;
+   if (!ie) goto unlock;
    ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_ENTERER);
    ie->func = func;
    ie->data = (void *)data;
    idle_enterers = (Ecore_Idle_Enterer *) eina_inlist_append(EINA_INLIST_GET(idle_enterers), EINA_INLIST_GET(ie));
+unlock:
+   _ecore_unlock();
    return ie;
 }
 
@@ -75,17 +80,19 @@ ecore_idle_enterer_add(Ecore_Task_Cb func, const void *data)
 EAPI Ecore_Idle_Enterer *
 ecore_idle_enterer_before_add(Ecore_Task_Cb func, const void *data)
 {
-   Ecore_Idle_Enterer *ie;
+   Ecore_Idle_Enterer *ie = NULL;
 
-   ECORE_MAIN_LOOP_ASSERT();
+   _ecore_lock();
 
-   if (!func) return NULL;
+   if (!func) goto unlock;
    ie = calloc(1, sizeof(Ecore_Idle_Enterer));
-   if (!ie) return NULL;
+   if (!ie) goto unlock;
    ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_ENTERER);
    ie->func = func;
    ie->data = (void *)data;
    idle_enterers = (Ecore_Idle_Enterer *) eina_inlist_prepend(EINA_INLIST_GET(idle_enterers), EINA_INLIST_GET(ie));
+unlock:
+   _ecore_unlock();
    return ie;
 }
 
@@ -98,7 +105,7 @@ ecore_idle_enterer_before_add(Ecore_Task_Cb func, const void *data)
 EAPI void *
 ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   void *data;
 
    if (!ECORE_MAGIC_CHECK(idle_enterer, ECORE_MAGIC_IDLE_ENTERER))
      {
@@ -106,10 +113,10 @@ ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer)
                          "ecore_idle_enterer_del");
         return NULL;
      }
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(idle_enterer->delete_me, NULL);
-   idle_enterer->delete_me = 1;
-   idle_enterers_delete_me = 1;
-   return idle_enterer->data;
+   _ecore_lock();
+   data = _ecore_idle_enterer_del(idle_enterer);
+   _ecore_unlock();
+   return data;
 }
 
 /**
@@ -120,6 +127,16 @@ ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer)
  * @}
  */
 
+static void *
+_ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer)
+{
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(idle_enterer->delete_me, NULL);
+   idle_enterer->delete_me = 1;
+   idle_enterers_delete_me = 1;
+   return idle_enterer->data;
+}
+
+
 void
 _ecore_idle_enterer_shutdown(void)
 {
@@ -154,10 +171,19 @@ _ecore_idle_enterer_call(void)
         Ecore_Idle_Enterer *ie = (Ecore_Idle_Enterer *)idle_enterer_current;
         if (!ie->delete_me)
           {
+             Ecore_Task_Cb func;
+             void *data;
+             Eina_Bool ret;
+
+             func = ie->func;
+             data = ie->data;
              ie->references++;
-             if (!ie->func(ie->data))
+             _ecore_unlock();
+             ret = func(data);
+             _ecore_lock();
+             if (!ret)
                {
-                  if (!ie->delete_me) ecore_idle_enterer_del(ie);
+                  if (!ie->delete_me) _ecore_idle_enterer_del(ie);
                }
              ie->references--;
           }
index c8abb87..d7d52f4 100644 (file)
@@ -23,6 +23,9 @@ static Ecore_Idle_Exiter *idle_exiters = NULL;
 static Ecore_Idle_Exiter *idle_exiter_current = NULL;
 static int                idle_exiters_delete_me = 0;
 
+static void *
+_ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter);
+
 /**
  * @addtogroup Ecore_Group Ecore - Main Loop and Job Functions.
  *
@@ -47,17 +50,18 @@ static int                idle_exiters_delete_me = 0;
 EAPI Ecore_Idle_Exiter *
 ecore_idle_exiter_add(Ecore_Task_Cb func, const void *data)
 {
-   Ecore_Idle_Exiter *ie;
+   Ecore_Idle_Exiter *ie = NULL;
 
-   ECORE_MAIN_LOOP_ASSERT();
-
-   if (!func) return NULL;
+   _ecore_lock();
+   if (!func) goto unlock;
    ie = calloc(1, sizeof(Ecore_Idle_Exiter));
-   if (!ie) return NULL;
+   if (!ie) goto unlock;
    ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_EXITER);
    ie->func = func;
    ie->data = (void *)data;
    idle_exiters = (Ecore_Idle_Exiter *) eina_inlist_append(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(ie));
+unlock:
+   _ecore_unlock();
    return ie;
 }
 
@@ -70,7 +74,7 @@ ecore_idle_exiter_add(Ecore_Task_Cb func, const void *data)
 EAPI void *
 ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter)
 {
-   ECORE_MAIN_LOOP_ASSERT();
+   void *data;
 
    if (!ECORE_MAGIC_CHECK(idle_exiter, ECORE_MAGIC_IDLE_EXITER))
      {
@@ -78,10 +82,10 @@ ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter)
                          "ecore_idle_exiter_del");
         return NULL;
      }
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(idle_exiter->delete_me, NULL);
-   idle_exiter->delete_me = 1;
-   idle_exiters_delete_me = 1;
-   return idle_exiter->data;
+   _ecore_lock();
+   data = _ecore_idle_exiter_del(idle_exiter);
+   _ecore_unlock();
+   return data;
 }
 
 /**
@@ -92,6 +96,15 @@ ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter)
  * @}
  */
 
+static void *
+_ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter)
+{
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(idle_exiter->delete_me, NULL);
+   idle_exiter->delete_me = 1;
+   idle_exiters_delete_me = 1;
+   return idle_exiter->data;
+}
+
 void
 _ecore_idle_exiter_shutdown(void)
 {
@@ -126,10 +139,19 @@ _ecore_idle_exiter_call(void)
         Ecore_Idle_Exiter *ie = (Ecore_Idle_Exiter *)idle_exiter_current;
         if (!ie->delete_me)
           {
+             Ecore_Task_Cb func;
+             void *data;
+             Eina_Bool ret;
+
+             func = ie->func;
+             data = ie->data;
              ie->references++;
-             if (!ie->func(ie->data))
+             _ecore_unlock();
+             ret = func(data);
+             _ecore_lock();
+             if (!ret)
                {
-                  if (!ie->delete_me) ecore_idle_exiter_del(ie);
+                  if (!ie->delete_me) _ecore_idle_exiter_del(ie);
                }
              ie->references--;
           }
index af43c31..672aff2 100644 (file)
@@ -23,6 +23,9 @@ static Ecore_Idler *idlers = NULL;
 static Ecore_Idler *idler_current = NULL;
 static int          idlers_delete_me = 0;
 
+static void *
+_ecore_idler_del(Ecore_Idler *idler);
+
 /**
  * @addtogroup Ecore_Group Ecore - Main Loop and Job Functions.
  *
@@ -86,15 +89,18 @@ Example with functions that deal with idle state:
 EAPI Ecore_Idler *
 ecore_idler_add(Ecore_Task_Cb func, const void *data)
 {
-   Ecore_Idler *ie;
+   Ecore_Idler *ie = NULL;
 
-   if (!func) return NULL;
+   _ecore_lock();
+   if (!func) goto unlock;
    ie = calloc(1, sizeof(Ecore_Idler));
-   if (!ie) return NULL;
+   if (!ie) goto unlock;
    ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLER);
    ie->func = func;
    ie->data = (void *)data;
    idlers = (Ecore_Idler *) eina_inlist_append(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
+unlock:
+   _ecore_unlock();
    return ie;
 }
 
@@ -107,16 +113,19 @@ ecore_idler_add(Ecore_Task_Cb func, const void *data)
 EAPI void *
 ecore_idler_del(Ecore_Idler *idler)
 {
+   void *data = NULL;
+
    if (!ECORE_MAGIC_CHECK(idler, ECORE_MAGIC_IDLER))
      {
         ECORE_MAGIC_FAIL(idler, ECORE_MAGIC_IDLER,
                          "ecore_idler_del");
         return NULL;
      }
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(idler->delete_me, NULL);
-   idler->delete_me = 1;
-   idlers_delete_me = 1;
-   return idler->data;
+
+   _ecore_lock();
+   data = _ecore_idler_del(idler);
+   _ecore_unlock();
+   return data;
 }
 
 /**
@@ -127,6 +136,16 @@ ecore_idler_del(Ecore_Idler *idler)
  * @}
  */
 
+static void *
+_ecore_idler_del(Ecore_Idler *idler)
+{
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(idler->delete_me, NULL);
+   idler->delete_me = 1;
+   idlers_delete_me = 1;
+   return idler->data;
+}
+
+
 void
 _ecore_idler_shutdown(void)
 {
@@ -160,10 +179,19 @@ _ecore_idler_call(void)
         Ecore_Idler *ie = (Ecore_Idler *)idler_current;
         if (!ie->delete_me)
           {
+             Eina_Bool ret;
+             Ecore_Task_Cb func;
+             void *data;
+
+             func = ie->func;
+             data = ie->data;
              ie->references++;
-             if (!ie->func(ie->data))
+             _ecore_unlock();
+             ret = func(data);
+             _ecore_lock();
+             if (!ret)
                {
-                  if (!ie->delete_me) ecore_idler_del(ie);
+                  if (!ie->delete_me) _ecore_idler_del(ie);
                }
              ie->references--;
           }
index 53d7a8a..688c2c5 100644 (file)
@@ -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();
 }
 
 /**
@@ -1275,8 +1304,15 @@ _ecore_main_prepare_handlers(void)
           }
         if (!fdh->delete_me && fdh->prep_func)
           {
+             Ecore_Fd_Prep_Cb prep_func;
+             void *prep_data;
+
+             prep_func = fdh->prep_func;
+             prep_data = fdh->prep_data;
              fdh->references++;
-             fdh->prep_func(fdh->prep_data, fdh);
+             _ecore_unlock();
+             prep_func(prep_data, fdh);
+             _ecore_lock();
              fdh->references--;
           }
         else
@@ -1360,7 +1396,9 @@ _ecore_main_select(double timeout)
 
    if (_ecore_signal_count_get()) return -1;
 
+   _ecore_unlock();
    ret = main_loop_select(max_fd + 1, &rfds, &wfds, &exfds, t);
+   _ecore_lock();
 
    _ecore_time_loop_time = ecore_time_get();
    if (ret < 0)
@@ -1424,9 +1462,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 +1588,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 +1641,27 @@ _ecore_main_fd_handlers_buf_call(void)
           }
         if ((!fdh->delete_me) && fdh->buf_func)
           {
+             Ecore_Fd_Cb buf_func;
+             void *buf_data;
+             Eina_Bool r;
+
+             /* copy data before releasing lock */
+             buf_func = fdh->buf_func;
+             buf_data = fdh->buf_data;
              fdh->references++;
-             if (fdh->buf_func(fdh->buf_data, fdh))
+             _ecore_unlock();
+             r = buf_func(buf_data, fdh);
+             _ecore_lock();
+             if (r)
                {
-                  ret |= fdh->func(fdh->data, fdh);
+                  Ecore_Fd_Cb func;
+                  void *data;
+
+                  func = fdh->func;
+                  data = fdh->data;
+                  _ecore_unlock();
+                  ret |= func(data, fdh);
+                  _ecore_lock();
                   fdh->read_active = EINA_TRUE;
                   _ecore_try_add_to_call_list(fdh);
                }
index 8e5be10..0e96874 100644 (file)
@@ -119,6 +119,9 @@ EAPI void          _ecore_magic_fail(const void *d, Ecore_Magic m, Ecore_Magic r
 
 void          _ecore_time_init(void);
 
+Ecore_Timer  *_ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data);
+void         *_ecore_timer_del(Ecore_Timer *timer);
+void          _ecore_timer_delay(Ecore_Timer *timer, double add);
 void          _ecore_timer_shutdown(void);
 void          _ecore_timer_cleanup(void);
 void          _ecore_timer_enable_new(void);
@@ -199,6 +202,21 @@ void _ecore_main_loop_shutdown(void);
 
 void _ecore_throttle(void);
 
+#ifdef HAVE_THREAD_SAFETY
+void _ecore_lock(void);
+void _ecore_unlock(void);
+#else
+static inline void _ecore_lock(void)
+  {
+     /* at least check we're not being called from a thread */
+     ECORE_MAIN_LOOP_ASSERT();
+  }
+
+static inline void _ecore_unlock(void)
+  {
+  }
+#endif
+
 extern int    _ecore_fps_debug;
 extern double _ecore_time_loop_time;
 extern Eina_Bool _ecore_glib_always_integrate;
index 0053524..3cacd20 100644 (file)
@@ -220,7 +220,7 @@ _ecore_signal_call(void)
              if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
                e->data = sigusr1_info[n];
 
-             ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
+             _ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
           }
         sig_count--;
      }
@@ -241,7 +241,7 @@ _ecore_signal_call(void)
              if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
                e->data = sigusr2_info[n];
 
-             ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
+             _ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
           }
         sig_count--;
      }
@@ -260,7 +260,7 @@ _ecore_signal_call(void)
              if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
                e->data = sighup_info[n];
 
-             ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL);
+             _ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL);
           }
         sig_count--;
      }
@@ -281,7 +281,7 @@ _ecore_signal_call(void)
              if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
                e->data = sigquit_info[n];
 
-             ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
+             _ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
           }
         sig_count--;
      }
@@ -302,7 +302,7 @@ _ecore_signal_call(void)
              if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
                e->data = sigint_info[n];
 
-             ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
+             _ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
           }
         sig_count--;
      }
@@ -323,7 +323,7 @@ _ecore_signal_call(void)
              if ((n < MAXSIGQ) && (sigterm_info[n].si_signo))
                e->data = sigterm_info[n];
 
-             ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
+             _ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
           }
         sig_count--;
      }
@@ -343,7 +343,7 @@ _ecore_signal_call(void)
              if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
                e->data = sigpwr_info[n];
 
-             ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL);
+             _ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL);
           }
         sig_count--;
      }
index 4449484..625b448 100644 (file)
@@ -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,26 @@ _ecore_thread_assert_main_loop_thread(const char *function)
      }
 }
 
+#ifdef HAVE_THREAD_SAFETY
+static int lock_count;
+
+void
+_ecore_lock(void)
+{
+  LKL(_ecore_main_loop_mutex);
+  lock_count++;
+  assert(lock_count == 1);
+}
+
+void
+_ecore_unlock(void)
+{
+  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,
index a4bc1a4..d190c7a 100644 (file)
@@ -107,14 +107,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 +142,13 @@ EAPI Ecore_Timer *
 ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
 {
    double now;
-   Ecore_Timer *timer;
+   Ecore_Timer *timer = NULL;
 
-   ECORE_MAIN_LOOP_ASSERT();
-
-   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 +158,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;
 }
 
@@ -174,24 +178,12 @@ ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
 EAPI Ecore_Timer *
 ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data)
 {
-   double now;
    Ecore_Timer *timer;
 
-   ECORE_MAIN_LOOP_ASSERT();
-
-   if (!func) return NULL;
-   if (in < 0.0) in = 0.0;
-   timer = calloc(1, sizeof(Ecore_Timer));
-   if (!timer) return NULL;
-   ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
-   now = ecore_loop_time_get();
-
-#ifdef WANT_ECORE_TIMER_DUMP
-   timer->timer_bt_num = backtrace((void**) (timer->timer_bt),
-                                   ECORE_TIMER_DEBUG_BT_NUM);
-#endif
+   _ecore_lock();
+   timer = _ecore_timer_loop_add(in, func, data);
+   _ecore_unlock();
 
-   _ecore_timer_set(timer, now + in, in, func, (void *)data);
    return timer;
 }
 
@@ -207,32 +199,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 +227,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 +249,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,8 +277,6 @@ ecore_timer_interval_get(Ecore_Timer *timer)
 EAPI void
 ecore_timer_delay(Ecore_Timer *timer, double add)
 {
-   ECORE_MAIN_LOOP_ASSERT();
-
    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
      {
         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
@@ -296,15 +284,9 @@ ecore_timer_delay(Ecore_Timer *timer, double add)
         return;
      }
 
-   if (timer->frozen)
-     {
-        timer->pending += add;
-     }
-   else
-     {
-        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);
-     }
+   _ecore_lock();
+   _ecore_timer_delay(timer, add);
+   _ecore_unlock();
 }
 
 /**
@@ -317,21 +299,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 +340,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 +361,8 @@ ecore_timer_freeze(Ecore_Timer *timer)
    timer->pending = timer->at - now;
    timer->at = 0.0;
    timer->frozen = 1;
+unlock:
+   _ecore_unlock();
 }
 
 /**
@@ -394,23 +383,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 +415,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 +451,7 @@ ecore_timer_dump(void)
 
    out = eina_strbuf_string_steal(result);
    eina_strbuf_free(result);
+   _ecore_unlock();
 
    return out;
 #else
@@ -474,6 +467,64 @@ ecore_timer_dump(void)
  * @}
  */
 
+Ecore_Timer *
+_ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data)
+{
+   double now;
+   Ecore_Timer *timer = NULL;
+
+   if (!func) return timer;
+   if (in < 0.0) in = 0.0;
+   timer = calloc(1, sizeof(Ecore_Timer));
+   if (!timer) return timer;
+   ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
+   now = ecore_loop_time_get();
+
+#ifdef WANT_ECORE_TIMER_DUMP
+   timer->timer_bt_num = backtrace((void**) (timer->timer_bt),
+                                   ECORE_TIMER_DEBUG_BT_NUM);
+#endif
+   _ecore_timer_set(timer, now + in, in, func, (void *)data);
+   return timer;
+}
+
+EAPI void
+_ecore_timer_delay(Ecore_Timer *timer, double add)
+{
+   if (timer->frozen)
+     {
+        timer->pending += add;
+     }
+   else
+     {
+        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);
+     }
+}
+
+
+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 +695,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 +724,9 @@ _ecore_timer_call(double when)
    while (timer_current)
      {
         Ecore_Timer *timer = timer_current;
+        Eina_Bool cont;
+        Ecore_Task_Cb func;
+        void *data;
 
         if (timer->at > when)
           {
@@ -686,9 +741,14 @@ _ecore_timer_call(double when)
           }
 
         timer->references++;
-        if (!timer->func(timer->data))
+        func = timer->func;
+        data = timer->data;
+        _ecore_unlock();
+        cont = func(data);
+        _ecore_lock();
+        if (!cont)
           {
-             if (!timer->delete_me) ecore_timer_del(timer);
+             if (!timer->delete_me) _ecore_timer_del(timer);
           }
         timer->references--;