From: Carsten Haitzler (Rasterman) Date: Wed, 27 Dec 2017 16:19:52 +0000 (+0900) Subject: remove elgacy ecore event usage in futures that limit to mainloop only X-Git-Tag: submit/sandbox/upgrade/efl120/20180319.053334~522 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=91570049456f2d52be0a93af8a40af12f0a5af61;p=platform%2Fupstream%2Fefl.git remove elgacy ecore event usage in futures that limit to mainloop only also eina_procmis was not threadsafe so cannto use loops in different threads at all until this was made safe. needed to disable the old ecore_event using code in for ecore futures and create a new efl loop message future and handler instead ... but now a quick experiment with multiple loops in 10 threads plus mainloop have timers at least work. i need to test more like fd handlers etc etc. but it's a step. --- diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am index 7ef3b74..8612bb2 100644 --- a/src/Makefile_Ecore.am +++ b/src/Makefile_Ecore.am @@ -38,6 +38,8 @@ ecore_eolian_files_public = \ ecore_eolian_files = \ $(ecore_eolian_files_public) \ + lib/ecore/efl_loop_message_future_handler.eo \ + lib/ecore/efl_loop_message_future.eo \ lib/ecore/efl_promise.eo \ lib/ecore/efl_model_item.eo \ lib/ecore/efl_model_container.eo \ @@ -97,6 +99,8 @@ lib/ecore/efl_loop_fd.c \ lib/ecore/efl_loop_handler.c \ lib/ecore/efl_loop_message.c \ lib/ecore/efl_loop_message_handler.c \ +lib/ecore/efl_loop_message_future.c \ +lib/ecore/efl_loop_message_future_handler.c \ lib/ecore/efl_io_closer_fd.c \ lib/ecore/efl_io_positioner_fd.c \ lib/ecore/efl_io_reader_fd.c \ diff --git a/src/lib/ecore/Ecore_Eo.h b/src/lib/ecore/Ecore_Eo.h index ec690a7..211c12c 100644 --- a/src/lib/ecore/Ecore_Eo.h +++ b/src/lib/ecore/Ecore_Eo.h @@ -36,6 +36,9 @@ extern "C" { #include "ecore_event_message.eo.h" #include "ecore_event_message_handler.eo.h" +#include "efl_loop_message_future.eo.h" +#include "efl_loop_message_future_handler.eo.h" + /** * @ingroup Ecore_MainLoop_Group * diff --git a/src/lib/ecore/ecore_events.c b/src/lib/ecore/ecore_events.c index 3adbe04..3911abe 100644 --- a/src/lib/ecore/ecore_events.c +++ b/src/lib/ecore/ecore_events.c @@ -12,16 +12,16 @@ typedef struct _Ecore_Future_Schedule_Entry Eina_Future_Schedule_Entry base; Eina_Future_Scheduler_Cb cb; Eina_Future *future; - Ecore_Event *event; + Eo *event; Eina_Value value; } Ecore_Future_Schedule_Entry; ////// // XXX: still using legacy ecore events -static Ecore_Event_Handler *future_handler = NULL; +//static Ecore_Event_Handler *future_handler = NULL; static Eina_Bool shutting_down = EINA_FALSE; static Eina_Mempool *mp_future_schedule_entry = NULL; -static int ECORE_EV_FUTURE_ID = -1; +//static int ECORE_EV_FUTURE_ID = -1; // ////// @@ -71,17 +71,6 @@ ecore_event_add(int type, return (Ecore_Event *)msg; } -static void -_event_del_cb(void *data, const Efl_Event *ev) -{ - Ecore_Future_Schedule_Entry *entry = data; - if ((ev->object == (Eo *) entry->event) && entry->future) - { - eina_future_cancel(entry->future); - eina_value_flush(&entry->value); - } -} - EAPI void * ecore_event_del(Ecore_Event *event) { @@ -127,8 +116,11 @@ ecore_event_current_event_get(void) return ecore_event_message_handler_current_event_get(_event_msg_handler); } +/* XXX: static Eina_Bool -ecore_future_dispatched(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) +ecore_future_dispatched(void *data EINA_UNUSED, + int type EINA_UNUSED, + void *event) { Ecore_Future_Schedule_Entry *entry = event; EINA_SAFETY_ON_NULL_RETURN_VAL(entry, EINA_FALSE); @@ -139,7 +131,8 @@ ecore_future_dispatched(void *data EINA_UNUSED, int type EINA_UNUSED, void *eve } static void -ecore_future_free(void *user_data, void *func_data EINA_UNUSED) +ecore_future_free(void *user_data, + void *func_data EINA_UNUSED) { Ecore_Future_Schedule_Entry *entry = user_data; if (entry->event) @@ -149,10 +142,35 @@ ecore_future_free(void *user_data, void *func_data EINA_UNUSED) } eina_mempool_free(mp_future_schedule_entry, entry); } +*/ + +static void +_future_dispatch_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + Ecore_Future_Schedule_Entry *entry = data; + entry->event = NULL; + entry->cb(entry->future, entry->value); +} + +static void +_event_del_cb(void *data, const Efl_Event *ev) +{ + Ecore_Future_Schedule_Entry *entry = data; + if ((ev->object == (Eo *) entry->event) && entry->future) + { + eina_future_cancel(entry->future); + eina_value_flush(&entry->value); + } + eina_mempool_free(mp_future_schedule_entry, entry); +} static Eina_Future_Schedule_Entry * -ecore_future_schedule(Eina_Future_Scheduler *sched, Eina_Future_Scheduler_Cb cb, Eina_Future *future, Eina_Value value) +ecore_future_schedule(Eina_Future_Scheduler *sched, + Eina_Future_Scheduler_Cb cb, + Eina_Future *future, + Eina_Value value) { + Efl_Loop_Future_Scheduler *loopsched = (Efl_Loop_Future_Scheduler *)sched; Ecore_Future_Schedule_Entry *entry; entry = eina_mempool_malloc(mp_future_schedule_entry, sizeof(*entry)); @@ -161,9 +179,19 @@ ecore_future_schedule(Eina_Future_Scheduler *sched, Eina_Future_Scheduler_Cb cb, entry->cb = cb; entry->future = future; entry->value = value; - entry->event = ecore_event_add(ECORE_EV_FUTURE_ID, entry, ecore_future_free, entry); + entry->event = efl_loop_message_future_handler_message_type_add + (loopsched->loop_data->future_message_handler); EINA_SAFETY_ON_NULL_GOTO(entry->event, err); - efl_event_callback_add((Eo *) entry->event, EFL_EVENT_DEL, _event_del_cb, entry); + efl_loop_message_future_data_set(entry->event, entry); + efl_loop_message_handler_message_send + (loopsched->loop_data->future_message_handler, entry->event); +// XXX: +// entry->event = ecore_event_add(ECORE_EV_FUTURE_ID, entry, +// ecore_future_free, entry); + efl_event_callback_add((Eo *)entry->event, EFL_LOOP_MESSAGE_EVENT_MESSAGE, + _future_dispatch_cb, entry); + efl_event_callback_add((Eo *)entry->event, EFL_EVENT_DEL, + _event_del_cb, entry); return &entry->base; err: @@ -174,12 +202,17 @@ ecore_future_schedule(Eina_Future_Scheduler *sched, Eina_Future_Scheduler_Cb cb, static void ecore_future_recall(Eina_Future_Schedule_Entry *s_entry) { + Eo *msg; + if (shutting_down) return; Ecore_Future_Schedule_Entry *entry = (Ecore_Future_Schedule_Entry *)s_entry; EINA_SAFETY_ON_NULL_RETURN(entry->event); - ecore_event_del(entry->event); +// XXX: +// ecore_event_del(entry->event); + msg = entry->event; eina_value_flush(&entry->value); entry->event = NULL; + efl_del(msg); } static Eina_Future_Scheduler ecore_future_scheduler = { @@ -238,24 +271,28 @@ _ecore_event_init(void) ////// // XXX: ecore future still using legacy... shutting_down = EINA_FALSE; - ECORE_EV_FUTURE_ID = ecore_event_type_new(); - future_handler = ecore_event_handler_add(ECORE_EV_FUTURE_ID, ecore_future_dispatched, NULL); - EINA_SAFETY_ON_NULL_GOTO(future_handler, err_handler); +// ECORE_EV_FUTURE_ID = ecore_event_type_new(); +// future_handler = ecore_event_handler_add(ECORE_EV_FUTURE_ID, ecore_future_dispatched, NULL); +// EINA_SAFETY_ON_NULL_GOTO(future_handler, err_handler); //FIXME: Is 512 too high? - mp_future_schedule_entry = eina_mempool_add(choice, "Ecore_Future_Event", - NULL, sizeof(Ecore_Future_Schedule_Entry), - 512); - EINA_SAFETY_ON_NULL_GOTO(mp_future_schedule_entry, err_pool); + if (!mp_future_schedule_entry) + { + mp_future_schedule_entry = eina_mempool_add + (choice, "Ecore_Future_Event", NULL, + sizeof(Ecore_Future_Schedule_Entry), 512); + EINA_SAFETY_ON_NULL_GOTO(mp_future_schedule_entry, err_pool); + } // ////// return EINA_TRUE; err_pool: - ecore_event_handler_del(future_handler); - future_handler = NULL; - err_handler: - ECORE_EV_FUTURE_ID = -1; +// XXX: +// ecore_event_handler_del(future_handler); +// future_handler = NULL; +// err_handler: +// ECORE_EV_FUTURE_ID = -1; return EINA_FALSE; } @@ -266,9 +303,9 @@ _ecore_event_shutdown(void) ////// // XXX: ecore future still using legacy... - ecore_event_handler_del(future_handler); - future_handler = NULL; - ECORE_EV_FUTURE_ID = -1; +// ecore_event_handler_del(future_handler); +// future_handler = NULL; +// ECORE_EV_FUTURE_ID = -1; // ////// diff --git a/src/lib/ecore/ecore_private.h b/src/lib/ecore/ecore_private.h index b194029..5530c1e 100644 --- a/src/lib/ecore/ecore_private.h +++ b/src/lib/ecore/ecore_private.h @@ -84,6 +84,7 @@ typedef struct _Ecore_Factorized_Idle Ecore_Factorized_Idle; typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data; typedef struct _Efl_Loop_Timer_Data Efl_Loop_Timer_Data; +typedef struct _Efl_Loop_Future_Scheduler Efl_Loop_Future_Scheduler; typedef struct _Efl_Loop_Data Efl_Loop_Data; typedef struct _Message_Handler Message_Handler; @@ -103,11 +104,22 @@ struct _Message Eina_Bool delete_me; }; +struct _Efl_Loop_Future_Scheduler +{ + Eina_Future_Scheduler eina_future_scheduler; + Eo *loop; + Efl_Loop_Data *loop_data; +}; + struct _Efl_Loop_Data { double loop_time; Eina_Hash *providers; + Efl_Loop_Future_Scheduler future_scheduler; + + Efl_Loop_Message_Handler *future_message_handler; + Efl_Loop_Timer *poll_high; Efl_Loop_Timer *poll_medium; Efl_Loop_Timer *poll_low; diff --git a/src/lib/ecore/ecore_timer.c b/src/lib/ecore/ecore_timer.c index 0ec3592..712bd17 100644 --- a/src/lib/ecore/ecore_timer.c +++ b/src/lib/ecore/ecore_timer.c @@ -460,7 +460,10 @@ _efl_loop_timer_efl_object_parent_set(Eo *obj, Efl_Loop_Timer_Data *pd, Efl_Obje _efl_loop_timer_util_loop_clear(pd); pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS); - pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS); + if (pd->loop) + pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS); + else + pd->loop_data = NULL; if (efl_parent_get(obj) != parent) return; diff --git a/src/lib/ecore/efl_loop.c b/src/lib/ecore/efl_loop.c index cf58573..5dc1e3f 100644 --- a/src/lib/ecore/efl_loop.c +++ b/src/lib/ecore/efl_loop.c @@ -307,6 +307,8 @@ _efl_loop_efl_object_constructor(Eo *obj, Efl_Loop_Data *pd) pd->message_handlers = eina_inarray_new(sizeof(Message_Handler), 32); pd->epoll_fd = -1; pd->timer_fd = -1; + pd->future_message_handler = efl_loop_message_handler_get + (EFL_LOOP_CLASS, obj, EFL_LOOP_MESSAGE_FUTURE_HANDLER_CLASS); return obj; } @@ -315,6 +317,8 @@ _efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd) { _ecore_main_content_clear(pd); + pd->future_message_handler = NULL; + eina_hash_free(pd->providers); pd->providers = NULL; @@ -325,8 +329,11 @@ _efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd) efl_del(pd->poll_high); pd->poll_high = NULL; - eina_inarray_free(pd->message_handlers); - pd->message_handlers = NULL; + if (pd->message_handlers) + { + eina_inarray_free(pd->message_handlers); + pd->message_handlers = NULL; + } efl_destructor(efl_super(obj, EFL_LOOP_CLASS)); @@ -439,10 +446,10 @@ ecore_loop_promise_unregister(Efl_Loop *l, Efl_Promise *p) static Eina_Future * _efl_loop_job(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED) { + Eina_Future_Scheduler *sched = efl_loop_future_scheduler_get(obj); // NOTE: Eolian should do efl_future_then() to bind future to object. return efl_future_Eina_FutureXXX_then - (obj, eina_future_resolved(efl_loop_future_scheduler_get(obj), - EINA_VALUE_EMPTY)); + (obj, eina_future_resolved(sched, EINA_VALUE_EMPTY)); } EOLIAN static void @@ -479,6 +486,7 @@ _efl_loop_idle(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED) { Efl_Loop_Promise_Simple_Data *d; Eina_Promise *p; + Eina_Future_Scheduler *sched = efl_loop_future_scheduler_get(obj); d = efl_loop_promise_simple_data_calloc(1); EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL); @@ -486,8 +494,7 @@ _efl_loop_idle(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED) d->idler = ecore_idler_add(_efl_loop_idle_done, d); EINA_SAFETY_ON_NULL_GOTO(d->idler, idler_error); - p = eina_promise_new(efl_loop_future_scheduler_get(obj), - _efl_loop_idle_cancel, d); + p = eina_promise_new(sched, _efl_loop_idle_cancel, d); // d is dead if p is NULL EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL); d->promise = p; @@ -504,8 +511,11 @@ static void _efl_loop_timeout_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED) { Efl_Loop_Promise_Simple_Data *d = data; - efl_del(d->timer); - d->timer = NULL; + if (d->timer) + { + efl_del(d->timer); + d->timer = NULL; + } efl_loop_promise_simple_data_mp_free(d); } @@ -520,11 +530,19 @@ _efl_loop_timeout_done(void *data, const Efl_Event *event) efl_del(event->object); } +static void +_efl_loop_timeout_del(void *data, const Efl_Event *event EINA_UNUSED) +{ + Efl_Loop_Promise_Simple_Data *d = data; + d->timer = NULL; +} + static Eina_Future * _efl_loop_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, double tim) { Efl_Loop_Promise_Simple_Data *d; Eina_Promise *p; + Eina_Future_Scheduler *sched = efl_loop_future_scheduler_get(obj); d = efl_loop_promise_simple_data_calloc(1); EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL); @@ -533,11 +551,14 @@ _efl_loop_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, double tim) efl_loop_timer_interval_set(efl_added, tim), efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TICK, - _efl_loop_timeout_done, d)); + _efl_loop_timeout_done, d), + efl_event_callback_add(efl_added, + EFL_EVENT_DEL, + _efl_loop_timeout_del, d) + ); EINA_SAFETY_ON_NULL_GOTO(d->timer, timer_error); - p = eina_promise_new(efl_loop_future_scheduler_get(obj), - _efl_loop_timeout_cancel, d); + p = eina_promise_new(sched, _efl_loop_timeout_cancel, d); // d is dead if p is NULL EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL); d->promise = p; @@ -699,7 +720,20 @@ efl_loop_future_scheduler_get(Eo *obj) if (!obj) return NULL; if (efl_isa(obj, EFL_LOOP_CLASS)) - return _ecore_event_future_scheduler_get(); + { + Efl_Loop_Data *pd = efl_data_scope_get(obj, EFL_LOOP_CLASS); + + if (!pd) return NULL; + if (!pd->future_scheduler.loop) + { + Eina_Future_Scheduler *sched = + _ecore_event_future_scheduler_get(); + pd->future_scheduler.eina_future_scheduler = *sched; + pd->future_scheduler.loop = obj; + pd->future_scheduler.loop_data = pd; + } + return &(pd->future_scheduler.eina_future_scheduler); + } return efl_loop_future_scheduler_get(efl_loop_get(obj)); } diff --git a/src/lib/ecore/efl_loop_message.eo b/src/lib/ecore/efl_loop_message.eo index 3ef851c..db873cc 100644 --- a/src/lib/ecore/efl_loop_message.eo +++ b/src/lib/ecore/efl_loop_message.eo @@ -7,6 +7,9 @@ class Efl.Loop.Message (Efl.Object) specific message types.]] methods { } + events { + message: Efl.Loop.Message; [[The message payload data]] + } implements { Efl.Object.constructor; Efl.Object.destructor; diff --git a/src/lib/ecore/efl_loop_message_future.c b/src/lib/ecore/efl_loop_message_future.c new file mode 100644 index 0000000..6ce4f34 --- /dev/null +++ b/src/lib/ecore/efl_loop_message_future.c @@ -0,0 +1,49 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "ecore_private.h" + +#define MY_CLASS EFL_LOOP_MESSAGE_FUTURE_CLASS + +////////////////////////////////////////////////////////////////////////// + +typedef struct _Efl_Loop_Message_Future_Data Efl_Loop_Message_Future_Data; + +struct _Efl_Loop_Message_Future_Data +{ + void *data; +}; + +////////////////////////////////////////////////////////////////////////// + +EOLIAN static void +_efl_loop_message_future_data_set(Eo *obj EINA_UNUSED, Efl_Loop_Message_Future_Data *pd, void *data) +{ + pd->data = data; +} + +EOLIAN static void * +_efl_loop_message_future_data_get(Eo *obj EINA_UNUSED, Efl_Loop_Message_Future_Data *pd) +{ + return pd->data; +} + +EOLIAN static Efl_Object * +_efl_loop_message_future_efl_object_constructor(Eo *obj, Efl_Loop_Message_Future_Data *pd EINA_UNUSED) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + return obj; +} + +EOLIAN static void +_efl_loop_message_future_efl_object_destructor(Eo *obj, Efl_Loop_Message_Future_Data *pd EINA_UNUSED) +{ + efl_destructor(efl_super(obj, MY_CLASS)); +} + +////////////////////////////////////////////////////////////////////////// + +#include "efl_loop_message_future.eo.c" diff --git a/src/lib/ecore/efl_loop_message_future.eo b/src/lib/ecore/efl_loop_message_future.eo new file mode 100644 index 0000000..8cdc928 --- /dev/null +++ b/src/lib/ecore/efl_loop_message_future.eo @@ -0,0 +1,21 @@ +import efl_types; +import eina_types; + +class Efl.Loop.Message.Future (Efl.Loop.Message) +{ + [[ Used internally for futures on the loop ]] + methods { + @property data { + [[ ]] + set { } + get { } + values { + data: void_ptr; [[ ]] + } + } + } + implements { + Efl.Object.constructor; + Efl.Object.destructor; + } +} diff --git a/src/lib/ecore/efl_loop_message_future_handler.c b/src/lib/ecore/efl_loop_message_future_handler.c new file mode 100644 index 0000000..d45ed1b --- /dev/null +++ b/src/lib/ecore/efl_loop_message_future_handler.c @@ -0,0 +1,51 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "ecore_private.h" + +#define MY_CLASS EFL_LOOP_MESSAGE_FUTURE_HANDLER_CLASS + +typedef struct _Efl_Loop_Message_Future_Handler_Data Efl_Loop_Message_Future_Handler_Data; + +struct _Efl_Loop_Message_Future_Handler_Data +{ + void *data; // dummy; +}; + +////////////////////////////////////////////////////////////////////////// + +EOLIAN static Efl_Loop_Message_Future * +_efl_loop_message_future_handler_message_type_add(Eo *obj, Efl_Loop_Message_Future_Handler_Data *pd) +{ + // XXX: implemented event obj cache + return efl_add(EFL_LOOP_MESSAGE_FUTURE_CLASS, obj); +} + +EOLIAN static Efl_Object * +_efl_loop_message_future_handler_efl_object_constructor(Eo *obj, Efl_Loop_Message_Future_Handler_Data *pd EINA_UNUSED) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + return obj; +} + +EOLIAN static void +_efl_loop_message_future_handler_efl_object_destructor(Eo *obj, Efl_Loop_Message_Future_Handler_Data *pd EINA_UNUSED) +{ + efl_destructor(efl_super(obj, MY_CLASS)); +} + +EOLIAN static void +_efl_loop_message_future_handler_efl_loop_message_handler_message_call(Eo *obj, Efl_Loop_Message_Future_Handler_Data *pd EINA_UNUSED, Efl_Loop_Message *message) +{ + efl_event_callback_call + (obj, EFL_LOOP_MESSAGE_FUTURE_HANDLER_EVENT_MESSAGE_FUTURE, message); + efl_loop_message_handler_message_call + (efl_super(obj, MY_CLASS), message); +} + +////////////////////////////////////////////////////////////////////////// + +#include "efl_loop_message_future_handler.eo.c" diff --git a/src/lib/ecore/efl_loop_message_future_handler.eo b/src/lib/ecore/efl_loop_message_future_handler.eo new file mode 100644 index 0000000..e53c054 --- /dev/null +++ b/src/lib/ecore/efl_loop_message_future_handler.eo @@ -0,0 +1,21 @@ +import efl_types; +import eina_types; + +class Efl.Loop.Message.Future.Handler (Efl.Loop.Message.Handler) +{ + [[ Internal use for future on an efl loop - replacing legacy ecore events ]] + methods { + message_type_add { + [[ ]] + return: Efl.Loop.Message.Future; [[ ]] + } + } + events { + message,future: Efl.Loop.Message.Future; [[ ]] + } + implements { + Efl.Object.constructor; + Efl.Object.destructor; + Efl.Loop.Message.Handler.message_call; [[ ]] + } +} diff --git a/src/lib/ecore/efl_loop_message_handler.c b/src/lib/ecore/efl_loop_message_handler.c index 04862da..05ecdbc 100644 --- a/src/lib/ecore/efl_loop_message_handler.c +++ b/src/lib/ecore/efl_loop_message_handler.c @@ -90,6 +90,8 @@ _efl_loop_message_handler_message_call(Eo *obj, Efl_Loop_Message_Handler_Data *p msg->delete_me = EINA_TRUE; break; } + efl_event_callback_call(message, EFL_LOOP_MESSAGE_EVENT_MESSAGE, + message); efl_event_callback_call(obj, EFL_LOOP_MESSAGE_HANDLER_EVENT_MESSAGE, message); // XXX: implement message object cache... diff --git a/src/lib/eina/eina_promise.c b/src/lib/eina/eina_promise.c index 437a9cf..fbb8784 100644 --- a/src/lib/eina/eina_promise.c +++ b/src/lib/eina/eina_promise.c @@ -3,6 +3,7 @@ #endif #include "eina_private.h" +#include "eina_lock.h" #include "eina_promise.h" #include "eina_mempool.h" #include "eina_promise_private.h" @@ -117,6 +118,7 @@ struct _Eina_Future { static Eina_Mempool *_promise_mp = NULL; static Eina_Mempool *_future_mp = NULL; +static Eina_Lock _pending_futures_lock; static Eina_List *_pending_futures = NULL; static int _promise_log_dom = -1; @@ -407,7 +409,9 @@ _eina_future_dispatch(Eina_Future *f, Eina_Value value) static void _scheduled_entry_cb(Eina_Future *f, Eina_Value value) { + eina_lock_take(&_pending_futures_lock); _pending_futures = eina_list_remove(_pending_futures, f); + eina_lock_release(&_pending_futures_lock); f->scheduled_entry = NULL; _eina_future_dispatch(f, value); } @@ -436,7 +440,9 @@ _eina_future_cancel(Eina_Future *f, int err) { eina_future_schedule_entry_recall(f->scheduled_entry); f->scheduled_entry = NULL; + eina_lock_take(&_pending_futures_lock); _pending_futures = eina_list_remove(_pending_futures, f); + eina_lock_release(&_pending_futures_lock); } if (f->promise) @@ -470,7 +476,9 @@ _eina_future_schedule(Eina_Promise *p, f, value); EINA_SAFETY_ON_NULL_GOTO(f->scheduled_entry, err); assert(f->scheduled_entry->scheduler != NULL); + eina_lock_take(&_pending_futures_lock); _pending_futures = eina_list_append(_pending_futures, f); + eina_lock_release(&_pending_futures_lock); DBG("The promise %p schedule the future %p with cb: %p and data: %p", p, f, f->cb, f->data); return; @@ -523,6 +531,8 @@ eina_promise_init(void) NULL, sizeof(Eina_Future), 512); EINA_SAFETY_ON_NULL_GOTO(_future_mp, err_future); + eina_lock_recursive_new(&_pending_futures_lock); + return EINA_TRUE; err_future: @@ -537,14 +547,17 @@ eina_promise_init(void) EAPI void __eina_promise_cancel_all(void) { + eina_lock_take(&_pending_futures_lock); while (_pending_futures) _eina_future_cancel(_pending_futures->data, ECANCELED); + eina_lock_release(&_pending_futures_lock); } Eina_Bool eina_promise_shutdown(void) { __eina_promise_cancel_all(); + eina_lock_free(&_pending_futures_lock); eina_mempool_del(_future_mp); eina_mempool_del(_promise_mp); eina_log_domain_unregister(_promise_log_dom);