From 5c8256e337e00c66eaa65a0d7802af91b237d2f1 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Thu, 28 Jul 2011 12:01:16 +0000 Subject: [PATCH] ecore: Add main loop thread safety 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 SVN revision: 61851 --- legacy/ecore/configure.ac | 17 ++ legacy/ecore/src/lib/ecore/ecore_anim.c | 107 ++++++---- legacy/ecore/src/lib/ecore/ecore_events.c | 174 ++++++++++++---- .../ecore/src/lib/ecore/ecore_idle_enterer.c | 56 +++-- .../ecore/src/lib/ecore/ecore_idle_exiter.c | 46 ++-- legacy/ecore/src/lib/ecore/ecore_idler.c | 46 +++- legacy/ecore/src/lib/ecore/ecore_main.c | 109 ++++++++-- legacy/ecore/src/lib/ecore/ecore_private.h | 18 ++ legacy/ecore/src/lib/ecore/ecore_signal.c | 14 +- legacy/ecore/src/lib/ecore/ecore_thread.c | 23 ++ legacy/ecore/src/lib/ecore/ecore_timer.c | 196 ++++++++++++------ 11 files changed, 591 insertions(+), 215 deletions(-) diff --git a/legacy/ecore/configure.ac b/legacy/ecore/configure.ac index db0f34eab1..fa7ab9d538 100644 --- a/legacy/ecore/configure.ac +++ b/legacy/ecore/configure.ac @@ -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" diff --git a/legacy/ecore/src/lib/ecore/ecore_anim.c b/legacy/ecore/src/lib/ecore/ecore_anim.c index 8aa36bbf11..e795b46fa3 100644 --- a/legacy/ecore/src/lib/ecore/ecore_anim.c +++ b/legacy/ecore/src/lib/ecore/ecore_anim.c @@ -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; } diff --git a/legacy/ecore/src/lib/ecore/ecore_events.c b/legacy/ecore/src/lib/ecore/ecore_events.c index c1f4658b5b..7f21771950 100644 --- a/legacy/ecore/src/lib/ecore/ecore_events.c +++ b/legacy/ecore/src/lib/ecore/ecore_events.c @@ -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_Event_Filter *ef = NULL; - ECORE_MAIN_LOOP_ASSERT(); - - 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; + Ecore_Filter_Cb func_filter; + void *loop_data; + void *data; + int type; + void *event; + Eina_Bool r; - if (!ef->func_filter(ef->data, ef->loop_data, - e->type, e->event)) + 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) diff --git a/legacy/ecore/src/lib/ecore/ecore_idle_enterer.c b/legacy/ecore/src/lib/ecore/ecore_idle_enterer.c index 9802895810..c4a191528c 100644 --- a/legacy/ecore/src/lib/ecore/ecore_idle_enterer.c +++ b/legacy/ecore/src/lib/ecore/ecore_idle_enterer.c @@ -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--; } diff --git a/legacy/ecore/src/lib/ecore/ecore_idle_exiter.c b/legacy/ecore/src/lib/ecore/ecore_idle_exiter.c index c8abb87292..d7d52f4147 100644 --- a/legacy/ecore/src/lib/ecore/ecore_idle_exiter.c +++ b/legacy/ecore/src/lib/ecore/ecore_idle_exiter.c @@ -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--; } diff --git a/legacy/ecore/src/lib/ecore/ecore_idler.c b/legacy/ecore/src/lib/ecore/ecore_idler.c index af43c31777..672aff26ba 100644 --- a/legacy/ecore/src/lib/ecore/ecore_idler.c +++ b/legacy/ecore/src/lib/ecore/ecore_idler.c @@ -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--; } diff --git a/legacy/ecore/src/lib/ecore/ecore_main.c b/legacy/ecore/src/lib/ecore/ecore_main.c index 53d7a8aa32..688c2c5895 100644 --- a/legacy/ecore/src/lib/ecore/ecore_main.c +++ b/legacy/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(); } /** @@ -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); } diff --git a/legacy/ecore/src/lib/ecore/ecore_private.h b/legacy/ecore/src/lib/ecore/ecore_private.h index 8e5be107c2..0e9687409d 100644 --- a/legacy/ecore/src/lib/ecore/ecore_private.h +++ b/legacy/ecore/src/lib/ecore/ecore_private.h @@ -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; diff --git a/legacy/ecore/src/lib/ecore/ecore_signal.c b/legacy/ecore/src/lib/ecore/ecore_signal.c index 0053524f38..3cacd206cc 100644 --- a/legacy/ecore/src/lib/ecore/ecore_signal.c +++ b/legacy/ecore/src/lib/ecore/ecore_signal.c @@ -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--; } diff --git a/legacy/ecore/src/lib/ecore/ecore_thread.c b/legacy/ecore/src/lib/ecore/ecore_thread.c index 4449484556..625b448897 100644 --- a/legacy/ecore/src/lib/ecore/ecore_thread.c +++ b/legacy/ecore/src/lib/ecore/ecore_thread.c @@ -3,6 +3,7 @@ #endif #include +#include #ifdef HAVE_EVIL # include @@ -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, diff --git a/legacy/ecore/src/lib/ecore/ecore_timer.c b/legacy/ecore/src/lib/ecore/ecore_timer.c index a4bc1a441c..d190c7a4e2 100644 --- a/legacy/ecore/src/lib/ecore/ecore_timer.c +++ b/legacy/ecore/src/lib/ecore/ecore_timer.c @@ -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(); + _ecore_lock(); + timer = _ecore_timer_loop_add(in, func, data); + _ecore_unlock(); - 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_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; + data = _ecore_timer_del(timer); - 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; +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--;