From 5dd52fd09b7d79c70b3134423a87aa6400a2d994 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Thu, 9 Nov 2017 15:59:04 +0900 Subject: [PATCH] ecore - begin moving data into the efl loop data in the object we really should have data inside the loop object, so begin moving it one small thing at a time. this is the basics that will allow multiple efl loops. make an eo efl object and class for fd handlers that is efl loop bound make fd handlers really bound to their parent loop and not global as well as have a nice class/obj. create an message queue per loop and put legacy ecore events on top of it... and a lot more. this is not 100% done, but it's a lot of the core and groundwork. various ecore_timer_add(), ecore_diler_add() etc. need changes. The following still need doing: ecore_timer (internal usage for sure) ecore_idler (internal usage for sure) ecore_idle_enterer ecore_idle_exiter ecore_pollers? (is the new efl loop stuff ok?) ecore_exe (fork/spawn from any thread and track exe from that thread?) ecore_signal code ecore_throttle (should we have a single global too? we have per loop) ecore_app ? (should every loop be given its own argv/argc?) Lots of internal ecore code uses/calls these legacy calls and we should have efl loop replacements and/or use the ones we have The following will bedifferently designed for loop to loop control/messaging/ipc: ecore_thread ecore_pipe --- src/Makefile_Ecore.am | 16 +- src/lib/ecore/Ecore_Eo.h | 7 + src/lib/ecore/ecore.c | 11 +- src/lib/ecore/ecore_alloc.c | 18 +- src/lib/ecore/ecore_event_message.c | 81 + src/lib/ecore/ecore_event_message.eo | 34 + src/lib/ecore/ecore_event_message_handler.c | 414 +++ src/lib/ecore/ecore_event_message_handler.eo | 86 + src/lib/ecore/ecore_events.c | 642 +--- src/lib/ecore/ecore_exe.c | 163 +- src/lib/ecore/ecore_exe_posix.c | 1524 ++++---- src/lib/ecore/ecore_exe_private.h | 7 +- src/lib/ecore/ecore_exe_win32.c | 7 +- src/lib/ecore/ecore_job.c | 2 +- src/lib/ecore/ecore_main.c | 3285 ++++++++---------- src/lib/ecore/ecore_main_common.h | 96 + src/lib/ecore/ecore_main_timechanges.c | 88 + src/lib/ecore/ecore_pipe.c | 342 +- src/lib/ecore/ecore_private.h | 168 +- src/lib/ecore/ecore_signal.c | 99 +- src/lib/ecore/ecore_time.c | 44 +- src/lib/ecore/ecore_timer.c | 435 +-- src/lib/ecore/efl_loop.c | 717 ++++ src/lib/ecore/efl_loop.eo | 37 +- src/lib/ecore/efl_loop_handler.c | 341 ++ src/lib/ecore/efl_loop_handler.eo | 72 + src/lib/ecore/efl_loop_message.c | 83 + src/lib/ecore/efl_loop_message.eo | 13 + src/lib/ecore/efl_loop_message_handler.c | 145 + src/lib/ecore/efl_loop_message_handler.eo | 38 + src/lib/ecore/efl_promise.c | 36 +- src/lib/ecore/efl_promise.eo | 1 + 32 files changed, 5071 insertions(+), 3981 deletions(-) create mode 100644 src/lib/ecore/ecore_event_message.c create mode 100644 src/lib/ecore/ecore_event_message.eo create mode 100644 src/lib/ecore/ecore_event_message_handler.c create mode 100644 src/lib/ecore/ecore_event_message_handler.eo create mode 100644 src/lib/ecore/ecore_main_common.h create mode 100644 src/lib/ecore/ecore_main_timechanges.c create mode 100644 src/lib/ecore/efl_loop.c create mode 100644 src/lib/ecore/efl_loop_handler.c create mode 100644 src/lib/ecore/efl_loop_handler.eo create mode 100644 src/lib/ecore/efl_loop_message.c create mode 100644 src/lib/ecore/efl_loop_message.eo create mode 100644 src/lib/ecore/efl_loop_message_handler.c create mode 100644 src/lib/ecore/efl_loop_message_handler.eo diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am index f96773852a..d0680de060 100644 --- a/src/Makefile_Ecore.am +++ b/src/Makefile_Ecore.am @@ -3,12 +3,17 @@ ecore_eolian_files_legacy = \ lib/ecore/ecore_exe.eo \ + lib/ecore/ecore_event_message.eo \ + lib/ecore/ecore_event_message_handler.eo \ lib/ecore/efl_loop_timer.eo ecore_eolian_files_public = \ lib/ecore/efl_loop.eo \ lib/ecore/efl_loop_consumer.eo \ lib/ecore/efl_loop_fd.eo \ + lib/ecore/efl_loop_handler.eo \ + lib/ecore/efl_loop_message.eo \ + lib/ecore/efl_loop_message_handler.eo \ lib/ecore/efl_io_closer_fd.eo \ lib/ecore/efl_io_positioner_fd.eo \ lib/ecore/efl_io_reader_fd.eo \ @@ -84,8 +89,14 @@ lib/ecore/ecore_idle_exiter.c \ lib/ecore/ecore_idler.c \ lib/ecore/ecore_job.c \ lib/ecore/ecore_main.c \ +lib/ecore/ecore_event_message.c \ +lib/ecore/ecore_event_message_handler.c \ +lib/ecore/efl_loop.c \ lib/ecore/efl_loop_consumer.c \ 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_io_closer_fd.c \ lib/ecore/efl_io_positioner_fd.c \ lib/ecore/efl_io_reader_fd.c \ @@ -115,6 +126,7 @@ lib/ecore/efl_interpolator_divisor.c \ lib/ecore/efl_interpolator_bounce.c \ lib/ecore/efl_interpolator_spring.c \ lib/ecore/efl_interpolator_cubic_bezier.c \ +lib/ecore/ecore_main_timechanges.c \ lib/ecore/ecore_pipe.c \ lib/ecore/ecore_poller.c \ lib/ecore/ecore_time.c \ @@ -124,7 +136,9 @@ lib/ecore/ecore_throttle.c \ lib/ecore/ecore_exe.c \ lib/ecore/ecore_exe_private.h \ lib/ecore/ecore_private.h \ -lib/ecore/ecore_internal.h +lib/ecore/ecore_internal.h \ +lib/ecore/ecore_main_common.h + if HAVE_WIN32 lib_ecore_libecore_la_SOURCES += lib/ecore/ecore_exe_win32.c diff --git a/src/lib/ecore/Ecore_Eo.h b/src/lib/ecore/Ecore_Eo.h index 9203bf1e4d..be1929aa42 100644 --- a/src/lib/ecore/Ecore_Eo.h +++ b/src/lib/ecore/Ecore_Eo.h @@ -29,12 +29,18 @@ */ +#include "ecore_event_message.eo.h" +#include "ecore_event_message_handler.eo.h" + /** * @ingroup Ecore_MainLoop_Group * * @{ */ +#include "efl_loop_message.eo.h" +#include "efl_loop_message_handler.eo.h" + #include "efl_loop.eo.h" /** @@ -56,6 +62,7 @@ EAPI int efl_loop_exit_code_process(Eina_Value *value); EAPI Eina_Future_Scheduler *efl_loop_future_scheduler_get(Eo *obj); #include "efl_loop_fd.eo.h" +#include "efl_loop_handler.eo.h" #include "efl_promise.eo.h" diff --git a/src/lib/ecore/ecore.c b/src/lib/ecore/ecore.c index 97dc4b2aa3..0c19d4b482 100644 --- a/src/lib/ecore/ecore.c +++ b/src/lib/ecore/ecore.c @@ -273,14 +273,12 @@ ecore_init(void) if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1; if (_ecore_fps_debug) _ecore_fps_debug_init(); if (!ecore_mempool_init()) goto shutdown_mempool; - if (!_ecore_event_init()) goto shutdown_mempool; _ecore_main_loop_init(); + if (!_ecore_event_init()) goto shutdown_event; vpath = efl_add(EFL_VPATH_CORE_CLASS, NULL); if (vpath) efl_vpath_manager_register(EFL_VPATH_MANAGER_CLASS, 0, vpath); - _mainloop_singleton = efl_add(EFL_LOOP_CLASS, NULL); - _ecore_signal_init(); #ifndef HAVE_EXOTIC _ecore_exe_init(); @@ -359,6 +357,9 @@ ecore_init(void) return _ecore_init_count; +shutdown_event: + _ecore_event_shutdown(); + _ecore_main_shutdown(); shutdown_mempool: ecore_mempool_shutdown(); efl_object_shutdown(); @@ -403,9 +404,6 @@ ecore_shutdown(void) } #endif - efl_del(_mainloop_singleton); - _mainloop_singleton = NULL; - if (_ecore_fps_debug) _ecore_fps_debug_shutdown(); _ecore_poller_shutdown(); _ecore_animator_shutdown(); @@ -442,7 +440,6 @@ ecore_shutdown(void) #ifndef HAVE_EXOTIC _ecore_exe_shutdown(); #endif - _efl_loop_timer_shutdown(); _ecore_event_shutdown(); _ecore_main_shutdown(); _ecore_signal_shutdown(); diff --git a/src/lib/ecore/ecore_alloc.c b/src/lib/ecore/ecore_alloc.c index 3196b82a2d..c98ef92335 100644 --- a/src/lib/ecore/ecore_alloc.c +++ b/src/lib/ecore/ecore_alloc.c @@ -33,9 +33,9 @@ struct _Ecore_Mempool } //GENERIC_ALLOC_FREE(Ecore_Animator, ecore_animator); -GENERIC_ALLOC_FREE(Ecore_Event_Handler, ecore_event_handler); -GENERIC_ALLOC_FREE(Ecore_Event_Filter, ecore_event_filter); -GENERIC_ALLOC_FREE(Ecore_Event, ecore_event); +//GENERIC_ALLOC_FREE(Ecore_Event_Handler, ecore_event_handler); +//GENERIC_ALLOC_FREE(Ecore_Event_Filter, ecore_event_filter); +//GENERIC_ALLOC_FREE(Ecore_Event, ecore_event); //GENERIC_ALLOC_FREE(Ecore_Idle_Exiter, ecore_idle_exiter); //GENERIC_ALLOC_FREE(Ecore_Idle_Enterer, ecore_idle_enterer); //GENERIC_ALLOC_FREE(Ecore_Idler, ecore_idler); @@ -51,9 +51,9 @@ GENERIC_ALLOC_FREE(Ecore_Win32_Handler, ecore_win32_handler); static Ecore_Mempool *mempool_array[] = { // &ecore_animator_mp, - &ecore_event_handler_mp, - &ecore_event_filter_mp, - &ecore_event_mp, +// &ecore_event_handler_mp, +// &ecore_event_filter_mp, +// &ecore_event_mp, // &ecore_idle_exiter_mp, // &ecore_idle_enterer_mp, // &ecore_idler_mp, @@ -78,9 +78,9 @@ ecore_mempool_init(void) Type##_mp.size = _ecore_sizeof_##TYPE // MP_SIZE_INIT(Ecore_Animator, ecore_animator); - MP_SIZE_INIT(Ecore_Event_Handler, ecore_event_handler); - MP_SIZE_INIT(Ecore_Event_Filter, ecore_event_filter); - MP_SIZE_INIT(Ecore_Event, ecore_event); +// MP_SIZE_INIT(Ecore_Event_Handler, ecore_event_handler); +// MP_SIZE_INIT(Ecore_Event_Filter, ecore_event_filter); +// MP_SIZE_INIT(Ecore_Event, ecore_event); // MP_SIZE_INIT(Ecore_Idle_Exiter, ecore_idle_exiter); // MP_SIZE_INIT(Ecore_Idle_Enterer, ecore_idle_enterer); // MP_SIZE_INIT(Ecore_Idler, ecore_idler); diff --git a/src/lib/ecore/ecore_event_message.c b/src/lib/ecore/ecore_event_message.c new file mode 100644 index 0000000000..ca072f8524 --- /dev/null +++ b/src/lib/ecore/ecore_event_message.c @@ -0,0 +1,81 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "ecore_private.h" + +#define MY_CLASS ECORE_EVENT_MESSAGE_CLASS + +////////////////////////////////////////////////////////////////////////// + +typedef struct _Ecore_Event_Message_Data Ecore_Event_Message_Data; + +struct _Ecore_Event_Message_Data +{ + int type; + void *ev; + Ecore_End_Cb free_func; + void *data; +}; + +////////////////////////////////////////////////////////////////////////// + +EOLIAN static void +_ecore_event_message_data_set(Eo *obj EINA_UNUSED, Ecore_Event_Message_Data *pd, int type, void *data, void *free_func, void *free_data) +{ + pd->type = type; + pd->ev = data; + pd->free_func = free_func; + pd->data = free_data; +} + +EOLIAN static void +_ecore_event_message_data_get(Eo *obj EINA_UNUSED, Ecore_Event_Message_Data *pd, int *type, void **data, void **free_func, void **free_data) +{ + if (type) *type = pd->type; + if (data) *data = pd->ev; + if (free_func) *free_func = pd->free_func; + if (free_data) *free_data = pd->data; +} + +EOLIAN static void +_ecore_event_message_data_steal(Eo *obj EINA_UNUSED, Ecore_Event_Message_Data *pd, int *type, void **data, void **free_func, void **free_data) +{ + if (type) *type = pd->type; + if (data) *data = pd->ev; + if (free_func) *free_func = pd->free_func; + if (free_data) *free_data = pd->data; + pd->type = -1; + pd->ev = NULL; + pd->free_func = NULL; + pd->data = NULL; +} + +EOLIAN static Efl_Object * +_ecore_event_message_efl_object_constructor(Eo *obj, Ecore_Event_Message_Data *pd EINA_UNUSED) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + pd->type = -1; + return obj; +} + +EOLIAN static void +_ecore_event_message_efl_object_destructor(Eo *obj EINA_UNUSED, Ecore_Event_Message_Data *pd EINA_UNUSED) +{ + if (pd->ev) + { + Ecore_End_Cb fn_free = pd->free_func; + void *ev = pd->ev; + + pd->ev = NULL; + if (fn_free) fn_free(pd->data, ev); + else free(ev); + } + efl_destructor(efl_super(obj, MY_CLASS)); +} + +////////////////////////////////////////////////////////////////////////// + +#include "ecore_event_message.eo.c" diff --git a/src/lib/ecore/ecore_event_message.eo b/src/lib/ecore/ecore_event_message.eo new file mode 100644 index 0000000000..002197a122 --- /dev/null +++ b/src/lib/ecore/ecore_event_message.eo @@ -0,0 +1,34 @@ +import efl_types; +import eina_types; + +class Ecore.Event.Message (Efl.Loop.Message) +{ + [[ For Legacy API usage Only. Legacy Ecore Events ]] + methods { + @property data { + [[ Property of the legacy event - set and get it ]] + set { } + get { } + values { + type: int; [[ The event type ]] + data: void_ptr; [[ The event data ]] + free_func: void_ptr; [[ Being lazy for legacy ]] + free_data: void_ptr; [[ Free func data ]] + } + } + data_steal { + [[ Steal the data out and set internal values to -1 + for type and NULL for other vals ]] + params { + @out type: int; [[ The event type ]] + @out data: void_ptr; [[ The event data ]] + @out free_func: void_ptr; [[ Being lazy for legacy ]] + @out free_data: void_ptr; [[ Free func data ]] + } + } + } + implements { + Efl.Object.constructor; + Efl.Object.destructor; + } +} diff --git a/src/lib/ecore/ecore_event_message_handler.c b/src/lib/ecore/ecore_event_message_handler.c new file mode 100644 index 0000000000..3879c3c78e --- /dev/null +++ b/src/lib/ecore/ecore_event_message_handler.c @@ -0,0 +1,414 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "ecore_private.h" + +#define MY_CLASS ECORE_EVENT_MESSAGE_HANDLER_CLASS + +////////////////////////////////////////////////////////////////////////// + +typedef struct _Handler Handler; +typedef struct _Filter Filter; + +struct _Handler +{ + EINA_INLIST; + Ecore_Event_Handler_Cb func; + void *data; + int type; + Eina_Bool delete_me : 1; + Eina_Bool to_add : 1; +}; + +struct _Filter +{ + EINA_INLIST; + Ecore_Data_Cb func_start; + Ecore_Filter_Cb func_filter; + Ecore_End_Cb func_end; + void *data; + void *loop_data; + Eina_Bool delete_me : 1; +}; + +typedef struct _Ecore_Event_Message_Handler_Data Ecore_Event_Message_Handler_Data; + +struct _Ecore_Event_Message_Handler_Data +{ + int event_type_count; + Eina_Inlist **handlers; // array of event_type_count inlists of handlers + Eina_Inlist *filters; + Eina_List *handlers_delete; + Eina_List *handlers_add; + Eina_List *filters_delete; + Eina_List *filters_add; + void *current_event_data; + int current_event_type; + int handlers_walking; + int filters_walking; +}; + +////////////////////////////////////////////////////////////////////////// + +Eina_Bool +_ecore_event_do_filter(void *handler_pd, Eo *msg_handler, Eo *msg) +{ + Filter *f; + void *ev; + int type; + Ecore_Event_Message_Handler_Data *eemhd = handler_pd; + + if (!eemhd->filters) return EINA_TRUE; + if (!efl_isa(msg_handler, MY_CLASS)) return EINA_TRUE; + eemhd->filters_walking++; + EINA_INLIST_FOREACH(eemhd->filters, f) + { + if (f->delete_me) continue; + type = -1; + ev = NULL; + ecore_event_message_data_get(msg, &type, &ev, NULL, NULL); + if (type >= 0) + { + if (!f->func_filter(f->data, f->loop_data, type, ev)) + _efl_loop_message_unsend(msg); + } + } + eemhd->filters_walking--; + return EINA_TRUE; +} + +void +_ecore_event_filters_call(Eo *obj, Efl_Loop_Data *pd) +{ + Filter *f; + Ecore_Event_Message_Handler_Data *eemhd; + Eo *ecore_event_handler = efl_loop_message_handler_get + (EFL_LOOP_CLASS, obj, ECORE_EVENT_MESSAGE_HANDLER_CLASS); + + if (!ecore_event_handler) return; + eemhd = efl_data_scope_get(ecore_event_handler, MY_CLASS); + if (!eemhd) return; + if (!eemhd->filters) return; + eemhd->filters_walking++; + EINA_INLIST_FOREACH(eemhd->filters, f) + { + if (f->delete_me) continue; + if (f->func_start) f->loop_data = f->func_start(f->data); + } + _efl_loop_messages_filter(obj, pd, eemhd); + EINA_INLIST_FOREACH(eemhd->filters, f) + { + if (f->delete_me) continue; + if (f->func_end) f->func_end(f->data, f->loop_data); + } + eemhd->filters_walking--; + if (eemhd->filters_walking == 0) + { + EINA_LIST_FREE(eemhd->filters_delete, f) + { + free(f); + } + } +} + +////////////////////////////////////////////////////////////////////////// + +EOLIAN static Ecore_Event_Message * +_ecore_event_message_handler_message_type_add(Eo *obj, Ecore_Event_Message_Handler_Data *pd EINA_UNUSED) +{ + // XXX: implemented event obj cache + return efl_add(ECORE_EVENT_MESSAGE_CLASS, obj); +} + +EOLIAN static int +_ecore_event_message_handler_type_new(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd) +{ + Eina_Inlist **tmp; + int evnum; + + evnum = pd->event_type_count + 1; + tmp = realloc(pd->handlers, sizeof(Eina_Inlist *) * (evnum + 1)); + if (!tmp) return 0; + pd->handlers = tmp; + pd->handlers[evnum] = NULL; + pd->event_type_count = evnum; + return evnum; +} + +EOLIAN static void * +_ecore_event_message_handler_handler_add(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd, int type, void *func, void *data) +{ + Handler *h; + + if ((type < 0) || (type > pd->event_type_count) || (!func)) return NULL; + h = calloc(1, sizeof(Handler)); + if (!h) return NULL; + h->func = func; + h->data = data; + h->type = type; + if (pd->current_event_type == type) + { + h->to_add = EINA_TRUE; + pd->handlers_add = eina_list_append(pd->handlers_add, h); + } + else + pd->handlers[type] = eina_inlist_append(pd->handlers[type], + EINA_INLIST_GET(h)); + return h; +} + +EOLIAN static void * +_ecore_event_message_handler_handler_del(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd, void *handler) +{ + Handler *h = handler; + void *data; + + if (!h) return NULL; + if ((h->type < 0) || (h->type > pd->event_type_count)) return NULL; + data = h->data; + if (pd->handlers_walking > 0) + { + h->delete_me = EINA_TRUE; + pd->handlers_delete = eina_list_append(pd->handlers_delete, h); + } + else + { + if (h->to_add) + pd->handlers_add = eina_list_remove(pd->handlers_add, h); + else + pd->handlers[h->type] = eina_inlist_remove(pd->handlers[h->type], + EINA_INLIST_GET(h)); + free(h); + } + return data; +} + +EOLIAN static void * +_ecore_event_message_handler_handler_data_get(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd EINA_UNUSED, void *handler) +{ + Handler *h = handler; + + if (!h) return NULL; + return h->data; +} + +EOLIAN static void * +_ecore_event_message_handler_handler_data_set(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd EINA_UNUSED, void *handler, void *data) +{ + Handler *h = handler; + void *prev_data; + + if (!h) return NULL; + prev_data = h->data; + h->data = data; + return prev_data; +} + +EOLIAN static void * +_ecore_event_message_handler_filter_add(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd, void *func_start, void *func_filter, void *func_end, void *data) +{ + Filter *f; + + if (!func_filter) return NULL; + f = calloc(1, sizeof(Filter)); + if (!f) return NULL; + f->func_start = func_start; + f->func_filter = func_filter; + f->func_end = func_end; + f->data = data; + pd->filters = eina_inlist_append(pd->filters, EINA_INLIST_GET(f)); + return f; +} + +EOLIAN static void * +_ecore_event_message_handler_filter_del(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd, void *filter) +{ + Filter *f = filter; + void *data; + + if (!f) return NULL; + data = f->data; + if (pd->filters_walking > 0) + { + f->delete_me = EINA_TRUE; + pd->filters_delete = eina_list_append(pd->filters_delete, f); + } + else + { + pd->filters = eina_inlist_remove(pd->filters, EINA_INLIST_GET(f)); + free(f); + } + return data; +} + +EOLIAN static int +_ecore_event_message_handler_current_type_get(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd) +{ + return pd->current_event_type; +} + +EOLIAN static void * +_ecore_event_message_handler_current_event_get(Eo *obj EINA_UNUSED, Ecore_Event_Message_Handler_Data *pd) +{ + return pd->current_event_data; +} + +EOLIAN static Efl_Object * +_ecore_event_message_handler_efl_object_constructor(Eo *obj, Ecore_Event_Message_Handler_Data *pd) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + pd->event_type_count = -1; + pd->current_event_type = -1; + return obj; +} + +EOLIAN static void +_ecore_event_message_handler_efl_object_destructor(Eo *obj, Ecore_Event_Message_Handler_Data *pd) +{ + Handler *h; + int i; + + if (pd->handlers_walking == 0) + { + EINA_LIST_FREE(pd->handlers_delete, h) + { + pd->handlers[h->type] = + eina_inlist_remove(pd->handlers[h->type], + EINA_INLIST_GET(h)); + free(h); + } + EINA_LIST_FREE(pd->handlers_add, h) + { + free(h); + } + for (i = 0; i < pd->event_type_count; i++) + { + EINA_INLIST_FREE(pd->handlers[i], h) free(h); + } + free(pd->handlers); + pd->handlers = NULL; + } + else + { + ERR("Destruction of ecore_event_message_handler while walking events"); + } + efl_destructor(efl_super(obj, MY_CLASS)); +} + +EOLIAN static void +_ecore_event_message_handler_efl_loop_message_handler_message_call(Eo *obj, Ecore_Event_Message_Handler_Data *pd, Efl_Loop_Message *message) +{ + Handler *h; + int type = -1; + void *data = NULL, *free_func = NULL, *free_data = NULL; + Ecore_End_Cb fn_free = NULL; + Eina_List *l, *l2; + int handled = 0; + + // call legacy handlers which are controled by this class' custom api + ecore_event_message_data_steal + (message, &type, &data, &free_func, &free_data); + if ((type >= 0) && (type <= pd->event_type_count)) + { + if (free_func) fn_free = free_func; + pd->current_event_data = data; + pd->current_event_type = type; + pd->handlers_walking++; + EINA_INLIST_FOREACH(pd->handlers[type], h) + { + if (h->delete_me) continue; + handled++; + if (!h->func(h->data, h->type, data)) break; + } + pd->handlers_walking--; + pd->current_event_data = NULL; + pd->current_event_type = -1; + EINA_LIST_FOREACH_SAFE(pd->handlers_add, l, l2, h) + { + if (h->type == type) + { + h->to_add = EINA_FALSE; + pd->handlers_add = + eina_list_remove_list(pd->handlers_add, l); + pd->handlers[type] = + eina_inlist_append(pd->handlers[type], EINA_INLIST_GET(h)); + } + } + if (pd->handlers_walking == 0) + { + EINA_LIST_FREE(pd->handlers_delete, h) + { + if (h->to_add) + pd->handlers_add = eina_list_remove(pd->handlers_add, h); + else + pd->handlers[h->type] = + eina_inlist_remove(pd->handlers[h->type], + EINA_INLIST_GET(h)); + free(h); + } + } + if ((type == ECORE_EVENT_SIGNAL_EXIT) && (handled == 0)) + { + Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS); + + if (loop) + { + Eina_Value v = EINA_VALUE_EMPTY; + int val = 0; + + eina_value_setup(&v, EINA_VALUE_TYPE_INT); + eina_value_set(&v, &val); + efl_loop_quit(loop, v); + } + } + } + + efl_event_callback_call + (obj, ECORE_EVENT_MESSAGE_HANDLER_EVENT_MESSAGE_ECORE_EVENT, message); + efl_loop_message_handler_message_call + (efl_super(obj, MY_CLASS), message); + + if (data) + { + if (fn_free) fn_free(free_data, data); + else free(data); + } +} + +static Eina_Bool +_flush_cb(void *data, void *handler EINA_UNUSED, void *message) +{ + int *type = data; + int evtype = -1; + void *evdata = NULL, *free_func = NULL, *free_data = NULL; + Ecore_End_Cb fn_free = NULL; + + if (!efl_isa(message, ECORE_EVENT_MESSAGE_CLASS)) return EINA_TRUE; + ecore_event_message_data_steal(message, &evtype, &evdata, &free_func, &free_data); + if (*type != evtype) return EINA_TRUE; + if (free_func) + { + fn_free = free_func; + fn_free(free_data, evdata); + } + return EINA_FALSE; +} + +EOLIAN static void +_ecore_event_message_handler_type_flush(Eo *obj, Ecore_Event_Message_Handler_Data *pd EINA_UNUSED, int type) +{ + Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS); + Efl_Loop_Data *loop_data = efl_data_scope_get(loop, EFL_LOOP_CLASS); + + if (loop && loop_data) + { + _efl_loop_messages_call(loop, loop_data, _flush_cb, &type); + } +} + +////////////////////////////////////////////////////////////////////////// + +#include "ecore_event_message_handler.eo.c" diff --git a/src/lib/ecore/ecore_event_message_handler.eo b/src/lib/ecore/ecore_event_message_handler.eo new file mode 100644 index 0000000000..78047164ca --- /dev/null +++ b/src/lib/ecore/ecore_event_message_handler.eo @@ -0,0 +1,86 @@ +import efl_types; +import eina_types; + +class Ecore.Event.Message.Handler (Efl.Loop.Message.Handler) +{ + [[ For Legacy API usage Only + This class is rather hacky/messy as it's really internal glue + to handle legacy ecore events alongside the new loop message + stuff merged together. This is ugly as it's internal only + to quickly glue things together and is destined for death in + EFL 2.0 or when we dump legacy. + ]] + methods { + message_type_add { + [[ ]] + return: Ecore.Event.Message; [[ ]] + } + type_new { + [[ ]] + return: int; [[ ]] + } + handler_add { + [[ Legacy list of callback handlers so they can return false ]] + params { + type: int; + func: void_ptr; + data: void_ptr; + } + return: void_ptr; [[ Lazy return handle ]] + } + handler_del { + params { + handler: void_ptr; [[ handler returned from handler_add() ]] + } + return: void_ptr; [[ handler data ptr ]] + } + handler_data_get { + params { + handler: void_ptr; [[ handler returned from handler_add() ]] + } + return: void_ptr; [[ handler data ptr ]] + } + handler_data_set { + params { + handler: void_ptr; [[ handler returned from handler_add() ]] + data: void_ptr; + } + return: void_ptr; [[ prev handler data ptr ]] + } + filter_add { + [[ Legacy event filter ]] + params { + func_start: void_ptr; + func_filter: void_ptr; + func_end: void_ptr; + data: void_ptr; + } + return: void_ptr; [[ Lazy return filter handle ]] + } + filter_del { + params { + filter: void_ptr; [[ filter returned from filter_add() ]] + } + return: void_ptr; [[ filter data ptr ]] + } + current_type_get { + return: int; [[ ]] + } + current_event_get { + return: void_ptr; [[ ]] + } + type_flush { + params { + type: int; [[ the event type to flush ]] + } + } + } + events { + message,ecore,event: Ecore.Event.Message; [[ Sample - override this ]] + } + implements { + Efl.Object.constructor; + Efl.Object.destructor; + Efl.Loop.Message.Handler.message_call; [[ Sample - override this ]] + } +} diff --git a/src/lib/ecore/ecore_events.c b/src/lib/ecore/ecore_events.c index ed405edb39..2a123a58fe 100644 --- a/src/lib/ecore/ecore_events.c +++ b/src/lib/ecore/ecore_events.c @@ -7,47 +7,6 @@ #include "Ecore.h" #include "ecore_private.h" -static int inpurge = 0; - -struct _Ecore_Event_Handler -{ - EINA_INLIST; - ECORE_MAGIC; - int type; - Ecore_Event_Handler_Cb func; - void *data; - int references; - Eina_Bool delete_me : 1; -}; -GENERIC_ALLOC_SIZE_DECLARE(Ecore_Event_Handler); - -struct _Ecore_Event_Filter -{ - EINA_INLIST; - ECORE_MAGIC; - Ecore_Data_Cb func_start; - Ecore_Filter_Cb func_filter; - Ecore_End_Cb func_end; - void *loop_data; - void *data; - int references; - Eina_Bool delete_me : 1; -}; -GENERIC_ALLOC_SIZE_DECLARE(Ecore_Event_Filter); - -struct _Ecore_Event -{ - EINA_INLIST; - ECORE_MAGIC; - int type; - void *event; - Ecore_End_Cb func_free; - void *data; - int references; - Eina_Bool delete_me : 1; -}; -GENERIC_ALLOC_SIZE_DECLARE(Ecore_Event); - typedef struct _Ecore_Future_Schedule_Entry { Eina_Future_Schedule_Entry base; @@ -57,131 +16,45 @@ typedef struct _Ecore_Future_Schedule_Entry Eina_Value value; } Ecore_Future_Schedule_Entry; -static int events_num = 0; -static Ecore_Event *events = NULL; -static Ecore_Event *event_current = NULL; -static Ecore_Event *purge_events = NULL; +////// +// XXX: still using legacy ecore events +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 Ecore_Event_Handler **event_handlers = NULL; -static Ecore_Event_Handler *event_handler_current = NULL; -static int event_handlers_num = 0; -static int event_handlers_alloc_num = 0; -static Eina_List *event_handlers_delete_list = NULL; - -static Ecore_Event_Handler *event_handlers_add_list = NULL; - -static Ecore_Event_Filter *event_filters = NULL; -static Ecore_Event_Filter *event_filter_current = NULL; -static Ecore_Event *event_filter_event_current = NULL; -static int event_filters_delete_me = 0; -static int event_id_max = ECORE_EVENT_COUNT; -static int ecore_raw_event_type = ECORE_EVENT_NONE; -static void *ecore_raw_event_event = NULL; -static Ecore_Event_Handler *future_handler = NULL; -static int ECORE_EV_FUTURE_ID = -1; -static Eina_Mempool *mp_future_schedule_entry = NULL; -static Eina_Bool shutting_down = EINA_FALSE; - -static void _ecore_event_purge_deleted(void); -static void *_ecore_event_del(Ecore_Event *event); +static Ecore_Event_Message_Handler *_event_msg_handler = NULL; EAPI Ecore_Event_Handler * ecore_event_handler_add(int type, Ecore_Event_Handler_Cb func, const void *data) { - Ecore_Event_Handler *eh = NULL; - - EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - - if (!func) return NULL; - if ((type <= ECORE_EVENT_NONE) || (type >= event_id_max)) return NULL; - eh = ecore_event_handler_calloc(1); - if (!eh) return NULL; - ECORE_MAGIC_SET(eh, ECORE_MAGIC_EVENT_HANDLER); - eh->type = type; - eh->func = func; - eh->data = (void *)data; - if (type >= (event_handlers_num - 1)) - { - int p_alloc_num; - - p_alloc_num = event_handlers_alloc_num; - event_handlers_num = type + 1; - if (event_handlers_num > event_handlers_alloc_num) - { - Ecore_Event_Handler **new_handlers; - int i; - - event_handlers_alloc_num = ((event_handlers_num + 16) / 16) * 16; - new_handlers = realloc(event_handlers, event_handlers_alloc_num * sizeof(Ecore_Event_Handler *)); - if (!new_handlers) - { - ecore_event_handler_mp_free(eh); - return NULL; - } - event_handlers = new_handlers; - for (i = p_alloc_num; i < event_handlers_alloc_num; i++) - event_handlers[i] = NULL; - } - } - if (ecore_raw_event_type == type) - 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)); - - return eh; + return ecore_event_message_handler_add(_event_msg_handler, + type, func, (void *)data); } EAPI void * ecore_event_handler_del(Ecore_Event_Handler *event_handler) { - if (!event_handler) return NULL; - EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - 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; - } - return _ecore_event_handler_del(event_handler); + return ecore_event_message_handler_del(_event_msg_handler, + event_handler); } EAPI void * ecore_event_handler_data_get(Ecore_Event_Handler *eh) { - EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - if (!ECORE_MAGIC_CHECK(eh, ECORE_MAGIC_EVENT_HANDLER)) - { - ECORE_MAGIC_FAIL(eh, ECORE_MAGIC_EVENT_HANDLER, "ecore_event_handler_data_get"); - return NULL; - } - return eh->data; + return ecore_event_message_handler_data_get(_event_msg_handler, eh); } EAPI void * ecore_event_handler_data_set(Ecore_Event_Handler *eh, const void *data) { - void *old = NULL; - - EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - if (!ECORE_MAGIC_CHECK(eh, ECORE_MAGIC_EVENT_HANDLER)) - { - ECORE_MAGIC_FAIL(eh, ECORE_MAGIC_EVENT_HANDLER, "ecore_event_handler_data_set"); - return NULL; - } - old = eh->data; - eh->data = (void *)data; - - return old; -} - -static void -_ecore_event_generic_free(void *data EINA_UNUSED, - void *event) -{ /* DO NOT MEMPOOL FREE THIS */ - free(event); + return ecore_event_message_handler_data_set(_event_msg_handler, eh, + (void *)data); } EAPI Ecore_Event * @@ -190,34 +63,27 @@ ecore_event_add(int type, Ecore_End_Cb func_free, void *data) { - EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); + Ecore_Event_Message *msg; - if (type <= ECORE_EVENT_NONE) return NULL; - if (type >= event_id_max) return NULL; - if ((ev) && (!func_free)) func_free = _ecore_event_generic_free; - return _ecore_event_add(type, ev, func_free, data); + msg = ecore_event_message_handler_message_type_add(_event_msg_handler); + ecore_event_message_data_set(msg, type, ev, func_free, data); + efl_loop_message_handler_message_send(_event_msg_handler, msg); + return (Ecore_Event *)msg; } EAPI void * ecore_event_del(Ecore_Event *event) { - if (!event) return NULL; - EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - if (!ECORE_MAGIC_CHECK(event, ECORE_MAGIC_EVENT)) - { - ECORE_MAGIC_FAIL(event, ECORE_MAGIC_EVENT, "ecore_event_del"); - return NULL; - } - EINA_SAFETY_ON_TRUE_RETURN_VAL(event->delete_me, NULL); - event->delete_me = 1; - return event->data; + void *data = NULL; + ecore_event_message_data_get((Eo *)event, NULL, &data, NULL, NULL); + _efl_loop_message_unsend((Eo *)event); + return data; } EAPI int ecore_event_type_new(void) { - EINA_MAIN_LOOP_CHECK_RETURN_VAL(0); - return event_id_max++; + return ecore_event_message_handler_type_new(_event_msg_handler); } EAPI Ecore_Event_Filter * @@ -226,59 +92,27 @@ ecore_event_filter_add(Ecore_Data_Cb func_start, Ecore_End_Cb func_end, const void *data) { - Ecore_Event_Filter *ef = NULL; - - EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - if (!func_filter) return NULL; - ef = ecore_event_filter_calloc(1); - if (!ef) return NULL; - 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)); - - return ef; + return ecore_event_message_handler_filter_add(_event_msg_handler, + func_start, func_filter, + func_end, (void *)data); } EAPI void * ecore_event_filter_del(Ecore_Event_Filter *ef) { - if (!ef) return NULL; - EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - if (!ECORE_MAGIC_CHECK(ef, ECORE_MAGIC_EVENT_FILTER)) - { - ECORE_MAGIC_FAIL(ef, ECORE_MAGIC_EVENT_FILTER, "ecore_event_filter_del"); - return NULL; - } - EINA_SAFETY_ON_TRUE_RETURN_VAL(ef->delete_me, NULL); - ef->delete_me = 1; - event_filters_delete_me = 1; - return ef->data; + return ecore_event_message_handler_filter_del(_event_msg_handler, ef); } EAPI int ecore_event_current_type_get(void) { - EINA_MAIN_LOOP_CHECK_RETURN_VAL(0); - return ecore_raw_event_type; + return ecore_event_message_handler_current_type_get(_event_msg_handler); } EAPI void * ecore_event_current_event_get(void) { - EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - return ecore_raw_event_event; -} - -EAPI void * -_ecore_event_handler_del(Ecore_Event_Handler *event_handler) -{ - 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; + return ecore_event_message_handler_current_event_get(_event_msg_handler); } static Eina_Bool @@ -294,12 +128,6 @@ static void ecore_future_free(void *user_data, void *func_data EINA_UNUSED) { Ecore_Future_Schedule_Entry *entry = user_data; - /* - In case entry->event is not NULL, it means - that ecore is shutting down. In this case, - we must cancel the future otherwise Eina may - try to use it and lead to crashes. - */ if (entry->event) { eina_future_cancel(entry->future); @@ -355,6 +183,44 @@ _ecore_event_init(void) const char *choice = getenv("EINA_MEMPOOL"); if ((!choice) || (!choice[0])) choice = "chained_mempool"; + _event_msg_handler = + efl_loop_message_handler_get(EFL_LOOP_CLASS, + _mainloop_singleton, + ECORE_EVENT_MESSAGE_HANDLER_CLASS); + if (!_event_msg_handler) + { + ERR("Cannot create legacy ecore event message handler"); + return EINA_FALSE; + } + // init some core legacy event types in t he same order and numbering as before + // ECORE_EVENT_NONE 0 + // no need to do as ev types start at 1 + + // ECORE_EVENT_SIGNAL_USER 1 + ecore_event_message_handler_type_new(_event_msg_handler); + // ECORE_EVENT_SIGNAL_HUP 2 + ecore_event_message_handler_type_new(_event_msg_handler); + // ECORE_EVENT_SIGNAL_EXIT 3 + ecore_event_message_handler_type_new(_event_msg_handler); + // ECORE_EVENT_SIGNAL_POWER 4 + ecore_event_message_handler_type_new(_event_msg_handler); + // ECORE_EVENT_SIGNAL_REALTIME 5 + ecore_event_message_handler_type_new(_event_msg_handler); + // ECORE_EVENT_MEMORY_STATE 6 + ecore_event_message_handler_type_new(_event_msg_handler); + // ECORE_EVENT_POWER_STATE 7 + ecore_event_message_handler_type_new(_event_msg_handler); + // ECORE_EVENT_LOCALE_CHANGED 8 + ecore_event_message_handler_type_new(_event_msg_handler); + // ECORE_EVENT_HOSTNAME_CHANGED 9 + ecore_event_message_handler_type_new(_event_msg_handler); + // ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED 10 + ecore_event_message_handler_type_new(_event_msg_handler); + // ECORE_EVENT_COUNT 11 + // no need to do as it was a count, nto an event + + ////// + // 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); @@ -364,6 +230,8 @@ _ecore_event_init(void) NULL, sizeof(Ecore_Future_Schedule_Entry), 512); EINA_SAFETY_ON_NULL_GOTO(mp_future_schedule_entry, err_pool); + // + ////// return EINA_TRUE; @@ -378,337 +246,42 @@ _ecore_event_init(void) void _ecore_event_shutdown(void) { - int i; - Ecore_Event_Handler *eh; - Ecore_Event_Filter *ef; - shutting_down = EINA_TRUE; + + ////// + // XXX: ecore future still using legacy... ecore_event_handler_del(future_handler); future_handler = NULL; - while (events) _ecore_event_del(events); - event_current = NULL; - for (i = 0; i < event_handlers_num; i++) - { - while ((eh = event_handlers[i])) - { - event_handlers[i] = (Ecore_Event_Handler *)eina_inlist_remove(EINA_INLIST_GET(event_handlers[i]), EINA_INLIST_GET(event_handlers[i])); - ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE); - if (!eh->delete_me) ecore_event_handler_mp_free(eh); - } - } - EINA_LIST_FREE(event_handlers_delete_list, eh) - ecore_event_handler_mp_free(eh); - if (event_handlers) free(event_handlers); - event_handlers = NULL; - event_handlers_num = 0; - event_handlers_alloc_num = 0; - while ((ef = event_filters)) - { - event_filters = (Ecore_Event_Filter *)eina_inlist_remove(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(event_filters)); - ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE); - ecore_event_filter_mp_free(ef); - } - event_filters_delete_me = 0; - event_filter_current = NULL; - event_filter_event_current = NULL; ECORE_EV_FUTURE_ID = -1; -} + // + ////// -int -_ecore_event_exist(void) -{ - Ecore_Event *e; - EINA_INLIST_FOREACH(events, e) - if (!e->delete_me) return 1; - return 0; -} - -Ecore_Event * -_ecore_event_add(int type, - void *ev, - Ecore_End_Cb func_free, - void *data) -{ - Ecore_Event *e; - - e = ecore_event_calloc(1); - if (!e) return NULL; - ECORE_MAGIC_SET(e, ECORE_MAGIC_EVENT); - e->type = type; - e->event = ev; - e->func_free = func_free; - e->data = data; - if (inpurge > 0) - { - purge_events = (Ecore_Event *)eina_inlist_append(EINA_INLIST_GET(purge_events), EINA_INLIST_GET(e)); - events_num++; - } - else - { - events = (Ecore_Event *)eina_inlist_append(EINA_INLIST_GET(events), EINA_INLIST_GET(e)); - events_num++; - } - return e; -} - -void * -_ecore_event_del(Ecore_Event *event) -{ - void *data; - - data = event->data; - if (event->func_free) _ecore_call_end_cb(event->func_free, event->data, event->event); - events = (Ecore_Event *)eina_inlist_remove(EINA_INLIST_GET(events), EINA_INLIST_GET(event)); - ECORE_MAGIC_SET(event, ECORE_MAGIC_NONE); - ecore_event_mp_free(event); - events_num--; - return data; -} - -static void -_ecore_event_purge_deleted(void) -{ - Ecore_Event *itr = events; - - inpurge++; - while (itr) - { - Ecore_Event *next = (Ecore_Event *)EINA_INLIST_GET(itr)->next; - if ((!itr->references) && (itr->delete_me)) - _ecore_event_del(itr); - itr = next; - } - inpurge--; - while (purge_events) - { - Ecore_Event *e = purge_events; - purge_events = (Ecore_Event *)eina_inlist_remove(EINA_INLIST_GET(purge_events), EINA_INLIST_GET(purge_events)); - events = (Ecore_Event *)eina_inlist_append(EINA_INLIST_GET(events), EINA_INLIST_GET(e)); - } -} - -static inline void -_ecore_event_filters_apply(void) -{ - if (!event_filter_current) - { - /* regular main loop, start from head */ - event_filter_current = event_filters; - } - else - { - /* recursive main loop, continue from where we were */ - event_filter_current = (Ecore_Event_Filter *)EINA_INLIST_GET(event_filter_current)->next; - } - if ((!event_filter_current) && (!event_filters_delete_me) && (!purge_events)) return; - eina_evlog("+event_filter", NULL, 0.0, NULL); - while (event_filter_current) - { - Ecore_Event_Filter *ef = event_filter_current; - - if (!ef->delete_me) - { - ef->references++; - - if (ef->func_start) - ef->loop_data = _ecore_call_data_cb(ef->func_start, ef->data); - - if (!event_filter_event_current) - { - /* regular main loop, start from head */ - event_filter_event_current = events; - } - else - { - /* recursive main loop, continue from where we were */ - event_filter_event_current = (Ecore_Event *)EINA_INLIST_GET(event_filter_event_current)->next; - } - - while (event_filter_event_current) - { - Ecore_Event *e = event_filter_event_current; - - if (!_ecore_call_filter_cb(ef->func_filter, ef->data, - ef->loop_data, e->type, e->event)) - { - ecore_event_del(e); - } - - if (event_filter_event_current) /* may have changed in recursive main loops */ - event_filter_event_current = (Ecore_Event *)EINA_INLIST_GET(event_filter_event_current)->next; - } - if (ef->func_end) - _ecore_call_end_cb(ef->func_end, ef->data, ef->loop_data); - - ef->references--; - } - - if (event_filter_current) /* may have changed in recursive main loops */ - event_filter_current = (Ecore_Event_Filter *)EINA_INLIST_GET(event_filter_current)->next; - } - eina_evlog("-event_filter", NULL, 0.0, NULL); - if (event_filters_delete_me) - { - int deleted_in_use = 0; - Ecore_Event_Filter *l; - for (l = event_filters; l; ) - { - Ecore_Event_Filter *ef = l; - l = (Ecore_Event_Filter *)EINA_INLIST_GET(l)->next; - if (ef->delete_me) - { - if (ef->references) - { - deleted_in_use++; - continue; - } - - event_filters = (Ecore_Event_Filter *)eina_inlist_remove(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(ef)); - ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE); - ecore_event_filter_mp_free(ef); - } - } - if (!deleted_in_use) - event_filters_delete_me = 0; - } -} - -void -_ecore_event_call(void) -{ - Eina_List *l, *l_next; - Ecore_Event_Handler *eh; - - _ecore_event_filters_apply(); - - if (!event_current) - { - /* regular main loop, start from head */ - event_current = events; - event_handler_current = NULL; - } - if ((!event_current) && (!event_handlers_delete_list)) return; - eina_evlog("+events", NULL, 0.0, NULL); - while (event_current) - { - Ecore_Event *e = event_current; - int handle_count = 0; - - if (e->delete_me) - { - event_current = (Ecore_Event *)EINA_INLIST_GET(event_current)->next; - continue; - } - - ecore_raw_event_type = e->type; - ecore_raw_event_event = e->event; - e->references++; - if ((e->type >= 0) && (e->type < event_handlers_num)) - { - if (!event_handler_current) - { - /* regular main loop, start from head */ - event_handler_current = event_handlers[e->type]; - } - else - { - /* recursive main loop, continue from where we were */ - event_handler_current = (Ecore_Event_Handler *)EINA_INLIST_GET(event_handler_current)->next; - } - - while ((event_handler_current) && (!e->delete_me)) - { - eh = event_handler_current; - if (!eh->delete_me) - { - Eina_Bool ret; - - handle_count++; - - eh->references++; - ret = _ecore_call_handler_cb(eh->func, eh->data, e->type, e->event); - eh->references--; - - if (!ret) - { - event_handler_current = NULL; - break; /* 0 == "call no further handlers" */ - } - } - - if (event_handler_current) /* may have changed in recursive main loops */ - event_handler_current = (Ecore_Event_Handler *)EINA_INLIST_GET(event_handler_current)->next; - } - } - while (event_handlers_add_list) - { - eh = event_handlers_add_list; - event_handlers_add_list = (Ecore_Event_Handler *)eina_inlist_remove(EINA_INLIST_GET(event_handlers_add_list), EINA_INLIST_GET(eh)); - event_handlers[eh->type] = (Ecore_Event_Handler *)eina_inlist_append(EINA_INLIST_GET(event_handlers[eh->type]), EINA_INLIST_GET(eh)); - } - /* if no handlers were set for EXIT signal - then default is */ - /* to quit the main loop */ - if ((e->type == ECORE_EVENT_SIGNAL_EXIT) && (handle_count == 0)) - ecore_main_loop_quit(); - e->references--; - e->delete_me = 1; - - if (event_current) /* may have changed in recursive main loops */ - event_current = (Ecore_Event *)EINA_INLIST_GET(event_current)->next; - } - eina_evlog("-events", NULL, 0.0, NULL); - - ecore_raw_event_type = ECORE_EVENT_NONE; - ecore_raw_event_event = NULL; - - _ecore_event_purge_deleted(); - - EINA_LIST_FOREACH_SAFE(event_handlers_delete_list, l, l_next, eh) - { - if (eh->references) continue; - - event_handlers_delete_list = eina_list_remove_list(event_handlers_delete_list, l); - - event_handlers[eh->type] = (Ecore_Event_Handler *)eina_inlist_remove(EINA_INLIST_GET(event_handlers[eh->type]), EINA_INLIST_GET(eh)); - ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE); - ecore_event_handler_mp_free(eh); - } + efl_loop_message_handler_message_clear(_event_msg_handler); + _event_msg_handler = NULL; } void * _ecore_event_signal_user_new(void) { - Ecore_Event_Signal_User *e; - - e = calloc(1, sizeof(Ecore_Event_Signal_User)); - return e; + return calloc(1, sizeof(Ecore_Event_Signal_User)); } void * _ecore_event_signal_hup_new(void) { - Ecore_Event_Signal_Hup *e; - - e = calloc(1, sizeof(Ecore_Event_Signal_Hup)); - return e; + return calloc(1, sizeof(Ecore_Event_Signal_Hup)); } void * _ecore_event_signal_exit_new(void) { - Ecore_Event_Signal_Exit *e; - - e = calloc(1, sizeof(Ecore_Event_Signal_Exit)); - return e; + return calloc(1, sizeof(Ecore_Event_Signal_Exit)); } void * _ecore_event_signal_power_new(void) { - Ecore_Event_Signal_Power *e; - - e = calloc(1, sizeof(Ecore_Event_Signal_Power)); - return e; + return calloc(1, sizeof(Ecore_Event_Signal_Power)); } void * @@ -720,58 +293,17 @@ _ecore_event_signal_realtime_new(void) EAPI void ecore_event_type_flush_internal(int type, ...) { - Eina_Inarray types; - Ecore_Event *event; - Eina_Inlist *l; - int *itr; va_list args; - Eina_Bool wrong_type = EINA_FALSE; - // In case of an empty list of event if (type == ECORE_EVENT_NONE) return; - - eina_inarray_step_set(&types, sizeof (Eina_Inarray), sizeof (int), 4); - - eina_inarray_push(&types, &type); + ecore_event_message_handler_type_flush(_event_msg_handler, type); va_start(args, type); - do + for (;;) { type = va_arg(args, int); - if (type == ECORE_EVENT_NONE) break ; - eina_inarray_push(&types, &type); + if (type == ECORE_EVENT_NONE) break; + ecore_event_message_handler_type_flush(_event_msg_handler, type); } - while (1); va_end(args); - - EINA_INARRAY_FOREACH(&types, itr) - { - if (*itr >= 0 && *itr < event_id_max) continue; - - ERR("Invalid event flush requested: %i", *itr); - wrong_type = EINA_TRUE; - } - - if (wrong_type) - { - eina_inarray_flush(&types); - return ; - } - - EINA_INLIST_FOREACH_SAFE((Eina_Inlist *) events, l, event) - { - Eina_Bool found = EINA_FALSE; - - EINA_INARRAY_FOREACH(&types, itr) - if (event->type == *itr) - found = EINA_TRUE; - if (!found) continue ; - - if (event->delete_me) continue ; - event->delete_me = 1; - } - - _ecore_event_purge_deleted(); - - eina_inarray_flush(&types); } diff --git a/src/lib/ecore/ecore_exe.c b/src/lib/ecore/ecore_exe.c index 22486cd609..908f677539 100644 --- a/src/lib/ecore/ecore_exe.c +++ b/src/lib/ecore/ecore_exe.c @@ -38,8 +38,6 @@ EAPI int ECORE_EXE_EVENT_DEL = 0; EAPI int ECORE_EXE_EVENT_DATA = 0; EAPI int ECORE_EXE_EVENT_ERROR = 0; -Eina_List *_ecore_exe_exes = NULL; - EAPI void ecore_exe_run_priority_set(int pri) { @@ -63,18 +61,19 @@ ecore_exe_run(const char *exe_cmd, } EAPI Ecore_Exe * -ecore_exe_pipe_run(const char *exe_cmd, - Ecore_Exe_Flags flags, - const void *data) +ecore_exe_pipe_run(const char *exe_cmd, + Ecore_Exe_Flags flags, + const void *data) { EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - Ecore_Exe *ret = efl_add(MY_CLASS, NULL, ecore_obj_exe_command_set(efl_added, exe_cmd, flags)); + Ecore_Exe *ret = efl_add(MY_CLASS, efl_loop_main_get(EFL_LOOP_CLASS), + ecore_obj_exe_command_set(efl_added, exe_cmd, + flags)); if (ret) { Ecore_Exe_Data *pd = efl_data_scope_get(ret, MY_CLASS); pd->data = (void *) data; } - return ret; } @@ -98,10 +97,7 @@ _ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe) { EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); obj = efl_finalize(efl_super(obj, MY_CLASS)); - - if (!obj) - return obj; - + if (!obj) return obj; return _impl_ecore_exe_efl_object_finalize(obj, exe); } @@ -111,8 +107,7 @@ ecore_exe_callback_pre_free_set(Ecore_Exe *obj, { EINA_MAIN_LOOP_CHECK_RETURN; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return; + if (!efl_isa(obj, MY_CLASS)) return; exe->pre_free_cb = func; } @@ -123,18 +118,15 @@ ecore_exe_send(Ecore_Exe *obj, { EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE); Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return EINA_FALSE; + if (!efl_isa(obj, MY_CLASS)) return EINA_FALSE; EINA_SAFETY_ON_TRUE_RETURN_VAL(size == 0, EINA_TRUE); - if (exe->close_stdin) - { - ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p", - exe, size, data); - return EINA_FALSE; - } - + { + ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p", + exe, size, data); + return EINA_FALSE; + } return _impl_ecore_exe_send(obj, exe, data, size); } @@ -143,9 +135,7 @@ ecore_exe_close_stdin(Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return; - + if (!efl_isa(obj, MY_CLASS)) return; exe->close_stdin = 1; } @@ -158,10 +148,9 @@ ecore_exe_auto_limits_set(Ecore_Exe *obj, { EINA_MAIN_LOOP_CHECK_RETURN; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return; - - _impl_ecore_exe_auto_limits_set(obj, exe, start_bytes, end_bytes, start_lines, end_lines); + if (!efl_isa(obj, MY_CLASS)) return; + _impl_ecore_exe_auto_limits_set(obj, exe, start_bytes, end_bytes, + start_lines, end_lines); } EAPI Ecore_Exe_Event_Data * @@ -170,9 +159,7 @@ ecore_exe_event_data_get(Ecore_Exe *obj, { EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return NULL; - + if (!efl_isa(obj, MY_CLASS)) return NULL; return _impl_ecore_exe_event_data_get(obj, exe, flags); } @@ -182,14 +169,10 @@ ecore_exe_tag_set(Ecore_Exe *obj, { EINA_MAIN_LOOP_CHECK_RETURN; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return; - + if (!efl_isa(obj, MY_CLASS)) return; IF_FREE(exe->tag); - if (tag) - exe->tag = strdup(tag); - else - exe->tag = NULL; + if (tag) exe->tag = strdup(tag); + else exe->tag = NULL; } EAPI const char * @@ -197,9 +180,7 @@ ecore_exe_tag_get(const Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return NULL; - + if (!efl_isa(obj, MY_CLASS)) return NULL; return exe->tag; } @@ -208,12 +189,9 @@ ecore_exe_free(Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return NULL; - + if (!efl_isa(obj, MY_CLASS)) return NULL; void *data = exe->data; efl_del(obj); - return data; } @@ -221,7 +199,6 @@ EOLIAN static void _ecore_exe_efl_object_destructor(Eo *obj, Ecore_Exe_Data *exe) { efl_destructor(efl_super(obj, ECORE_EXE_CLASS)); - _impl_ecore_exe_efl_object_destructor(obj, exe); } @@ -239,9 +216,7 @@ ecore_exe_pid_get(const Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN_VAL(0); Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return -1; - + if (!efl_isa(obj, MY_CLASS)) return -1; return exe->pid; } @@ -250,9 +225,7 @@ ecore_exe_cmd_get(const Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); const char *ret = NULL; - ecore_obj_exe_command_get(obj, &ret, NULL); - return ret; } @@ -261,9 +234,7 @@ ecore_exe_data_get(const Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return NULL; - + if (!efl_isa(obj, MY_CLASS)) return NULL; return exe->data; } @@ -274,9 +245,7 @@ ecore_exe_data_set(Ecore_Exe *obj, void *ret; EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return NULL; - + if (!efl_isa(obj, MY_CLASS)) return NULL; ret = exe->data; exe->data = data; return ret; @@ -287,9 +256,7 @@ ecore_exe_flags_get(const Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN_VAL(0); Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return 0; - + if (!efl_isa(obj, MY_CLASS)) return 0; return exe->flags; } @@ -309,15 +276,8 @@ EOLIAN static void _ecore_exe_efl_control_suspend_set(Eo *obj EINA_UNUSED, Ecore_Exe_Data *exe, Eina_Bool suspend) { EINA_MAIN_LOOP_CHECK_RETURN; - - if (suspend) - { - _impl_ecore_exe_pause(obj, exe); - } - else - { - _impl_ecore_exe_continue(obj, exe); - } + if (suspend) _impl_ecore_exe_pause(obj, exe); + else _impl_ecore_exe_continue(obj, exe); } EAPI void @@ -325,9 +285,7 @@ ecore_exe_interrupt(Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return; - + if (!efl_isa(obj, MY_CLASS)) return; _impl_ecore_exe_interrupt(obj, exe); } @@ -336,9 +294,7 @@ ecore_exe_quit(Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return; - + if (!efl_isa(obj, MY_CLASS)) return; _impl_ecore_exe_quit(obj, exe); } @@ -347,9 +303,7 @@ ecore_exe_terminate(Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return; - + if (!efl_isa(obj, MY_CLASS)) return; _impl_ecore_exe_terminate(obj, exe); } @@ -358,9 +312,7 @@ ecore_exe_kill(Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return; - + if (!efl_isa(obj, MY_CLASS)) return; _impl_ecore_exe_kill(obj, exe); } @@ -370,9 +322,7 @@ ecore_exe_signal(Ecore_Exe *obj, { EINA_MAIN_LOOP_CHECK_RETURN; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return; - + if (!efl_isa(obj, MY_CLASS)) return; _impl_ecore_exe_signal(obj, exe, num); } @@ -381,9 +331,7 @@ ecore_exe_hup(Ecore_Exe *obj) { EINA_MAIN_LOOP_CHECK_RETURN; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (!efl_isa(obj, MY_CLASS)) - return; - + if (!efl_isa(obj, MY_CLASS)) return; _impl_ecore_exe_hup(obj, exe); } @@ -401,7 +349,9 @@ _ecore_exe_shutdown(void) { Ecore_Exe *exe = NULL; Eina_List *l1, *l2; - EINA_LIST_FOREACH_SAFE(_ecore_exe_exes, l1, l2, exe) + Efl_Loop_Data *loop = EFL_LOOP_DATA; + + EINA_LIST_FOREACH_SAFE(loop->exes, l1, l2, exe) ecore_exe_free(exe); ecore_event_type_flush(ECORE_EXE_EVENT_ADD, @@ -415,22 +365,20 @@ _ecore_exe_find(pid_t pid) { Eina_List *itr; Ecore_Exe *obj; + Efl_Loop_Data *loop = EFL_LOOP_DATA; - EINA_LIST_FOREACH(_ecore_exe_exes, itr, obj) - { - Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (exe->pid == pid) - return obj; - } + EINA_LIST_FOREACH(loop->exes, itr, obj) + { + Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); + if (exe->pid == pid) return obj; + } return NULL; } void * _ecore_exe_event_del_new(void) { - Ecore_Exe_Event_Del *e; - - e = calloc(1, sizeof(Ecore_Exe_Event_Del)); + Ecore_Exe_Event_Del *e = calloc(1, sizeof(Ecore_Exe_Event_Del)); return e; } @@ -438,11 +386,8 @@ void _ecore_exe_event_del_free(void *data EINA_UNUSED, void *ev) { - Ecore_Exe_Event_Del *e; - - e = ev; - if (e->exe) - ecore_exe_free(e->exe); + Ecore_Exe_Event_Del *e = ev; + if (e->exe) ecore_exe_free(e->exe); free(e); } @@ -450,18 +395,14 @@ void _ecore_exe_event_exe_data_free(void *data EINA_UNUSED, void *ev) { - Ecore_Exe_Event_Data *e; - - e = ev; + Ecore_Exe_Event_Data *e = ev; ecore_exe_event_data_free(e); } Ecore_Exe_Event_Add * _ecore_exe_event_add_new(void) { - Ecore_Exe_Event_Add *e; - - e = calloc(1, sizeof(Ecore_Exe_Event_Add)); + Ecore_Exe_Event_Add *e = calloc(1, sizeof(Ecore_Exe_Event_Add)); return e; } @@ -469,9 +410,7 @@ void _ecore_exe_event_add_free(void *data EINA_UNUSED, void *ev) { - Ecore_Exe_Event_Add *e; - - e = ev; + Ecore_Exe_Event_Add *e = ev; free(e); } diff --git a/src/lib/ecore/ecore_exe_posix.c b/src/lib/ecore/ecore_exe_posix.c index bebfce26a1..21d8861ef2 100644 --- a/src/lib/ecore/ecore_exe_posix.c +++ b/src/lib/ecore/ecore_exe_posix.c @@ -43,60 +43,51 @@ * appended with a preceding space. The first is the command off course. */ -struct _ecore_exe_dead_exe -{ - pid_t pid; - char *cmd; -}; - -static inline void _ecore_exe_exec_it(const char *exe_cmd, +static inline void _ecore_exe_exec_it(const char *exe_cmd, Ecore_Exe_Flags flags); -static Eina_Bool _ecore_exe_data_generic_handler(void *data, +static Eina_Bool _ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, - Ecore_Exe_Flags flags); -static Eina_Bool _ecore_exe_data_error_handler(void *data, - Ecore_Fd_Handler *fd_handler); -static Eina_Bool _ecore_exe_data_read_handler(void *data, - Ecore_Fd_Handler *fd_handler); -static Eina_Bool _ecore_exe_data_write_handler(void *data, - Ecore_Fd_Handler *fd_handler); -static void _ecore_exe_flush(Ecore_Exe *obj); -static Ecore_Exe *_ecore_exe_is_it_alive(pid_t pid); -static Eina_Bool _ecore_exe_make_sure_its_dead(void *data); -static Eina_Bool _ecore_exe_make_sure_its_really_dead(void *data); -static void _ecore_exe_dead_attach(Ecore_Exe *obj); + Ecore_Exe_Flags flags); +static Eina_Bool _ecore_exe_data_error_handler(void *data, + Ecore_Fd_Handler *fd_handler); +static Eina_Bool _ecore_exe_data_read_handler(void *data, + Ecore_Fd_Handler *fd_handler); +static Eina_Bool _ecore_exe_data_write_handler(void *data, + Ecore_Fd_Handler *fd_handler); +static void _ecore_exe_flush(Ecore_Exe *obj); +static void _ecore_exe_make_sure_its_dead(void *data, const Efl_Event *event); +static void _ecore_exe_make_sure_its_really_dead(void *data, const Efl_Event *event); +static void _ecore_exe_dead_attach(Ecore_Exe *obj); static const char *shell = NULL; /* FIXME: This errno checking stuff should be put elsewhere for everybody to use. * For now it lives here though, just to make testing easier. */ -static int _ecore_exe_check_errno(int result, - const char *file, - int line); +static int _ecore_exe_check_errno(int result, + const char *file, + int line); -#define E_IF_NO_ERRNO(result, foo, ok) \ - while (((ok) = _ecore_exe_check_errno((result) = (foo), __FILE__, __LINE__)) == -1) \ - sleep(1); \ - if (ok) +#define E_IF_NO_ERRNO(result, foo, ok) \ + while (((ok) = _ecore_exe_check_errno((result) = (foo), __FILE__, __LINE__)) == -1) sleep(1); \ + if (ok) -#define E_NO_ERRNO(result, foo, ok) \ - while (((ok) = _ecore_exe_check_errno((result) = (foo), __FILE__, __LINE__)) == -1) \ - sleep(1) +#define E_NO_ERRNO(result, foo, ok) \ + while (((ok) = _ecore_exe_check_errno((result) = (foo), __FILE__, __LINE__)) == -1) sleep(1) #define E_IF_NO_ERRNO_NOLOOP(result, foo, ok) \ if (((ok) = _ecore_exe_check_errno((result) = (foo), __FILE__, __LINE__))) static int -_ecore_exe_check_errno(int result, +_ecore_exe_check_errno(int result, const char *file EINA_UNUSED, - int line EINA_UNUSED) + int line EINA_UNUSED) { int saved_errno = errno; if (result == -1) - { - perror("*** errno reports "); + { + perror("*** errno reports "); /* What is currently supported - * * pipe @@ -152,63 +143,63 @@ _ecore_exe_check_errno(int result, * // Something failed, cleanup. * } */ - switch (saved_errno) - { - case EACCES: - case EAGAIN: - case EINTR: - { /* Not now, try later. */ - ERR("*** Must try again in %s @%u.", file, line); - result = -1; - break; - } + switch (saved_errno) + { + case EACCES: + case EAGAIN: + case EINTR: + { /* Not now, try later. */ + ERR("*** Must try again in %s @%u.", file, line); + result = -1; + break; + } - case EMFILE: - case ENFILE: - case ENOLCK: - { /* Low on resources. */ - ERR("*** Low on resources in %s @%u.", file, - line); - result = 0; - break; - } + case EMFILE: + case ENFILE: + case ENOLCK: + { /* Low on resources. */ + ERR("*** Low on resources in %s @%u.", file, + line); + result = 0; + break; + } - case EIO: - { /* I/O error. */ - ERR("*** I/O error in %s @%u.", file, line); - result = 0; - break; - } + case EIO: + { /* I/O error. */ + ERR("*** I/O error in %s @%u.", file, line); + result = 0; + break; + } - case EFAULT: - case EBADF: - case EINVAL: - case EROFS: - case EISDIR: - case EDEADLK: - case EPERM: - case EBUSY: - { /* Programmer fucked up. */ - ERR("*** NAUGHTY PROGRAMMER!!!\n" - "*** SPANK SPANK SPANK!!!\n" - "*** Now go fix your code in %s @%u. Tut tut tut!", - file, line); - result = 0; - break; - } + case EFAULT: + case EBADF: + case EINVAL: + case EROFS: + case EISDIR: + case EDEADLK: + case EPERM: + case EBUSY: + { /* Programmer fucked up. */ + ERR("*** NAUGHTY PROGRAMMER!!!\n" + "*** SPANK SPANK SPANK!!!\n" + "*** Now go fix your code in %s @%u. Tut tut tut!", + file, line); + result = 0; + break; + } - default: - { /* Unsupported errno code, please add this one. */ - ERR("*** NAUGHTY PROGRAMMER!!!\n" - "*** SPANK SPANK SPANK!!!\n" - "*** Unsupported errno code %d, please add this one.\n" - "*** Now go fix your code in %s @%u, from %s @%u. Tut tut tut!", - saved_errno, __FILE__, __LINE__, file, line); - result = 0; - break; - } - } - } + default: + { /* Unsupported errno code, please add this one. */ + ERR("*** NAUGHTY PROGRAMMER!!!\n" + "*** SPANK SPANK SPANK!!!\n" + "*** Unsupported errno code %d, please add this one.\n" + "*** Now go fix your code in %s @%u, from %s @%u. Tut tut tut!", + saved_errno, __FILE__, __LINE__, file, line); + result = 0; + break; + } + } + } else /* Everything is fine. */ result = 1; @@ -260,319 +251,327 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe) /* Create some pipes. */ if (ok) - { - E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok) - { - } - } + { + E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok) + { + } + } if (ok && (flags & ECORE_EXE_PIPE_ERROR)) - { - E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok) - { - exe->child_fd_error = errorPipe[0]; - exe->child_fd_error_x = errorPipe[1]; - } - } + { + E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok) + { + exe->child_fd_error = errorPipe[0]; + exe->child_fd_error_x = errorPipe[1]; + } + } if (ok && (flags & ECORE_EXE_PIPE_READ)) - { - E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok) - { - exe->child_fd_read = readPipe[0]; - exe->child_fd_read_x = readPipe[1]; - } - } + { + E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok) + { + exe->child_fd_read = readPipe[0]; + exe->child_fd_read_x = readPipe[1]; + } + } if (ok && (flags & ECORE_EXE_PIPE_WRITE)) - { - E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok) - { - exe->child_fd_write = writePipe[1]; - exe->child_fd_write_x = writePipe[0]; - } - } + { + E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok) + { + exe->child_fd_write = writePipe[1]; + exe->child_fd_write_x = writePipe[0]; + } + } if (ok) - { - pid_t pid = 0; - volatile int vfork_exec_errno = 0; + { + pid_t pid = 0; + volatile int vfork_exec_errno = 0; - /* FIXME: I should double check this. After a quick look around, this is already done, but via a more modern method. */ - /* signal(SIGPIPE, SIG_IGN); We only want EPIPE on errors */ - pid = fork(); + /* FIXME: I should double check this. After a quick look around, this is already done, but via a more modern method. */ + /* signal(SIGPIPE, SIG_IGN); We only want EPIPE on errors */ + pid = fork(); - if (pid == -1) - { - ERR("Failed to fork process"); - pid = 0; - } - else if (pid == 0) /* child */ - { + if (pid == -1) + { + ERR("Failed to fork process"); + pid = 0; + } + else if (pid == 0) /* child */ + { #ifdef HAVE_SYSTEMD - unsetenv("NOTIFY_SOCKET"); + unsetenv("NOTIFY_SOCKET"); #endif - if (run_pri != ECORE_EXE_PRIORITY_INHERIT) - { -#ifdef PRIO_PROCESS - if ((run_pri >= -20) && (run_pri <= 19)) - setpriority(PRIO_PROCESS, 0, run_pri); + if (run_pri != ECORE_EXE_PRIORITY_INHERIT) + { +#ifdef PRIO_PROCESS + if ((run_pri >= -20) && (run_pri <= 19)) + setpriority(PRIO_PROCESS, 0, run_pri); #else #warning "Your OS/libc does not provide PRIO_PROCESS (and possibly setpriority())" #warning "This is a POSIX-1.2001 standard and it is highly encouraged that you" #warning "Have support for this" #endif - } - if (ok && (flags & ECORE_EXE_ISOLATE_IO)) - { - int devnull; + } + if (ok && (flags & ECORE_EXE_ISOLATE_IO)) + { + int devnull; - /* we want to isolatie the stdin/out/err of the process so - * it can't share those of the parent, so close and replace with - * /dev/null */ - devnull = open("/dev/null", O_RDONLY); - if (devnull >= 0) - { - E_NO_ERRNO(result, close(STDIN_FILENO), ok); - E_NO_ERRNO(result, dup2(devnull, STDIN_FILENO), ok); - E_NO_ERRNO(result, close(devnull), ok); - } + /* we want to isolatie the stdin/out/err of the process so + * it can't share those of the parent, so close and replace with + * /dev/null */ + devnull = open("/dev/null", O_RDONLY); + if (devnull >= 0) + { + E_NO_ERRNO(result, close(STDIN_FILENO), ok); + E_NO_ERRNO(result, dup2(devnull, STDIN_FILENO), ok); + E_NO_ERRNO(result, close(devnull), ok); + } - devnull = open("/dev/null", O_WRONLY); - if (devnull >= 0) - { - E_NO_ERRNO(result, close(STDOUT_FILENO), ok); - E_NO_ERRNO(result, dup2(devnull, STDOUT_FILENO), ok); - E_NO_ERRNO(result, close(devnull), ok); - } + devnull = open("/dev/null", O_WRONLY); + if (devnull >= 0) + { + E_NO_ERRNO(result, close(STDOUT_FILENO), ok); + E_NO_ERRNO(result, dup2(devnull, STDOUT_FILENO), ok); + E_NO_ERRNO(result, close(devnull), ok); + } - devnull = open("/dev/null", O_WRONLY); - if (devnull >= 0) - { - E_NO_ERRNO(result, close(STDERR_FILENO), ok); - E_NO_ERRNO(result, dup2(devnull, STDERR_FILENO), ok); - E_NO_ERRNO(result, close(devnull), ok); - } - } - else - { - /* dup2 STDERR, STDIN, and STDOUT. dup2() allegedly closes the - * second pipe if it's open. On the other hand, there was the - * Great FD Leak Scare of '06, so let's be paranoid. */ - if (ok && (flags & ECORE_EXE_PIPE_ERROR)) - { - E_NO_ERRNO(result, close(STDERR_FILENO), ok); - E_NO_ERRNO(result, dup2(errorPipe[1], STDERR_FILENO), ok); - } - if (ok && (flags & ECORE_EXE_PIPE_READ)) - { - E_NO_ERRNO(result, close(STDOUT_FILENO), ok); - E_NO_ERRNO(result, dup2(readPipe[1], STDOUT_FILENO), ok); - } - if (ok && (flags & ECORE_EXE_PIPE_WRITE)) - { - E_NO_ERRNO(result, close(STDIN_FILENO), ok); - E_NO_ERRNO(result, dup2(writePipe[0], STDIN_FILENO), ok); - } - } + devnull = open("/dev/null", O_WRONLY); + if (devnull >= 0) + { + E_NO_ERRNO(result, close(STDERR_FILENO), ok); + E_NO_ERRNO(result, dup2(devnull, STDERR_FILENO), ok); + E_NO_ERRNO(result, close(devnull), ok); + } + } + else + { + /* dup2 STDERR, STDIN, and STDOUT. dup2() allegedly closes the + * second pipe if it's open. On the other hand, there was the + * Great FD Leak Scare of '06, so let's be paranoid. */ + if (ok && (flags & ECORE_EXE_PIPE_ERROR)) + { + E_NO_ERRNO(result, close(STDERR_FILENO), ok); + E_NO_ERRNO(result, dup2(errorPipe[1], STDERR_FILENO), ok); + } + if (ok && (flags & ECORE_EXE_PIPE_READ)) + { + E_NO_ERRNO(result, close(STDOUT_FILENO), ok); + E_NO_ERRNO(result, dup2(readPipe[1], STDOUT_FILENO), ok); + } + if (ok && (flags & ECORE_EXE_PIPE_WRITE)) + { + E_NO_ERRNO(result, close(STDIN_FILENO), ok); + E_NO_ERRNO(result, dup2(writePipe[0], STDIN_FILENO), ok); + } + } - if (ok) - { - /* Setup the status pipe. */ - E_NO_ERRNO(result, close(statusPipe[0]), ok); - E_IF_NO_ERRNO(result, eina_file_close_on_exec(statusPipe[1], EINA_TRUE), ok) /* close on exec shows success */ - { - /* Run the actual command. */ - _ecore_exe_exec_it(exe_cmd, flags); /* no return */ - } - } - - /* Something went 'orribly wrong. */ - vfork_exec_errno = errno; - - /* Close the pipes. */ - if (flags & ECORE_EXE_PIPE_ERROR) - E_NO_ERRNO(result, close(errorPipe[1]), ok); - if (flags & ECORE_EXE_PIPE_READ) - E_NO_ERRNO(result, close(readPipe[1]), ok); - if (flags & ECORE_EXE_PIPE_WRITE) - E_NO_ERRNO(result, close(writePipe[0]), ok); - E_NO_ERRNO(result, close(statusPipe[1]), ok); - - _exit(-1); - } - else /* parent */ - { - /* Close the unused pipes. */ - E_NO_ERRNO(result, close(statusPipe[1]), ok); - - /* FIXME: after having a good look at the current e fd - * handling, investigate fcntl(dataPipe[x], F_SETSIG, ...) */ - /* FIXME: above F_SETSIG etc. - this is async SIGIO based IO - * which is also linux specific so we probably don't want to - * do this as long as select() is working fine. the only time - * we really want to think of SIGIO async IO is when it all - * actually works basically everywhere and we can turn all - * IO into DMA async activities (i.e. you do a read() then - * the read is complete not on return but when you get a - * SIGIO - the read() just starts the transfer and it is - * completed in the background by DMA (or whatever mechanism - * the kernel choses)) */ - - /* Wait for it to start executing. */ - /* FIXME: this doesn't seem very nice - we sit and block - * waiting on a child process... even though it's just - * the segment between the fork() and the exec) it just feels - * wrong */ - for (;; ) - { - char buf; - - E_NO_ERRNO(result, read(statusPipe[0], &buf, 1), ok); - if (result == 0) - { - if (vfork_exec_errno != 0) - { - n = vfork_exec_errno; - ERR("Could not start \"%s\"", exe_cmd); - pid = 0; - } - break; - } - } - - /* Close the status pipe. */ + if (ok) + { + /* Setup the status pipe. */ E_NO_ERRNO(result, close(statusPipe[0]), ok); - } + E_IF_NO_ERRNO(result, eina_file_close_on_exec(statusPipe[1], EINA_TRUE), ok) /* close on exec shows success */ + { + /* Run the actual command. */ + _ecore_exe_exec_it(exe_cmd, flags); /* no return */ + } + } - if (pid) + /* Something went 'orribly wrong. */ + vfork_exec_errno = errno; + + /* Close the pipes. */ + if (flags & ECORE_EXE_PIPE_ERROR) + E_NO_ERRNO(result, close(errorPipe[1]), ok); + if (flags & ECORE_EXE_PIPE_READ) + E_NO_ERRNO(result, close(readPipe[1]), ok); + if (flags & ECORE_EXE_PIPE_WRITE) + E_NO_ERRNO(result, close(writePipe[0]), ok); + E_NO_ERRNO(result, close(statusPipe[1]), ok); + + _exit(-1); + } + else /* parent */ + { + /* Close the unused pipes. */ + E_NO_ERRNO(result, close(statusPipe[1]), ok); + + /* FIXME: after having a good look at the current e fd + * handling, investigate fcntl(dataPipe[x], F_SETSIG, ...) */ + /* FIXME: above F_SETSIG etc. - this is async SIGIO based IO + * which is also linux specific so we probably don't want to + * do this as long as select() is working fine. the only time + * we really want to think of SIGIO async IO is when it all + * actually works basically everywhere and we can turn all + * IO into DMA async activities (i.e. you do a read() then + * the read is complete not on return but when you get a + * SIGIO - the read() just starts the transfer and it is + * completed in the background by DMA (or whatever mechanism + * the kernel choses)) */ + + /* Wait for it to start executing. */ + /* FIXME: this doesn't seem very nice - we sit and block + * waiting on a child process... even though it's just + * the segment between the fork() and the exec) it just feels + * wrong */ + for (;; ) { - /* Setup the exe structure. */ - exe->start_bytes = -1; - exe->end_bytes = -1; - exe->start_lines = -1; - exe->end_lines = -1; - exe->pid = pid; - exe->flags = flags; - if (exe->cmd) - { - if (flags & ECORE_EXE_PIPE_ERROR) /* Setup the error stuff. */ - { - E_IF_NO_ERRNO(result, - fcntl(exe->child_fd_error, F_SETFL, - O_NONBLOCK), ok) { - } - E_IF_NO_ERRNO(result, - eina_file_close_on_exec(exe->child_fd_error, EINA_TRUE), - ok) { - } - E_IF_NO_ERRNO(result, - eina_file_close_on_exec(exe->child_fd_error_x, EINA_TRUE), - ok) { - } - { - exe->error_fd_handler = - ecore_main_fd_handler_add(exe->child_fd_error, - ECORE_FD_READ, - _ecore_exe_data_error_handler, - obj, NULL, NULL); - if (!exe->error_fd_handler) - ok = 0; - } - } - if (ok && (flags & ECORE_EXE_PIPE_READ)) /* Setup the read stuff. */ - { - E_IF_NO_ERRNO(result, - fcntl(exe->child_fd_read, F_SETFL, - O_NONBLOCK), ok) { - } - E_IF_NO_ERRNO(result, - eina_file_close_on_exec(exe->child_fd_read, EINA_TRUE), - ok) { - } - E_IF_NO_ERRNO(result, - eina_file_close_on_exec(exe->child_fd_read_x, EINA_TRUE), - ok) { - } - { - exe->read_fd_handler = - ecore_main_fd_handler_add(exe->child_fd_read, - ECORE_FD_READ, - _ecore_exe_data_read_handler, - obj, NULL, NULL); - if (!exe->read_fd_handler) - ok = 0; - } - } - if (ok && (flags & ECORE_EXE_PIPE_WRITE)) /* Setup the write stuff. */ - { - E_IF_NO_ERRNO(result, - fcntl(exe->child_fd_write, F_SETFL, - O_NONBLOCK), ok) { - } - E_IF_NO_ERRNO(result, - eina_file_close_on_exec(exe->child_fd_write, EINA_TRUE), - ok) { - } - E_IF_NO_ERRNO(result, - eina_file_close_on_exec(exe->child_fd_write_x, EINA_TRUE), - ok) { - } - { - exe->write_fd_handler = - ecore_main_fd_handler_add(exe->child_fd_write, - ECORE_FD_WRITE, - _ecore_exe_data_write_handler, - obj, NULL, NULL); - if (exe->write_fd_handler) - ecore_main_fd_handler_active_set(exe->write_fd_handler, 0); /* Nothing to write to start with. */ - else - ok = 0; - } - } + char buf; - _ecore_exe_exes = eina_list_append(_ecore_exe_exes, obj); - n = 0; - } - else - ok = 0; + E_NO_ERRNO(result, read(statusPipe[0], &buf, 1), ok); + if (result == 0) + { + if (vfork_exec_errno != 0) + { + n = vfork_exec_errno; + ERR("Could not start \"%s\"", exe_cmd); + pid = 0; + } + break; + } } - else - ok = 0; - } + + /* Close the status pipe. */ + E_NO_ERRNO(result, close(statusPipe[0]), ok); + } + + if (pid) + { + /* Setup the exe structure. */ + exe->start_bytes = -1; + exe->end_bytes = -1; + exe->start_lines = -1; + exe->end_lines = -1; + exe->pid = pid; + exe->flags = flags; + if (exe->cmd) + { + if (flags & ECORE_EXE_PIPE_ERROR) /* Setup the error stuff. */ + { + E_IF_NO_ERRNO(result, + fcntl(exe->child_fd_error, F_SETFL, + O_NONBLOCK), ok) { + } + E_IF_NO_ERRNO(result, + eina_file_close_on_exec(exe->child_fd_error, EINA_TRUE), + ok) { + } + E_IF_NO_ERRNO(result, + eina_file_close_on_exec(exe->child_fd_error_x, EINA_TRUE), + ok) { + } + { + // XXX: eoify ecore fd handlers + exe->error_fd_handler = + ecore_main_fd_handler_add(exe->child_fd_error, + ECORE_FD_READ, + _ecore_exe_data_error_handler, + obj, NULL, NULL); + if (!exe->error_fd_handler) + ok = 0; + } + } + if (ok && (flags & ECORE_EXE_PIPE_READ)) /* Setup the read stuff. */ + { + E_IF_NO_ERRNO(result, + fcntl(exe->child_fd_read, F_SETFL, + O_NONBLOCK), ok) { + } + E_IF_NO_ERRNO(result, + eina_file_close_on_exec(exe->child_fd_read, EINA_TRUE), + ok) { + } + E_IF_NO_ERRNO(result, + eina_file_close_on_exec(exe->child_fd_read_x, EINA_TRUE), + ok) { + } + { + // XXX: eoify ecore fd handlers + exe->read_fd_handler = + ecore_main_fd_handler_add(exe->child_fd_read, + ECORE_FD_READ, + _ecore_exe_data_read_handler, + obj, NULL, NULL); + if (!exe->read_fd_handler) + ok = 0; + } + } + if (ok && (flags & ECORE_EXE_PIPE_WRITE)) /* Setup the write stuff. */ + { + E_IF_NO_ERRNO(result, + fcntl(exe->child_fd_write, F_SETFL, + O_NONBLOCK), ok) { + } + E_IF_NO_ERRNO(result, + eina_file_close_on_exec(exe->child_fd_write, EINA_TRUE), + ok) { + } + E_IF_NO_ERRNO(result, + eina_file_close_on_exec(exe->child_fd_write_x, EINA_TRUE), + ok) { + } + { + // XXX: eoify ecore fd handlers + exe->write_fd_handler = + ecore_main_fd_handler_add(exe->child_fd_write, + ECORE_FD_WRITE, + _ecore_exe_data_write_handler, + obj, NULL, NULL); + // XXX: eoify ecore fd handlers + if (exe->write_fd_handler) + ecore_main_fd_handler_active_set(exe->write_fd_handler, 0); /* Nothing to write to start with. */ + else + ok = 0; + } + } + + exe->loop = efl_provider_find(obj, EFL_LOOP_CLASS); + Efl_Loop_Data *loop = efl_data_scope_get(exe->loop, EFL_LOOP_CLASS); + if (loop) loop->exes = eina_list_append(loop->exes, obj); + n = 0; + } + else + ok = 0; + } + else + ok = 0; + } if (!ok) /* Something went wrong, so pull down everything. */ - { - if (exe->pid) ecore_exe_terminate(obj); - obj = NULL; - } + { + // XXX: eoify terminate method + if (exe->pid) ecore_exe_terminate(obj); + obj = NULL; + } else - { - Ecore_Exe_Event_Add *e; + { + Ecore_Exe_Event_Add *e; - e = _ecore_exe_event_add_new(); - if (e) - { - e->exe = obj; - /* Send the event. */ - ecore_event_add(ECORE_EXE_EVENT_ADD, e, - _ecore_exe_event_add_free, NULL); - } - /* INF("Running as %d for %s.\n", exe->pid, exe->cmd); */ - } + e = _ecore_exe_event_add_new(); + if (e) + { + e->exe = obj; + // XXX: eoify ecore_event_add + /* Send the event. */ + ecore_event_add(ECORE_EXE_EVENT_ADD, e, + _ecore_exe_event_add_free, NULL); + } + /* INF("Running as %d for %s.\n", exe->pid, exe->cmd); */ + } errno = n; return obj; } Eina_Bool -_impl_ecore_exe_send(Ecore_Exe *obj EINA_UNUSED, - Ecore_Exe_Data *exe, - const void *data, - int size) +_impl_ecore_exe_send(Ecore_Exe *obj EINA_UNUSED, + Ecore_Exe_Data *exe, + const void *data, + int size) { void *buf; if (exe->child_fd_write == -1) { ERR("Ecore_Exe %p created without ECORE_EXE_PIPE_WRITE! " - "Cannot send %d bytes from %p", exe, size, data); + "Cannot send %d bytes from %p", exe, size, data); return EINA_FALSE; } @@ -583,19 +582,20 @@ _impl_ecore_exe_send(Ecore_Exe *obj EINA_UNUSED, memcpy((char *)exe->write_data_buf + exe->write_data_size, data, size); exe->write_data_size += size; + // XXX: eoify ecore_fd_handlers if (exe->write_fd_handler) - ecore_main_fd_handler_active_set(exe->write_fd_handler, ECORE_FD_WRITE); + ecore_main_fd_handler_active_set(exe->write_fd_handler, ECORE_FD_WRITE); return EINA_TRUE; } void _impl_ecore_exe_auto_limits_set(Ecore_Exe *obj EINA_UNUSED, - Ecore_Exe_Data *exe, - int start_bytes, - int end_bytes, - int start_lines, - int end_lines) + Ecore_Exe_Data *exe, + int start_bytes, + int end_bytes, + int start_lines, + int end_lines) { /* FIXME: sanitize the input. */ exe->start_bytes = start_bytes; @@ -644,9 +644,9 @@ _impl_ecore_exe_auto_limits_set(Ecore_Exe *obj EINA_UNUSED, } Ecore_Exe_Event_Data * -_impl_ecore_exe_event_data_get(Ecore_Exe *obj, - Ecore_Exe_Data *exe, - Ecore_Exe_Flags flags) +_impl_ecore_exe_event_data_get(Ecore_Exe *obj, + Ecore_Exe_Data *exe, + Ecore_Exe_Flags flags) { Ecore_Exe_Event_Data *e = NULL; int is_buffered = 0; @@ -655,130 +655,130 @@ _impl_ecore_exe_event_data_get(Ecore_Exe *obj, /* Sort out what sort of event we are. */ if (flags & ECORE_EXE_PIPE_READ) - { - flags = ECORE_EXE_PIPE_READ; - if (exe->flags & ECORE_EXE_PIPE_READ_LINE_BUFFERED) - is_buffered = 1; - } + { + flags = ECORE_EXE_PIPE_READ; + if (exe->flags & ECORE_EXE_PIPE_READ_LINE_BUFFERED) + is_buffered = 1; + } else - { - flags = ECORE_EXE_PIPE_ERROR; - if (exe->flags & ECORE_EXE_PIPE_ERROR_LINE_BUFFERED) - is_buffered = 1; - } + { + flags = ECORE_EXE_PIPE_ERROR; + if (exe->flags & ECORE_EXE_PIPE_ERROR_LINE_BUFFERED) + is_buffered = 1; + } /* Get the data. */ if (flags & ECORE_EXE_PIPE_READ) - { - inbuf = exe->read_data_buf; - inbuf_num = exe->read_data_size; - exe->read_data_buf = NULL; - exe->read_data_size = 0; - } + { + inbuf = exe->read_data_buf; + inbuf_num = exe->read_data_size; + exe->read_data_buf = NULL; + exe->read_data_size = 0; + } else - { - inbuf = exe->error_data_buf; - inbuf_num = exe->error_data_size; - exe->error_data_buf = NULL; - exe->error_data_size = 0; - } + { + inbuf = exe->error_data_buf; + inbuf_num = exe->error_data_size; + exe->error_data_buf = NULL; + exe->error_data_size = 0; + } e = calloc(1, sizeof(Ecore_Exe_Event_Data)); if (e) - { - e->exe = obj; - e->data = inbuf; - e->size = inbuf_num; + { + e->exe = obj; + e->data = inbuf; + e->size = inbuf_num; - if (is_buffered) /* Deal with line buffering. */ - { - int max = 0; - int count = 0; - int i; - int last = 0; - char *c; + if (is_buffered) /* Deal with line buffering. */ + { + int max = 0; + int count = 0; + int i; + int last = 0; + char *c; - c = (char *)inbuf; - for (i = 0; i < inbuf_num; i++) /* Find the lines. */ + c = (char *)inbuf; + for (i = 0; i < inbuf_num; i++) /* Find the lines. */ + { + if (inbuf[i] == '\n') + { + if (count >= max) { - if (inbuf[i] == '\n') - { - if (count >= max) - { - Ecore_Exe_Event_Data_Line *lines; + Ecore_Exe_Event_Data_Line *lines; - /* In testing, the lines seem to arrive in batches of 500 to 1000 lines at most, roughly speaking. */ - max += 10; /* FIXME: Maybe keep track of the largest number of lines ever sent, and add half that many instead of 10. */ - lines = realloc(e->lines, sizeof(Ecore_Exe_Event_Data_Line) * (max + 1)); /* Allow room for the NULL termination. */ - if (!lines) - { - ERR("Out of memory adding exe data lines to event"); - break; - } - e->lines = lines; - } - /* raster said to leave the line endings as line endings, however - - * This is line buffered mode, we are not dealing with binary here, but lines. - * If we are not dealing with binary, we must be dealing with ASCII, unicode, or some other text format. - * Thus the user is most likely gonna deal with this text as strings. - * Thus the user is most likely gonna pass this data to str functions. - * rasters way - the endings are always gonna be '\n'; onefangs way - they will always be '\0' - * We are handing them the string length as a convenience. - * Thus if they really want it in raw format, they can e->lines[i].line[e->lines[i].size - 1] = '\n'; easily enough. - * In the default case, we can do this conversion quicker than the user can, as we already have the index and pointer. - * Let's make it easy on them to use these as standard C strings. - * - * onefang is proud to announce that he has just set a new personal record for the - * most over documentation of a simple assignment statement. B-) - */ - inbuf[i] = '\0'; - e->lines[count].line = c; - e->lines[count].size = i - last; - last = i + 1; - c = (char *)&inbuf[last]; - count++; - } + /* In testing, the lines seem to arrive in batches of 500 to 1000 lines at most, roughly speaking. */ + max += 10; /* FIXME: Maybe keep track of the largest number of lines ever sent, and add half that many instead of 10. */ + lines = realloc(e->lines, sizeof(Ecore_Exe_Event_Data_Line) * (max + 1)); /* Allow room for the NULL termination. */ + if (!lines) + { + ERR("Out of memory adding exe data lines to event"); + break; + } + e->lines = lines; } - if (i > last) /* Partial line left over, save it for next time. */ - { - if (count != 0) e->size = last; - if (flags & ECORE_EXE_PIPE_READ) - { - exe->read_data_size = i - last; - exe->read_data_buf = malloc(exe->read_data_size); - if (exe->read_data_buf) - memcpy(exe->read_data_buf, c, exe->read_data_size); - else - { - exe->read_data_size = 0; - ERR("Out of memory in allocating exe pipe data"); - } - } - else - { - exe->error_data_size = i - last; - exe->error_data_buf = malloc(exe->error_data_size); - if (exe->error_data_buf) - memcpy(exe->error_data_buf, c, exe->error_data_size); - else - { - exe->error_data_size = 0; - ERR("Out of memory in allocating exe pipe data"); - } - } - } - if (count == 0) /* No lines to send, cancel the event. */ - { - _ecore_exe_event_exe_data_free(NULL, e); - e = NULL; - } - else /* NULL terminate the array, so that people know where the end is. */ - { - e->lines[count].line = NULL; - e->lines[count].size = 0; - } - } - } + /* raster said to leave the line endings as line endings, however - + * This is line buffered mode, we are not dealing with binary here, but lines. + * If we are not dealing with binary, we must be dealing with ASCII, unicode, or some other text format. + * Thus the user is most likely gonna deal with this text as strings. + * Thus the user is most likely gonna pass this data to str functions. + * rasters way - the endings are always gonna be '\n'; onefangs way - they will always be '\0' + * We are handing them the string length as a convenience. + * Thus if they really want it in raw format, they can e->lines[i].line[e->lines[i].size - 1] = '\n'; easily enough. + * In the default case, we can do this conversion quicker than the user can, as we already have the index and pointer. + * Let's make it easy on them to use these as standard C strings. + * + * onefang is proud to announce that he has just set a new personal record for the + * most over documentation of a simple assignment statement. B-) + */ + inbuf[i] = '\0'; + e->lines[count].line = c; + e->lines[count].size = i - last; + last = i + 1; + c = (char *)&inbuf[last]; + count++; + } + } + if (i > last) /* Partial line left over, save it for next time. */ + { + if (count != 0) e->size = last; + if (flags & ECORE_EXE_PIPE_READ) + { + exe->read_data_size = i - last; + exe->read_data_buf = malloc(exe->read_data_size); + if (exe->read_data_buf) + memcpy(exe->read_data_buf, c, exe->read_data_size); + else + { + exe->read_data_size = 0; + ERR("Out of memory in allocating exe pipe data"); + } + } + else + { + exe->error_data_size = i - last; + exe->error_data_buf = malloc(exe->error_data_size); + if (exe->error_data_buf) + memcpy(exe->error_data_buf, c, exe->error_data_size); + else + { + exe->error_data_size = 0; + ERR("Out of memory in allocating exe pipe data"); + } + } + } + if (count == 0) /* No lines to send, cancel the event. */ + { + _ecore_exe_event_exe_data_free(NULL, e); + e = NULL; + } + else /* NULL terminate the array, so that people know where the end is. */ + { + e->lines[count].line = NULL; + e->lines[count].size = 0; + } + } + } return e; } @@ -795,20 +795,9 @@ _impl_ecore_exe_efl_object_destructor(Eo *obj, Ecore_Exe_Data *exe) if (exe->pre_free_cb) exe->pre_free_cb(data, obj); - if (exe->doomsday_clock) - { - struct _ecore_exe_dead_exe *dead; + exe->doomsday_clock = NULL; - ecore_timer_del(exe->doomsday_clock); - exe->doomsday_clock = NULL; - dead = exe->doomsday_clock_dead; - if (dead) - { - IF_FREE(dead->cmd); - free(dead); - exe->doomsday_clock_dead = NULL; - } - } + // XXX: eoify ecore fd handlers IF_FN_DEL(ecore_main_fd_handler_del, exe->write_fd_handler); IF_FN_DEL(ecore_main_fd_handler_del, exe->read_fd_handler); IF_FN_DEL(ecore_main_fd_handler_del, exe->error_fd_handler); @@ -829,7 +818,8 @@ _impl_ecore_exe_efl_object_destructor(Eo *obj, Ecore_Exe_Data *exe) IF_FREE(exe->error_data_buf); IF_FREE(exe->cmd); - _ecore_exe_exes = eina_list_remove(_ecore_exe_exes, obj); + Efl_Loop_Data *loop = efl_data_scope_get(exe->loop, EFL_LOOP_CLASS); + if (loop) loop->exes = eina_list_remove(loop->exes, obj); IF_FREE(exe->tag); } @@ -870,25 +860,21 @@ _impl_ecore_exe_terminate(Ecore_Exe *obj, Ecore_Exe_Data *exe) void _impl_ecore_exe_kill(Ecore_Exe *obj EINA_UNUSED, Ecore_Exe_Data *exe) { - struct _ecore_exe_dead_exe *dead; - dead = calloc(1, sizeof(struct _ecore_exe_dead_exe)); - if (dead) - { - dead->pid = exe->pid; - dead->cmd = strdup(exe->cmd); - IF_FN_DEL(ecore_timer_del, exe->doomsday_clock); - exe->doomsday_clock = - ecore_timer_add(10.0, _ecore_exe_make_sure_its_really_dead, dead); - } - + efl_del(exe->doomsday_clock); + exe->doomsday_clock = efl_add(EFL_LOOP_TIMER_CLASS, obj, + efl_event_callback_add(efl_added, + EFL_LOOP_TIMER_EVENT_TICK, + _ecore_exe_make_sure_its_really_dead, + obj), + efl_loop_timer_interval_set(efl_added, 10.0)); INF("Sending KILL signal to %s (%d).", exe->cmd, exe->pid); kill(exe->pid, SIGKILL); } void _impl_ecore_exe_signal(Ecore_Exe *obj EINA_UNUSED, - Ecore_Exe_Data *exe, - int num) + Ecore_Exe_Data *exe, + int num) { if (num == 1) kill(exe->pid, SIGUSR1); @@ -902,102 +888,41 @@ _impl_ecore_exe_hup(Ecore_Exe *obj EINA_UNUSED, Ecore_Exe_Data *exe) kill(exe->pid, SIGHUP); } -static Ecore_Exe * -_ecore_exe_is_it_alive(pid_t pid) +static void +_ecore_exe_make_sure_its_dead(void *data, const Efl_Event *event EINA_UNUSED) { - Ecore_Exe *exe = NULL; - - /* FIXME: There is no nice, safe, OS independent way to tell if a - * particular PID is still alive. I have written code to do so - * for my urunlevel busybox applet (http://urunlevel.sourceforge.net/), - * but it's for linux only, and still not guaranteed. - * - * So for now, we just check that a valid Ecore_Exe structure - * exists for it. Even that is not a guarantee, as the structure - * can be freed without killing the process. - * - * I think we can safely put exe's into two categories, those users - * that care about the life of the exe, and the run and forget type. - * The run and forget type starts up the exe, then free's the - * Ecore_Exe structure straight away. They can never call any of - * the functions that can call this, so we don't worry about them. - * - * Those user's that care about the life of exe's will keep the - * Ecore_Exe structure around, terminate them eventually, or - * register for exit events. For these ones the assumption - * that valid Ecore_Exe struct == live exe is almost valid. - * - * I will probably copy my urunlevel code into here someday. - */ - exe = _ecore_exe_find(pid); - - return exe; -} - -static Eina_Bool -_ecore_exe_make_sure_its_dead(void *data) -{ - struct _ecore_exe_dead_exe *dead; - - dead = data; - if (dead) + Eo *exe_obj = data; + Ecore_Exe_Data *exe = efl_data_scope_get(exe_obj, MY_CLASS); + if (exe) { - Ecore_Exe *obj = NULL; - - if ((obj = _ecore_exe_is_it_alive(dead->pid))) - { - Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - if (exe) - { - if (dead->cmd) - INF("Sending KILL signal to allegedly dead %s (%d).", - dead->cmd, dead->pid); - else - INF("Sending KILL signal to allegedly dead PID %d.", - dead->pid); - exe->doomsday_clock = - ecore_timer_add(10.0, _ecore_exe_make_sure_its_really_dead, - dead); - kill(dead->pid, SIGKILL); - } - } + if (exe->cmd) + INF("Sending KILL signal to allegedly dead %s (%d).", exe->cmd, exe->pid); else - { - IF_FREE(dead->cmd); - free(dead); - } + INF("Sending KILL signal to allegedly dead PID %d.", exe->pid); + exe->doomsday_clock = efl_add(EFL_LOOP_TIMER_CLASS, exe_obj, + efl_event_callback_add(efl_added, + EFL_LOOP_TIMER_EVENT_TICK, + _ecore_exe_make_sure_its_really_dead, + exe_obj), + efl_loop_timer_interval_set(efl_added, 10.0)); + kill(exe->pid, SIGKILL); } - return ECORE_CALLBACK_CANCEL; } -static Eina_Bool -_ecore_exe_make_sure_its_really_dead(void *data) +static void +_ecore_exe_make_sure_its_really_dead(void *data, const Efl_Event *event EINA_UNUSED) { - struct _ecore_exe_dead_exe *dead; - - dead = data; - if (dead) + Eo *exe_obj = data; + Ecore_Exe_Data *exe = efl_data_scope_get(exe_obj, MY_CLASS); + if (exe) { - Ecore_Exe *obj = NULL; - - if ((obj = _ecore_exe_is_it_alive(dead->pid))) - { - Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); - - if (exe) - { - ERR("RUN! The zombie wants to eat your brains! And your CPU!"); - if (dead->cmd) - INF("%s (%d) is not really dead.", dead->cmd, dead->pid); - else - INF("PID %d is not really dead.", dead->pid); - exe->doomsday_clock = NULL; - } - IF_FREE(dead->cmd); - free(dead); - } + ERR("RUN! The zombie wants to eat your brains! And your CPU!"); + if (exe->cmd) + INF("%s (%d) is not really dead.", exe->cmd, exe->pid); + else + INF("PID %d is not really dead.", exe->pid); + exe->doomsday_clock = NULL; } - return ECORE_CALLBACK_CANCEL; } Ecore_Timer * @@ -1009,7 +934,7 @@ _ecore_exe_doomsday_clock_get(Ecore_Exe *obj) } void -_ecore_exe_doomsday_clock_set(Ecore_Exe *obj, +_ecore_exe_doomsday_clock_set(Ecore_Exe *obj, Ecore_Timer *dc) { Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); @@ -1018,7 +943,7 @@ _ecore_exe_doomsday_clock_set(Ecore_Exe *obj, } static inline void -_ecore_exe_exec_it(const char *exe_cmd, +_ecore_exe_exec_it(const char *exe_cmd, Ecore_Exe_Flags flags) { char use_sh = 1; @@ -1033,55 +958,55 @@ _ecore_exe_exec_it(const char *exe_cmd, * If we don't find them, we can call the exe directly. */ if (!strpbrk(exe_cmd, "|&;<>()$`\\\"'*?#")) - { - char *token; - char pre_command = 1; - int num_tokens = 0; - int len; + { + char *token; + char pre_command = 1; + int num_tokens = 0; + int len; - len = strlen(exe_cmd); - buf = alloca(len + 1); - strcpy(buf, exe_cmd); - buf[len] = 0; + len = strlen(exe_cmd); + buf = alloca(len + 1); + strcpy(buf, exe_cmd); + buf[len] = 0; - token = strtok(buf, " \t\n\v"); - while (token) - { - if (token[0] == '~') - break; - if (pre_command) - { - if (token[0] == '[') - break; - if (strchr(token, '=')) - break; - else - pre_command = 0; - } - num_tokens++; - token = strtok(NULL, " \t\n\v"); - } - if ((!token) && (num_tokens)) - { - int i = 0; + token = strtok(buf, " \t\n\v"); + while (token) + { + if (token[0] == '~') + break; + if (pre_command) + { + if (token[0] == '[') + break; + if (strchr(token, '=')) + break; + else + pre_command = 0; + } + num_tokens++; + token = strtok(NULL, " \t\n\v"); + } + if ((!token) && (num_tokens)) + { + int i = 0; - len = strlen(exe_cmd); - buf = alloca(len + 1); - strcpy(buf, exe_cmd); - buf[len] = 0; + len = strlen(exe_cmd); + buf = alloca(len + 1); + strcpy(buf, exe_cmd); + buf[len] = 0; - token = strtok(buf, " \t\n\v"); - use_sh = 0; - args = alloca((num_tokens + 1) * sizeof(char *)); - for (i = 0; i < num_tokens; i++) - { - if (token) - args[i] = token; - token = strtok(NULL, " \t\n\v"); - } - args[num_tokens] = NULL; - } - } + token = strtok(buf, " \t\n\v"); + use_sh = 0; + args = alloca((num_tokens + 1) * sizeof(char *)); + for (i = 0; i < num_tokens; i++) + { + if (token) + args[i] = token; + token = strtok(NULL, " \t\n\v"); + } + args[num_tokens] = NULL; + } + } #ifdef HAVE_PRCTL if ((flags & ECORE_EXE_TERM_WITH_PARENT)) @@ -1092,34 +1017,34 @@ _ecore_exe_exec_it(const char *exe_cmd, if (!(flags & ECORE_EXE_NOT_LEADER)) setsid(); if ((flags & ECORE_EXE_USE_SH)) - { - errno = 0; - execl("/bin/sh", "/bin/sh", "-c", exe_cmd, (char *)NULL); - } + { + errno = 0; + execl("/bin/sh", "/bin/sh", "-c", exe_cmd, (char *)NULL); + } else if (use_sh) /* We have to use a shell to run this. */ - { - if (!shell) /* Find users preferred shell. */ - { + { + if (!shell) /* Find users preferred shell. */ + { #if defined(HAVE_GETUID) && defined(HAVE_GETEUID) - if (getuid() == geteuid()) + if (getuid() == geteuid()) #endif - shell = getenv("SHELL"); - if (!shell) - shell = "/bin/sh"; - } - errno = 0; - execl(shell, shell, "-c", exe_cmd, (char *)NULL); - } - else /* We can run this directly. */ - { - if (!args) - { - ERR("arg[0] is NULL!"); - return; - } - errno = 0; - if (args[0]) execvp(args[0], args); - } + shell = getenv("SHELL"); + if (!shell) + shell = "/bin/sh"; + } + errno = 0; + execl(shell, shell, "-c", exe_cmd, (char *)NULL); + } + else + { /* We can run this directly. */ + if (!args) + { + ERR("arg[0] is NULL!"); + return; + } + errno = 0; + if (args[0]) execvp(args[0], args); + } save_errno = errno; errno = save_errno; @@ -1127,9 +1052,9 @@ _ecore_exe_exec_it(const char *exe_cmd, } static Eina_Bool -_ecore_exe_data_generic_handler(void *data, +_ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, - Ecore_Exe_Flags flags) + Ecore_Exe_Flags flags) { Ecore_Exe *obj = data; int child_fd; @@ -1141,139 +1066,142 @@ _ecore_exe_data_generic_handler(void *data, /* Sort out what sort of handler we are. */ if (flags & ECORE_EXE_PIPE_READ) - { - flags = ECORE_EXE_PIPE_READ; - event_type = ECORE_EXE_EVENT_DATA; - eo_event = ECORE_EXE_EVENT_DATA_GET; - child_fd = exe->child_fd_read; - } + { + flags = ECORE_EXE_PIPE_READ; + event_type = ECORE_EXE_EVENT_DATA; + eo_event = ECORE_EXE_EVENT_DATA_GET; + child_fd = exe->child_fd_read; + } else - { - flags = ECORE_EXE_PIPE_ERROR; - event_type = ECORE_EXE_EVENT_ERROR; - eo_event = ECORE_EXE_EVENT_DATA_ERROR; - child_fd = exe->child_fd_error; - } + { + flags = ECORE_EXE_PIPE_ERROR; + event_type = ECORE_EXE_EVENT_ERROR; + eo_event = ECORE_EXE_EVENT_DATA_ERROR; + child_fd = exe->child_fd_error; + } if ((fd_handler) && (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))) - { - unsigned char *inbuf, *temp; - int inbuf_num; + { + unsigned char *inbuf, *temp; + int inbuf_num; - /* Get any left over data from last time. */ - if (flags & ECORE_EXE_PIPE_READ) - { - inbuf = exe->read_data_buf; - inbuf_num = exe->read_data_size; - exe->read_data_buf = NULL; - exe->read_data_size = 0; - } - else - { - inbuf = exe->error_data_buf; - inbuf_num = exe->error_data_size; - exe->error_data_buf = NULL; - exe->error_data_size = 0; - } + /* Get any left over data from last time. */ + if (flags & ECORE_EXE_PIPE_READ) + { + inbuf = exe->read_data_buf; + inbuf_num = exe->read_data_size; + exe->read_data_buf = NULL; + exe->read_data_size = 0; + } + else + { + inbuf = exe->error_data_buf; + inbuf_num = exe->error_data_size; + exe->error_data_buf = NULL; + exe->error_data_size = 0; + } - for (;; ) - { - int num, lost_exe; - char buf[READBUFSIZ]; + for (;; ) + { + int num, lost_exe; + char buf[READBUFSIZ]; - lost_exe = 0; - errno = 0; - if ((num = read(child_fd, buf, READBUFSIZ)) < 1) + lost_exe = 0; + errno = 0; + if ((num = read(child_fd, buf, READBUFSIZ)) < 1) + { + /* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE + * (currently 64k) to inbuf, use that instead of buf, and + * save ourselves a memcpy(). */ + lost_exe = ((errno == EIO) || + (errno == EBADF) || + (errno == EPIPE) || + (errno == EINVAL) || (errno == ENOSPC)); + if ((errno != EAGAIN) && (errno != EINTR)) + perror("_ecore_exe_generic_handler() read problem "); + } + if (num > 0) /* data got read. */ + { + temp = inbuf; + inbuf = realloc(inbuf, inbuf_num + num); + if (inbuf) + { + memcpy(inbuf + inbuf_num, buf, num); + inbuf_num += num; + } + else // realloc fails and returns NULL. + { + ERR("Out of memory in exe generic data handler"); + inbuf = temp; + } + } + else + { /* No more data to read. */ + if (inbuf) + { + Ecore_Exe_Event_Data *e; + + /* Stash the data away for later. */ + if (flags & ECORE_EXE_PIPE_READ) { - /* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE - * (currently 64k) to inbuf, use that instead of buf, and - * save ourselves a memcpy(). */ - lost_exe = ((errno == EIO) || - (errno == EBADF) || - (errno == EPIPE) || - (errno == EINVAL) || (errno == ENOSPC)); - if ((errno != EAGAIN) && (errno != EINTR)) - perror("_ecore_exe_generic_handler() read problem "); + exe->read_data_buf = inbuf; + exe->read_data_size = inbuf_num; } - if (num > 0) /* data got read. */ + else { - temp = inbuf; - inbuf = realloc(inbuf, inbuf_num + num); - if (inbuf) + exe->error_data_buf = inbuf; + exe->error_data_size = inbuf_num; + } + + if (!(exe->flags & ECORE_EXE_PIPE_AUTO)) + { + // XXX: use eo method + e = ecore_exe_event_data_get(obj, flags); + if (e) /* Send the event. */ { - memcpy(inbuf + inbuf_num, buf, num); - inbuf_num += num; - } - else // realloc fails and returns NULL. - { - ERR("Out of memory in exe generic data handler"); - inbuf = temp; + // XXX: eoify ecore event + ecore_event_add(event_type, e, + _ecore_exe_event_exe_data_free, + NULL); + efl_event_callback_call(obj, eo_event, e); } } - else /* No more data to read. */ + } + if (lost_exe) + { + if (flags & ECORE_EXE_PIPE_READ) { - if (inbuf) - { - Ecore_Exe_Event_Data *e; - - /* Stash the data away for later. */ - if (flags & ECORE_EXE_PIPE_READ) - { - exe->read_data_buf = inbuf; - exe->read_data_size = inbuf_num; - } - else - { - exe->error_data_buf = inbuf; - exe->error_data_size = inbuf_num; - } - - if (!(exe->flags & ECORE_EXE_PIPE_AUTO)) - { - e = ecore_exe_event_data_get(obj, flags); - if (e) /* Send the event. */ - { - ecore_event_add(event_type, e, - _ecore_exe_event_exe_data_free, - NULL); - efl_event_callback_call(obj, eo_event, e); - } - } - } - if (lost_exe) - { - if (flags & ECORE_EXE_PIPE_READ) - { - if (exe->read_data_size) - INF("There are %d bytes left unsent from the dead exe %s.", - exe->read_data_size, exe->cmd); - } - else - { - if (exe->error_data_size) - INF("There are %d bytes left unsent from the dead exe %s.", - exe->error_data_size, exe->cmd); - } - /* Thought about this a bit. If the exe has actually - * died, this won't do any harm as it must have died - * recently and the pid has not had a chance to recycle. - * It is also a paranoid catchall, coz the usual ecore_signal - * mechanism should kick in. But let's give it a good - * kick in the head anyway. - */ - ecore_exe_terminate(obj); - } - break; + if (exe->read_data_size) + INF("There are %d bytes left unsent from the dead exe %s.", + exe->read_data_size, exe->cmd); } - } - } + else + { + if (exe->error_data_size) + INF("There are %d bytes left unsent from the dead exe %s.", + exe->error_data_size, exe->cmd); + } + /* Thought about this a bit. If the exe has actually + * died, this won't do any harm as it must have died + * recently and the pid has not had a chance to recycle. + * It is also a paranoid catchall, coz the usual ecore_signal + * mechanism should kick in. But let's give it a good + * kick in the head anyway. + */ + // XXX: use eo method + ecore_exe_terminate(obj); + } + break; + } + } + } return ECORE_CALLBACK_RENEW; } static Eina_Bool -_ecore_exe_data_error_handler(void *data, +_ecore_exe_data_error_handler(void *data, Ecore_Fd_Handler *fd_handler) { return _ecore_exe_data_generic_handler(data, fd_handler, @@ -1281,7 +1209,7 @@ _ecore_exe_data_error_handler(void *data, } static Eina_Bool -_ecore_exe_data_read_handler(void *data, +_ecore_exe_data_read_handler(void *data, Ecore_Fd_Handler *fd_handler) { return _ecore_exe_data_generic_handler(data, fd_handler, @@ -1289,7 +1217,7 @@ _ecore_exe_data_read_handler(void *data, } static Eina_Bool -_ecore_exe_data_write_handler(void *data, +_ecore_exe_data_write_handler(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED) { Ecore_Exe *obj = data; @@ -1297,9 +1225,10 @@ _ecore_exe_data_write_handler(void *data, if (!exe) return EINA_FALSE; + // XXX: use eo method if ((exe->write_fd_handler) && (ecore_main_fd_handler_active_get - (exe->write_fd_handler, ECORE_FD_WRITE))) + (exe->write_fd_handler, ECORE_FD_WRITE))) _ecore_exe_flush(obj); /* If we have sent all there is to send, and we need to close the pipe, then close it. */ @@ -1339,7 +1268,9 @@ _ecore_exe_flush(Ecore_Exe *obj) { if (errno == EIO || errno == EBADF || errno == EPIPE || errno == EINVAL || errno == ENOSPC) /* we lost our exe! */ { + // XXX: use eo method (eoify) ecore_exe_terminate(obj); + // XXX: eoify fd handlers if (exe->write_fd_handler) ecore_main_fd_handler_active_set(exe->write_fd_handler, 0); } @@ -1352,6 +1283,7 @@ _ecore_exe_flush(Ecore_Exe *obj) exe->write_data_size = 0; exe->write_data_offset = 0; IF_FREE(exe->write_data_buf); + // XXX: eoify fd handlers if (exe->write_fd_handler) ecore_main_fd_handler_active_set(exe->write_fd_handler, 0); } @@ -1361,20 +1293,14 @@ _ecore_exe_flush(Ecore_Exe *obj) static void _ecore_exe_dead_attach(Ecore_Exe *obj) { - struct _ecore_exe_dead_exe *dead; Ecore_Exe_Data *exe = efl_data_scope_get(obj, MY_CLASS); if (!exe) return; - if (exe->doomsday_clock_dead) return; - dead = calloc(1, sizeof(struct _ecore_exe_dead_exe)); - if (dead) - { - dead->pid = exe->pid; - if (exe->cmd) dead->cmd = strdup(exe->cmd); - IF_FN_DEL(ecore_timer_del, exe->doomsday_clock); - exe->doomsday_clock = - ecore_timer_add(10.0, _ecore_exe_make_sure_its_dead, dead); - exe->doomsday_clock_dead = dead; - } + if (exe->doomsday_clock) return; + exe->doomsday_clock = efl_add(EFL_LOOP_TIMER_CLASS, obj, + efl_event_callback_add(efl_added, + EFL_LOOP_TIMER_EVENT_TICK, + _ecore_exe_make_sure_its_dead, + obj), + efl_loop_timer_interval_set(efl_added, 10.0)); } - diff --git a/src/lib/ecore/ecore_exe_private.h b/src/lib/ecore/ecore_exe_private.h index 17a726d368..aad66fc1da 100644 --- a/src/lib/ecore/ecore_exe_private.h +++ b/src/lib/ecore/ecore_exe_private.h @@ -68,10 +68,9 @@ typedef enum struct _Ecore_Exe_Data { - pid_t pid; void *data; char *tag, *cmd; - Ecore_Exe_Flags flags; + Eo *loop; #ifdef _WIN32 HANDLE process; @@ -124,10 +123,11 @@ struct _Ecore_Exe_Data int start_bytes, end_bytes, start_lines, end_lines; /* Number of bytes/lines to auto pipe at start/end of stdout/stderr. */ Ecore_Timer *doomsday_clock; /* The Timer of Death. Muahahahaha. */ - void *doomsday_clock_dead; /* data for the doomsday clock */ #endif Ecore_Exe_Cb pre_free_cb; + pid_t pid; + Ecore_Exe_Flags flags; Eina_Bool close_stdin : 1; }; @@ -137,7 +137,6 @@ EAPI extern int ECORE_EXE_EVENT_ADD; EAPI extern int ECORE_EXE_EVENT_DEL; EAPI extern int ECORE_EXE_EVENT_DATA; EAPI extern int ECORE_EXE_EVENT_ERROR; -extern Eina_List *_ecore_exe_exes; Ecore_Exe *_ecore_exe_find(pid_t pid); void *_ecore_exe_event_del_new(void); diff --git a/src/lib/ecore/ecore_exe_win32.c b/src/lib/ecore/ecore_exe_win32.c index 204f13e353..7ca179a482 100644 --- a/src/lib/ecore/ecore_exe_win32.c +++ b/src/lib/ecore/ecore_exe_win32.c @@ -528,7 +528,9 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe) goto error; } - _ecore_exe_exes = eina_list_append(_ecore_exe_exes, obj); + exe->loop = efl_provider_find(obj, EFL_LOOP_CLASS); + Efl_Loop_Data *loop = efl_data_scope_get(exe->loop, EFL_LOOP_CLASS); + if (loop) loop->exes = eina_list_append(loop->exes, obj); e = calloc(1, sizeof(Ecore_Exe_Event_Add)); if (!e) goto error; @@ -711,7 +713,8 @@ _impl_ecore_exe_efl_object_destructor(Eo *obj, Ecore_Exe_Data *exe) IF_FREE(exe->cmd); - _ecore_exe_exes = eina_list_remove(_ecore_exe_exes, obj); + Efl_Loop_Data *loop = efl_data_scope_get(exe->loop, EFL_LOOP_CLASS); + if (loop) loop->exes = eina_list_remove(loop->exes, obj); IF_FREE(exe->tag); } diff --git a/src/lib/ecore/ecore_job.c b/src/lib/ecore/ecore_job.c index f302b44a99..41ddbb2148 100644 --- a/src/lib/ecore/ecore_job.c +++ b/src/lib/ecore/ecore_job.c @@ -35,7 +35,7 @@ _ecore_job_init(void) void _ecore_job_shutdown(void) { - _ecore_event_handler_del(_ecore_job_handler); + ecore_event_handler_del(_ecore_job_handler); _ecore_job_handler = NULL; } diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c index 6a5ea42def..59631892e7 100644 --- a/src/lib/ecore/ecore_main.c +++ b/src/lib/ecore/ecore_main.c @@ -25,7 +25,7 @@ #endif #ifdef HAVE_IEEEFP_H -# include /* for Solaris */ +# include // for Solaris #endif #ifdef _MSC_VER @@ -60,120 +60,31 @@ #include "Ecore.h" #include "ecore_private.h" -#if defined(HAVE_SYS_EPOLL_H) && !defined(HAVE_LIBUV) -# define HAVE_EPOLL 1 -# include -#else - -# define HAVE_EPOLL 0 -# define EPOLLIN 1 -# define EPOLLPRI 2 -# define EPOLLOUT 4 -# define EPOLLERR 8 - -#define EPOLL_CTL_ADD 1 -#define EPOLL_CTL_DEL 2 -#define EPOLL_CTL_MOD 3 - -typedef union epoll_data { - void *ptr; - int fd; - uint32_t u32; - uint64_t u64; -} epoll_data_t; - -struct epoll_event -{ - uint32_t events; - epoll_data_t data; -}; - -static inline int -epoll_create(int size EINA_UNUSED) -{ - return -1; -} - -static inline int -epoll_wait(int epfd EINA_UNUSED, - struct epoll_event *events EINA_UNUSED, - int maxevents EINA_UNUSED, - int timeout EINA_UNUSED) -{ - return -1; -} - -static inline int -epoll_ctl(int epfd EINA_UNUSED, - int op EINA_UNUSED, - int fd EINA_UNUSED, - struct epoll_event *event EINA_UNUSED) -{ - return -1; -} - -#endif - -#ifdef HAVE_SYS_TIMERFD_H -# include -#else -/* fallback code if we don't have real timerfd - reduces number of ifdefs */ -# ifndef CLOCK_MONOTONIC -# define CLOCK_MONOTONIC 0 /* bogus value */ -# endif -# ifndef TFD_NONBLOCK -# define TFD_NONBLOCK 0 /* bogus value */ -# endif -#endif /* HAVE_SYS_TIMERFD_H */ - -#ifndef TFD_TIMER_ABSTIME -# define TFD_TIMER_ABSTIME (1 << 0) -#endif -#ifndef TFD_TIMER_CANCELON_SET -# define TFD_TIMER_CANCELON_SET (1 << 1) -#endif - -#ifndef HAVE_TIMERFD_CREATE -static inline int -timerfd_create(int clockid EINA_UNUSED, - int flags EINA_UNUSED) -{ - return -1; -} - -static inline int -timerfd_settime(int fd EINA_UNUSED, - int flags EINA_UNUSED, - const struct itimerspec *new_value EINA_UNUSED, - struct itimerspec *old_value EINA_UNUSED) -{ - return -1; -} - -#endif /* HAVE_TIMERFD_CREATE */ +#include "ecore_main_common.h" #ifdef USE_G_MAIN_LOOP # include #endif #ifdef HAVE_LIBUV -#ifdef HAVE_NODE_UV_H -#include -#elif defined(HAVE_NODEJS_DEPS_UV_UV_H) -#include -#elif defined(HAVE_NODEJS_DEPS_UV_INCLUDE_UV_H) -#include -#elif defined(HAVE_NODEJS_SRC_UV_H) -#include -#elif defined(HAVE_UV_H) -#include -#else -#error No uv.h header found? -#endif +# ifdef HAVE_NODE_UV_H +# include +# elif defined(HAVE_NODEJS_DEPS_UV_UV_H) +# include +# elif defined(HAVE_NODEJS_DEPS_UV_INCLUDE_UV_H) +# include +# elif defined(HAVE_NODEJS_SRC_UV_H) +# include +# elif defined(HAVE_UV_H) +# include +# else +# error No uv.h header found? +# endif -#if defined HAVE_DLOPEN && ! defined _WIN32 -# include -#endif +// XXX: FIXME: use eina_module +# if defined(HAVE_DLOPEN) && !defined(_WIN32) +# include +# endif static uv_prepare_t _ecore_main_uv_prepare; static uv_check_t _ecore_main_uv_check; @@ -203,73 +114,70 @@ static int (*_dl_uv_check_stop)(uv_check_t* prepare); static int (*_dl_uv_close)(uv_handle_t* handle, uv_close_cb close_cb); #endif -#define NS_PER_SEC (1000.0 * 1000.0 * 1000.0) +#define NS_PER_SEC (1000000000.0) struct _Ecore_Fd_Handler { EINA_INLIST; - ECORE_MAGIC; - Ecore_Fd_Handler *next_ready; - int fd; - Ecore_Fd_Handler_Flags flags; - Ecore_Fd_Cb func; - void *data; - Ecore_Fd_Cb buf_func; - void *buf_data; - Ecore_Fd_Prep_Cb prep_func; - void *prep_data; - int references; - Eina_Bool read_active : 1; - Eina_Bool write_active : 1; - Eina_Bool error_active : 1; - Eina_Bool delete_me : 1; - Eina_Bool file : 1; + ECORE_MAGIC; + Ecore_Fd_Handler *next_ready; + int fd; + Ecore_Fd_Handler_Flags flags; + Eo *handler; + Eo *loop; + Efl_Loop_Data *loop_data; + Ecore_Fd_Cb func; + void *data; + Ecore_Fd_Cb buf_func; + void *buf_data; + Ecore_Fd_Prep_Cb prep_func; + void *prep_data; + int references; #if defined(USE_G_MAIN_LOOP) - GPollFD gfd; + GPollFD gfd; #endif #ifdef HAVE_LIBUV - uv_poll_t uv_handle; + uv_poll_t uv_handle; #endif + Eina_Bool read_active : 1; + Eina_Bool write_active : 1; + Eina_Bool error_active : 1; + Eina_Bool delete_me : 1; + Eina_Bool file : 1; }; GENERIC_ALLOC_SIZE_DECLARE(Ecore_Fd_Handler); -typedef struct _Efl_Loop_Promise_Simple_Data { - union { - Ecore_Timer *timer; - Ecore_Idler *idler; - }; - Eina_Promise *promise; -} Efl_Loop_Promise_Simple_Data; -GENERIC_ALLOC_SIZE_DECLARE(Efl_Loop_Promise_Simple_Data); - #ifdef _WIN32 struct _Ecore_Win32_Handler { EINA_INLIST; - ECORE_MAGIC; - HANDLE h; - Ecore_Win32_Handle_Cb func; - void *data; - int references; - Eina_Bool delete_me : 1; + ECORE_MAGIC; + HANDLE h; + Eo *handler; + Eo *loop; + Efl_Loop_Data *loop_data; + Ecore_Win32_Handle_Cb func; + void *data; + int references; + Eina_Bool delete_me : 1; }; GENERIC_ALLOC_SIZE_DECLARE(Ecore_Win32_Handler); #endif #if !defined(USE_G_MAIN_LOOP) && !defined(HAVE_LIBUV) -static int _ecore_main_select(double timeout); +static int _ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout); #endif -static void _ecore_main_prepare_handlers(void); -static void _ecore_main_fd_handlers_cleanup(void); +static void _ecore_main_prepare_handlers(Eo *obj, Efl_Loop_Data *pd); +static void _ecore_main_fd_handlers_cleanup(Eo *obj, Efl_Loop_Data *pd); #ifndef _WIN32 # ifndef USE_G_MAIN_LOOP -static void _ecore_main_fd_handlers_bads_rem(void); +static void _ecore_main_fd_handlers_bads_rem(Eo *obj, Efl_Loop_Data *pd); # endif #endif -static void _ecore_main_fd_handlers_call(void); -static int _ecore_main_fd_handlers_buf_call(void); +static void _ecore_main_fd_handlers_call(Eo *obj, Efl_Loop_Data *pd); +static int _ecore_main_fd_handlers_buf_call(Eo *obj, Efl_Loop_Data *pd); #ifndef USE_G_MAIN_LOOP -static void _ecore_main_loop_iterate_internal(int once_only); +static void _ecore_main_loop_iterate_internal(Eo *obj, Efl_Loop_Data *pd, int once_only); #endif #ifdef _WIN32 @@ -278,127 +186,96 @@ static int _ecore_main_win32_select(int nfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); -static void _ecore_main_win32_handlers_cleanup(void); +static void _ecore_main_win32_handlers_cleanup(Eo *obj, Efl_Loop_Data *pd); #endif +static void _ecore_main_loop_setup(Eo *obj, Efl_Loop_Data *pd); +static void _ecore_main_loop_clear(Eo *obj, Efl_Loop_Data *pd); + +// for legacy mainloop only and not other loops int in_main_loop = 0; - -static Eina_List *_pending_futures = NULL; -static Eina_List *_pending_promises = NULL; -#if (defined __GNUC__) && (__GNUC__ <= 4) -// GCC 4 does not support compound literal for statics initializers in C99 -static Eina_Value _ecore_exit_code = {0}; -# else -static Eina_Value _ecore_exit_code = EINA_VALUE_EMPTY; -#endif -static int do_quit = 0; -static Ecore_Fd_Handler *fd_handlers = NULL; -static Ecore_Fd_Handler *fd_handler_current = NULL; -static Eina_List *fd_handlers_with_prep = NULL; -static Eina_List *file_fd_handlers = NULL; -static Eina_List *fd_handlers_with_buffer = NULL; -static Eina_List *fd_handlers_to_delete = NULL; - -/* single linked list of ready fdhs, terminated by loop to self */ -static Ecore_Fd_Handler *fd_handlers_to_call; -static Ecore_Fd_Handler *fd_handlers_to_call_current; - -#ifdef _WIN32 -static Ecore_Win32_Handler *win32_handlers = NULL; -static Ecore_Win32_Handler *win32_handler_current = NULL; -static Eina_List *win32_handlers_to_delete = NULL; -#endif - -#ifdef _WIN32 -Ecore_Select_Function main_loop_select = _ecore_main_win32_select; -#else -# if !defined EXOTIC_NO_SELECT -# include -Ecore_Select_Function main_loop_select = select; -# else -Ecore_Select_Function main_loop_select = NULL; -# endif -#endif - #ifndef USE_G_MAIN_LOOP static double t1 = 0.0; static double t2 = 0.0; #endif -#ifdef HAVE_EPOLL -static int epoll_fd = -1; -static pid_t epoll_pid; +#ifdef _WIN32 +Ecore_Select_Function main_loop_select = _ecore_main_win32_select; +static Ecore_Select_Function general_loop_select = _ecore_main_win32_select; +#else +# include +Ecore_Select_Function main_loop_select = select; +static Ecore_Select_Function general_loop_select = select; #endif -static int timer_fd = -1; #ifdef USE_G_MAIN_LOOP -static GPollFD ecore_epoll_fd; -static GPollFD ecore_timer_fd; -static GSource *ecore_glib_source; -static guint ecore_glib_source_id; +static GPollFD ecore_epoll_fd; +static GPollFD ecore_timer_fd; +static GSource *ecore_glib_source; +static guint ecore_glib_source_id; static GMainLoop *ecore_main_loop; -static gboolean ecore_idling; -static gboolean _ecore_glib_idle_enterer_called; -static gboolean ecore_fds_ready; +static gboolean ecore_idling; +static gboolean _ecore_glib_idle_enterer_called; +static gboolean ecore_fds_ready; #endif #ifdef EFL_EXTRA_SANITY_CHECKS static inline void -_ecore_fd_valid(void) +_ecore_fd_valid(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) { -#ifdef HAVE_EPOLL - if (epoll_fd >= 0) +# ifdef HAVE_EPOLL + if ((pd->epoll_fd >= 0) && + (fcntl(pd->epoll_fd, F_GETFD) < 0)) { - if (fcntl(epoll_fd, F_GETFD) < 0) - { - ERR("arghhh you caught me! report a backtrace to edevel!"); -#ifdef HAVE_PAUSE - pause(); -#else - sleep(60); -#endif - } + ERR("arghhh you caught me! report a backtrace to edevel!"); +# ifdef HAVE_PAUSE + pause(); +# else + sleep(60); +# endif } -#endif +# endif } #endif static inline void -_ecore_try_add_to_call_list(Ecore_Fd_Handler *fdh) +_ecore_try_add_to_call_list(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, Ecore_Fd_Handler *fdh) { - /* check if this fdh is already in the list */ + // check if this fdh is already in the list if (fdh->next_ready) { - DBG("next_ready"); - return; + DBG("next_ready"); + return; } if (fdh->read_active || fdh->write_active || fdh->error_active) { - DBG("added"); - /* - * make sure next_ready is non-null by pointing to ourselves - * use that to indicate this fdh is in the ready list - * insert at the head of the list to avoid trouble - */ - fdh->next_ready = fd_handlers_to_call ? fd_handlers_to_call : fdh; - fd_handlers_to_call = fdh; + DBG("added"); + // make sure next_ready is non-null by pointing to ourselves + // use that to indicate this fdh is in the ready list + // insert at the head of the list to avoid trouble + fdh->next_ready = pd->fd_handlers_to_call ? pd->fd_handlers_to_call : fdh; + pd->fd_handlers_to_call = fdh; } } +static inline void +_throttle_do(Efl_Loop_Data *pd) +{ + if (pd->throttle == 0) return + eina_evlog("+throttle", NULL, 0.0, NULL); + usleep(pd->throttle); + eina_evlog("-throttle", NULL, 0.0, NULL); +} + #ifdef HAVE_EPOLL static inline int -_ecore_get_epoll_fd(void) +_ecore_get_epoll_fd(Eo *obj, Efl_Loop_Data *pd) { - if (epoll_pid && (epoll_pid != getpid())) - { - /* forked! */ - _ecore_main_loop_shutdown(); - } - if ((epoll_pid == 0) && (epoll_fd < 0)) - { - _ecore_main_loop_init(); - } - return epoll_fd; + if (pd->epoll_pid && (pd->epoll_pid != getpid())) // forked! + _ecore_main_loop_clear(obj, pd); + if ((pd->epoll_pid == 0) && (pd->epoll_fd < 0)) + _ecore_main_loop_setup(obj, pd); + return pd->epoll_fd; } static inline int @@ -420,7 +297,7 @@ static inline int _ecore_poll_events_from_fdh(Ecore_Fd_Handler *fdh) { int events = 0; - if (fdh->flags & ECORE_FD_READ) events |= EPOLLIN; + if (fdh->flags & ECORE_FD_READ) events |= EPOLLIN; if (fdh->flags & ECORE_FD_WRITE) events |= EPOLLOUT; if (fdh->flags & ECORE_FD_ERROR) events |= EPOLLERR | EPOLLPRI; return events; @@ -432,7 +309,7 @@ static inline int _gfd_events_from_fdh(Ecore_Fd_Handler *fdh) { int events = 0; - if (fdh->flags & ECORE_FD_READ) events |= G_IO_IN; + if (fdh->flags & ECORE_FD_READ) events |= G_IO_IN; if (fdh->flags & ECORE_FD_WRITE) events |= G_IO_OUT; if (fdh->flags & ECORE_FD_ERROR) events |= G_IO_ERR; return events; @@ -441,42 +318,42 @@ _gfd_events_from_fdh(Ecore_Fd_Handler *fdh) #ifdef HAVE_LIBUV static void -_ecore_main_uv_poll_cb(uv_poll_t* handle, int status, int events) +_ecore_main_uv_poll_cb(uv_poll_t *handle, int status, int events) { - DBG("_ecore_main_uv_poll_cb %p status %d events %d", (void*)handle->data, status, events); - Ecore_Fd_Handler* fdh = handle->data; + Eo *obj = ML_OBJ; + Efl_Loop_Data *pd = ML_DAT; - if(_ecore_main_uv_idling) + DBG("_ecore_main_uv_poll_cb %p status %d events %d", + (void *)handle->data, status, events); + Ecore_Fd_Handler *fdh = handle->data; + + if (_ecore_main_uv_idling) { DBG("not IDLE anymore"); _ecore_main_uv_idling = EINA_FALSE; - _ecore_idle_exiter_call(_mainloop_singleton); + _ecore_idle_exiter_call(obj); _ecore_animator_run_reset(); } - - if (status) - fdh->error_active = EINA_TRUE; - if (events & UV_READABLE) - fdh->read_active = EINA_TRUE; - if (events & UV_WRITABLE) - fdh->write_active = EINA_TRUE; - _ecore_try_add_to_call_list(fdh); + if (status) fdh->error_active = EINA_TRUE; + if (events & UV_READABLE) fdh->read_active = EINA_TRUE; + if (events & UV_WRITABLE) fdh->write_active = EINA_TRUE; - _ecore_main_fd_handlers_call(); - if (fd_handlers_with_buffer) - _ecore_main_fd_handlers_buf_call(); - _ecore_signal_received_process(); - _ecore_event_call(); - _ecore_main_fd_handlers_cleanup(); - _efl_loop_timer_expired_timers_call(_ecore_time_loop_time); + _ecore_try_add_to_call_list(obj, pd, fdh); + + _ecore_main_fd_handlers_call(obj, pd); + if (pd->fd_handlers_with_buffer) _ecore_main_fd_handlers_buf_call(obj, pd); + _ecore_signal_received_process(obj, pd); + efl_loop_message_process(obj); + _ecore_main_fd_handlers_cleanup(obj, pd); + _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time); } static int _ecore_main_uv_events_from_fdh(Ecore_Fd_Handler *fdh) { int events = 0; - if (fdh->flags & ECORE_FD_READ) events |= UV_READABLE; + if (fdh->flags & ECORE_FD_READ) events |= UV_READABLE; if (fdh->flags & ECORE_FD_WRITE) events |= UV_WRITABLE; DBG("events is %d", (int)events); return events; @@ -484,50 +361,52 @@ _ecore_main_uv_events_from_fdh(Ecore_Fd_Handler *fdh) #endif static inline int -_ecore_main_fdh_poll_add(Ecore_Fd_Handler *fdh) +_ecore_main_fdh_poll_add(Efl_Loop_Data *pd EINA_UNUSED, Ecore_Fd_Handler *fdh) { DBG("_ecore_main_fdh_poll_add"); int r = 0; #ifdef HAVE_EPOLL -#ifdef HAVE_LIBUV - if(!_dl_uv_run) -#endif +# ifdef HAVE_LIBUV + if (!_dl_uv_run) +# endif { - if ((!fdh->file) && (epoll_fd >= 0)) - { - r = _ecore_epoll_add(_ecore_get_epoll_fd(), fdh->fd, - _ecore_poll_events_from_fdh(fdh), fdh); - } + if ((!fdh->file) && (pd->epoll_fd >= 0)) + r = _ecore_epoll_add(_ecore_get_epoll_fd(fdh->loop, pd), fdh->fd, + _ecore_poll_events_from_fdh(fdh), fdh); } -#ifdef HAVE_LIBUV +# ifdef HAVE_LIBUV else -#endif +# endif #endif { #ifdef HAVE_LIBUV - if(!fdh->file) - { - DBG("_ecore_main_fdh_poll_add libuv socket %p", fdh); - fdh->uv_handle.data = fdh; - DBG("_ecore_main_fdh_poll_add2 %p", fdh); - _dl_uv_poll_init_socket(_dl_uv_default_loop(), &fdh->uv_handle, fdh->fd); - DBG("_ecore_main_fdh_poll_add3 %p", fdh->uv_handle.data); - _dl_uv_poll_start(&fdh->uv_handle, _ecore_main_uv_events_from_fdh(fdh) - , _ecore_main_uv_poll_cb); - DBG("_ecore_main_fdh_poll_add libuv DONE"); - } - else - { - DBG("_ecore_main_fdh_poll_add libuv file"); - fdh->uv_handle.data = fdh; - DBG("_ecore_main_fdh_poll_add2 %p", fdh); - _dl_uv_poll_init(_dl_uv_default_loop(), &fdh->uv_handle, fdh->fd); - DBG("_ecore_main_fdh_poll_add3 %p", fdh->uv_handle.data); - _dl_uv_poll_start(&fdh->uv_handle, _ecore_main_uv_events_from_fdh(fdh) - , _ecore_main_uv_poll_cb); - DBG("_ecore_main_fdh_poll_add libuv DONE"); - } + if (!fdh->file) + { + DBG("_ecore_main_fdh_poll_add libuv socket %p", fdh); + fdh->uv_handle.data = fdh; + DBG("_ecore_main_fdh_poll_add2 %p", fdh); + _dl_uv_poll_init_socket(_dl_uv_default_loop(), + &fdh->uv_handle, fdh->fd); + DBG("_ecore_main_fdh_poll_add3 %p", fdh->uv_handle.data); + _dl_uv_poll_start(&fdh->uv_handle, + _ecore_main_uv_events_from_fdh(fdh) + , _ecore_main_uv_poll_cb); + DBG("_ecore_main_fdh_poll_add libuv DONE"); + } + else + { + DBG("_ecore_main_fdh_poll_add libuv file"); + fdh->uv_handle.data = fdh; + DBG("_ecore_main_fdh_poll_add2 %p", fdh); + _dl_uv_poll_init(_dl_uv_default_loop(), + &fdh->uv_handle, fdh->fd); + DBG("_ecore_main_fdh_poll_add3 %p", fdh->uv_handle.data); + _dl_uv_poll_start(&fdh->uv_handle, + _ecore_main_uv_events_from_fdh(fdh) + , _ecore_main_uv_poll_cb); + DBG("_ecore_main_fdh_poll_add libuv DONE"); + } #elif defined(USE_G_MAIN_LOOP) fdh->gfd.fd = fdh->fd; fdh->gfd.events = _gfd_events_from_fdh(fdh); @@ -540,47 +419,45 @@ _ecore_main_fdh_poll_add(Ecore_Fd_Handler *fdh) } static inline void -_ecore_main_fdh_poll_del(Ecore_Fd_Handler *fdh) +_ecore_main_fdh_poll_del(Efl_Loop_Data *pd, Ecore_Fd_Handler *fdh) { #ifdef HAVE_EPOLL -#ifdef HAVE_LIBUV - if(!_dl_uv_run) -#endif +# ifdef HAVE_LIBUV + if (!_dl_uv_run) +# endif { - if ((!fdh->file) && (epoll_fd >= 0)) - { - struct epoll_event ev; - int efd = _ecore_get_epoll_fd(); + if ((!fdh->file) && (pd->epoll_fd >= 0)) + { + struct epoll_event ev; + int efd = _ecore_get_epoll_fd(fdh->loop, pd); - memset(&ev, 0, sizeof (ev)); - DBG("removing poll on %d", fdh->fd); - /* could get an EBADF if somebody closed the FD before removing it */ - if ((epoll_ctl(efd, EPOLL_CTL_DEL, fdh->fd, &ev) < 0)) - { - if (errno == EBADF) - { - WRN("fd %d was closed, can't remove from epoll - reinit!", - fdh->fd); - _ecore_main_loop_shutdown(); - _ecore_main_loop_init(); - } - else - { - ERR("Failed to delete epoll fd %d! (errno=%d)", fdh->fd, errno); - } - } - } + memset(&ev, 0, sizeof (ev)); + DBG("removing poll on %d", fdh->fd); + // could get an EBADF if somebody closed the FD before removing + if ((epoll_ctl(efd, EPOLL_CTL_DEL, fdh->fd, &ev) < 0)) + { + if (errno == EBADF) + { + WRN("fd %d closed, can't remove from epoll - reinit!", + fdh->fd); + _ecore_main_loop_clear(fdh->loop, pd); + _ecore_main_loop_setup(fdh->loop, pd); + } + else ERR("Failed to delete epoll fd %d! (errno=%d)", + fdh->fd, errno); + } + } } -#ifdef HAVE_LIBUV +# ifdef HAVE_LIBUV else -#endif +# endif #endif { #ifdef HAVE_LIBUV - DBG("_ecore_main_fdh_poll_del libuv %p", fdh); - uv_handle_t* h = (uv_handle_t*)&fdh->uv_handle; - _dl_uv_close(h, 0); - DBG("_ecore_main_fdh_poll_del libuv DONE"); + DBG("_ecore_main_fdh_poll_del libuv %p", fdh); + uv_handle_t* h = (uv_handle_t*)&fdh->uv_handle; + _dl_uv_close(h, 0); + DBG("_ecore_main_fdh_poll_del libuv DONE"); #elif USE_G_MAIN_LOOP fdh->gfd.fd = fdh->fd; fdh->gfd.events = _gfd_events_from_fdh(fdh); @@ -592,35 +469,35 @@ _ecore_main_fdh_poll_del(Ecore_Fd_Handler *fdh) } static inline int -_ecore_main_fdh_poll_modify(Ecore_Fd_Handler *fdh) +_ecore_main_fdh_poll_modify(Efl_Loop_Data *pd EINA_UNUSED, Ecore_Fd_Handler *fdh) { DBG("_ecore_main_fdh_poll_modify %p", fdh); int r = 0; #ifdef HAVE_EPOLL -#ifdef HAVE_LIBUV - if(!_dl_uv_run) -#endif +# ifdef HAVE_LIBUV + if (!_dl_uv_run) +# endif { - if ((!fdh->file) && (epoll_fd >= 0)) - { - struct epoll_event ev; - int efd = _ecore_get_epoll_fd(); + if ((!fdh->file) && (pd->epoll_fd >= 0)) + { + struct epoll_event ev; + int efd = _ecore_get_epoll_fd(fdh->loop, pd); - memset(&ev, 0, sizeof (ev)); - ev.events = _ecore_poll_events_from_fdh(fdh); - ev.data.ptr = fdh; - DBG("modifing epoll on %d to %08x", fdh->fd, ev.events); - r = epoll_ctl(efd, EPOLL_CTL_MOD, fdh->fd, &ev); - } + memset(&ev, 0, sizeof (ev)); + ev.events = _ecore_poll_events_from_fdh(fdh); + ev.data.ptr = fdh; + DBG("modifing epoll on %d to %08x", fdh->fd, ev.events); + r = epoll_ctl(efd, EPOLL_CTL_MOD, fdh->fd, &ev); + } } -#ifdef HAVE_LIBUV +# ifdef HAVE_LIBUV else -#endif +# endif #endif { #ifdef HAVE_LIBUV - _dl_uv_poll_start(&fdh->uv_handle, _ecore_main_uv_events_from_fdh(fdh) - , _ecore_main_uv_poll_cb); + _dl_uv_poll_start(&fdh->uv_handle, _ecore_main_uv_events_from_fdh(fdh) + , _ecore_main_uv_poll_cb); #elif defined(USE_G_MAIN_LOOP) fdh->gfd.fd = fdh->fd; fdh->gfd.events = _gfd_events_from_fdh(fdh); @@ -633,12 +510,12 @@ _ecore_main_fdh_poll_modify(Ecore_Fd_Handler *fdh) #ifdef HAVE_EPOLL static inline int -_ecore_main_fdh_epoll_mark_active(void) +_ecore_main_fdh_epoll_mark_active(Eo *obj, Efl_Loop_Data *pd) { DBG("_ecore_main_fdh_epoll_mark_active"); struct epoll_event ev[32]; int i, ret; - int efd = _ecore_get_epoll_fd(); + int efd = _ecore_get_epoll_fd(obj, pd); memset(&ev, 0, sizeof (ev)); ret = epoll_wait(efd, ev, sizeof(ev) / sizeof(struct epoll_event), 0); @@ -666,42 +543,33 @@ _ecore_main_fdh_epoll_mark_active(void) continue; } - if (ev[i].events & EPOLLIN) - fdh->read_active = EINA_TRUE; - if (ev[i].events & EPOLLOUT) - fdh->write_active = EINA_TRUE; - if (ev[i].events & EPOLLERR) - fdh->error_active = EINA_TRUE; + if (ev[i].events & EPOLLIN) fdh->read_active = EINA_TRUE; + if (ev[i].events & EPOLLOUT) fdh->write_active = EINA_TRUE; + if (ev[i].events & EPOLLERR) fdh->error_active = EINA_TRUE; - _ecore_try_add_to_call_list(fdh); + _ecore_try_add_to_call_list(obj, pd, fdh); } - return ret; } #endif #ifdef USE_G_MAIN_LOOP - static inline int -_ecore_main_fdh_glib_mark_active(void) +_ecore_main_fdh_glib_mark_active(Eo *obj, Efl_Loop_Data *pd) { Ecore_Fd_Handler *fdh; int ret = 0; /* call the prepare callback for all handlers */ - EINA_INLIST_FOREACH(fd_handlers, fdh) + EINA_INLIST_FOREACH(pd->fd_handlers, fdh) { - if (fdh->delete_me) - continue; + if (fdh->delete_me) continue; - if (fdh->gfd.revents & G_IO_IN) - fdh->read_active = EINA_TRUE; - if (fdh->gfd.revents & G_IO_OUT) - fdh->write_active = EINA_TRUE; - if (fdh->gfd.revents & G_IO_ERR) - fdh->error_active = EINA_TRUE; + if (fdh->gfd.revents & G_IO_IN) fdh->read_active = EINA_TRUE; + if (fdh->gfd.revents & G_IO_OUT) fdh->write_active = EINA_TRUE; + if (fdh->gfd.revents & G_IO_ERR) fdh->error_active = EINA_TRUE; - _ecore_try_add_to_call_list(fdh); + _ecore_try_add_to_call_list(obj, fdh); if (fdh->gfd.revents & (G_IO_IN | G_IO_OUT | G_IO_ERR)) ret++; } @@ -714,159 +582,164 @@ static gboolean _ecore_main_gsource_prepare(GSource *source EINA_UNUSED, gint *next_time) { + Eo *obj = ML_OBJ; + Efl_Loop_Data *pd = ML_DAT; gboolean ready = FALSE; in_main_loop++; + pd->in_loop = in_main_loop; - if (!ecore_idling && !_ecore_glib_idle_enterer_called) + if ((!ecore_idling) && (!_ecore_glib_idle_enterer_called)) { - _ecore_time_loop_time = ecore_time_get(); - _efl_loop_timer_expired_timers_call(_ecore_time_loop_time); + pd->loop_time = _ecore_time_loop_time = ecore_time_get(); + _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time); - _ecore_idle_enterer_call(_mainloop_singleton); + _ecore_idle_enterer_call(obj); _ecore_throttle(); + _throttle_do(pd); _ecore_glib_idle_enterer_called = FALSE; - if (fd_handlers_with_buffer) - _ecore_main_fd_handlers_buf_call(); + if (pd->fd_handlers_with_buffer) + _ecore_main_fd_handlers_buf_call(obj, pd); } - _ecore_signal_received_process(); + _ecore_signal_received_process(obj, pd); - /* don't check fds if somebody quit */ + // don't check fds if somebody quit if (g_main_loop_is_running(ecore_main_loop)) { - /* only set idling state in dispatch */ - if (ecore_idling && !_ecore_idler_exist(_mainloop_singleton) && !_ecore_event_exist()) - { - if (_efl_loop_timers_exists()) - { - int r = -1; - double t = _efl_loop_timer_next_get(); + // only set idling state in dispatch + if (ecore_idling && (!_ecore_idler_exist(obj)) && + (!efl_loop_message_exists(obj))) + { + if (_efl_loop_timers_exists(obj, pd)) + { + int r = -1; + double t = _efl_loop_timer_next_get(obj, pd); - if ((timer_fd >= 0) && (t > 0.0)) - { - struct itimerspec ts; + if ((timer_fd >= 0) && (t > 0.0)) + { + struct itimerspec ts; - ts.it_interval.tv_sec = 0; - ts.it_interval.tv_nsec = 0; - ts.it_value.tv_sec = t; - ts.it_value.tv_nsec = fmod(t * NS_PER_SEC, NS_PER_SEC); + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 0; + ts.it_value.tv_sec = t; + ts.it_value.tv_nsec = fmod(t * NS_PER_SEC, NS_PER_SEC); - /* timerfd cannot sleep for 0 time */ - if (ts.it_value.tv_sec || ts.it_value.tv_nsec) - { - r = timerfd_settime(timer_fd, 0, &ts, NULL); - if (r < 0) - { - ERR("timer set returned %d (errno=%d)", r, errno); - close(timer_fd); - timer_fd = -1; - } - else - INF("sleeping for %ld s %06ldus", - ts.it_value.tv_sec, - ts.it_value.tv_nsec / 1000); - } - } - if (r == -1) - { - *next_time = ceil(t * 1000.0); - if (t == 0.0) - ready = TRUE; - } - } - else - *next_time = -1; - } - else - { - *next_time = 0; - if (_ecore_event_exist()) - ready = TRUE; - } + // timerfd cannot sleep for 0 time + if (ts.it_value.tv_sec || ts.it_value.tv_nsec) + { + r = timerfd_settime(timer_fd, 0, &ts, NULL); + if (r < 0) + { + ERR("timer set returned %d (errno=%d)", + r, errno); + close(timer_fd); + timer_fd = -1; + } + else INF("sleeping for %ld s %06ldus", + ts.it_value.tv_sec, + ts.it_value.tv_nsec / 1000); + } + } + if (r == -1) + { + *next_time = ceil(t * 1000.0); + if (t == 0.0) ready = TRUE; + } + } + else *next_time = -1; + } + else + { + *next_time = 0; + if (efl_loop_message_exists(obj)) ready = TRUE; + } - if (fd_handlers_with_prep) - _ecore_main_prepare_handlers(); + if (pd->fd_handlers_with_prep) _ecore_main_prepare_handlers(obj, pd); } - else - ready = TRUE; + else ready = TRUE; in_main_loop--; + pd->in_loop = in_main_loop; DBG("leave, timeout = %d", *next_time); - /* ready if we're not running (about to quit) */ + // ready if we're not running (about to quit) return ready; } static gboolean _ecore_main_gsource_check(GSource *source EINA_UNUSED) { + Eo *obj = ML_OBJ; + Efl_Loop_Data *pd = ML_DAT; gboolean ret = FALSE; in_main_loop++; - - /* check if old timers expired */ - if (ecore_idling && !_ecore_idler_exist(_mainloop_singleton) && !_ecore_event_exist()) + pd->in_loop = in_main_loop; + // check if old timers expired + if (ecore_idling && (!_ecore_idler_exist(obj)) && + (!efl_loop_message_exists(obj))) { if (timer_fd >= 0) { uint64_t count = 0; int r = read(timer_fd, &count, sizeof count); if ((r == -1) && (errno == EAGAIN)) - ; - else if (r == sizeof count) - ret = TRUE; + { + } + else if (r == sizeof count) ret = TRUE; else { - /* unexpected things happened... fail back to old way */ - ERR("timer read returned %d (errno=%d)", r, errno); - close(timer_fd); - timer_fd = -1; + // unexpected things happened... fail back to old way + ERR("timer read returned %d (errno=%d)", r, errno); + close(timer_fd); + timer_fd = -1; } } } - else - ret = TRUE; + else ret = TRUE; - /* check if fds are ready */ + // check if fds are ready #ifdef HAVE_EPOLL - if (epoll_fd >= 0) - ecore_fds_ready = (_ecore_main_fdh_epoll_mark_active() > 0); + if (pd->epoll_fd >= 0) + ecore_fds_ready = (_ecore_main_fdh_epoll_mark_active(obj, pd) > 0); else #endif - ecore_fds_ready = (_ecore_main_fdh_glib_mark_active() > 0); - _ecore_main_fd_handlers_cleanup(); - if (ecore_fds_ready) - ret = TRUE; + ecore_fds_ready = (_ecore_main_fdh_glib_mark_active(obj, pd) > 0); + _ecore_main_fd_handlers_cleanup(obj, pd); + if (ecore_fds_ready) ret = TRUE; - /* check timers after updating loop time */ - if (!ret && _efl_loop_timers_exists()) - ret = (0.0 == _efl_loop_timer_next_get()); + // check timers after updating loop time + if (!ret && _efl_loop_timers_exists(obj, pd)) + ret = (0.0 == _efl_loop_timer_next_get(obj, pd)); in_main_loop--; - + pd->in_loop = in_main_loop; return ret; } -/* like we just came out of main_loop_select in _ecore_main_select */ +// like we just came out of main_loop_select in _ecore_main_select static gboolean _ecore_main_gsource_dispatch(GSource *source EINA_UNUSED, GSourceFunc callback EINA_UNUSED, gpointer user_data EINA_UNUSED) { + Eo *obj = ML_OBJ; + Efl_Loop_Data *pd = ML_DAT; gboolean events_ready, timers_ready, idlers_ready; double next_time; - _ecore_time_loop_time = ecore_time_get(); - _efl_loop_timer_enable_new(); - next_time = _efl_loop_timer_next_get(); + pd->loop_time = ecore_time_get(); + _efl_loop_timer_enable_new(obj, pd); + next_time = _efl_loop_timer_next_get(obj, pd); - events_ready = _ecore_event_exist(); - timers_ready = _efl_loop_timers_exists() && (0.0 == next_time); - idlers_ready = _ecore_idler_exist(_mainloop_singleton); + events_ready = efl_loop_message_exists(obj); + timers_ready = _efl_loop_timers_exists(obj, pd) && (0.0 == next_time); + idlers_ready = _ecore_idler_exist(obj); in_main_loop++; + pd->in_loop = in_main_loop; DBG("enter idling=%d fds=%d events=%d timers=%d (next=%.2f) idlers=%d", ecore_idling, ecore_fds_ready, events_ready, timers_ready, next_time, idlers_ready); @@ -874,51 +747,50 @@ _ecore_main_gsource_dispatch(GSource *source EINA_UNUSED, if (ecore_idling && events_ready) { _ecore_animator_run_reset(); - _ecore_idle_exiter_call(_mainloop_singleton); + _ecore_idle_exiter_call(obj); ecore_idling = 0; } - else if (!ecore_idling && !events_ready) - { - ecore_idling = 1; - } + else if (!ecore_idling && !events_ready) ecore_idling = 1; if (ecore_idling) { - _ecore_idler_all_call(_mainloop_singleton); + _ecore_idler_all_call(obj); - events_ready = _ecore_event_exist(); + events_ready = efl_loop_message_exists(obj); if (ecore_fds_ready || events_ready || timers_ready) { _ecore_animator_run_reset(); - _ecore_idle_exiter_call(_mainloop_singleton); + _ecore_idle_exiter_call(obj); ecore_idling = 0; } } - /* process events */ + // process events if (!ecore_idling) { - _ecore_main_fd_handlers_call(); - if (fd_handlers_with_buffer) - _ecore_main_fd_handlers_buf_call(); - _ecore_signal_received_process(); - _ecore_event_call(); - _ecore_main_fd_handlers_cleanup(); + _ecore_main_fd_handlers_call(obj, pd); + if (pd->fd_handlers_with_buffer) + _ecore_main_fd_handlers_buf_call(obj, pd); + _ecore_signal_received_process(obj, pd); + efl_loop_message_process(obj); + _ecore_main_fd_handlers_cleanup(obj, pd); - _efl_loop_timer_expired_timers_call(_ecore_time_loop_time); + _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time); - _ecore_idle_enterer_call(_mainloop_singleton); + _ecore_idle_enterer_call(obj); _ecore_throttle(); + _throttle_do(pd); _ecore_glib_idle_enterer_called = TRUE; - if (fd_handlers_with_buffer) - _ecore_main_fd_handlers_buf_call(); + if (pd->fd_handlers_with_buffer) + _ecore_main_fd_handlers_buf_call(obj, pd); } in_main_loop--; + pd->in_loop = in_main_loop; - return TRUE; /* what should be returned here? */ + return TRUE; // what should be returned here? } static void @@ -928,366 +800,413 @@ _ecore_main_gsource_finalize(GSource *source EINA_UNUSED) static GSourceFuncs ecore_gsource_funcs = { - .prepare = _ecore_main_gsource_prepare, - .check = _ecore_main_gsource_check, + .prepare = _ecore_main_gsource_prepare, + .check = _ecore_main_gsource_check, .dispatch = _ecore_main_gsource_dispatch, .finalize = _ecore_main_gsource_finalize, }; - #endif -#ifdef HAVE_SYS_TIMERFD_H -static int realtime_fd = -1; - -static void detect_time_changes_start(void); -static Eina_Bool -_realtime_update(void *data EINA_UNUSED, Ecore_Fd_Handler *fdh EINA_UNUSED) -{ - char buf[64]; - - if (read(realtime_fd, buf, sizeof(buf)) >= 0) return EINA_TRUE; - - DBG("system clock changed"); - ecore_event_add(ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED, NULL, NULL, NULL); - - close(realtime_fd); - realtime_fd = -1; - detect_time_changes_start(); - return EINA_FALSE; -} -#endif - -static void -detect_time_changes_start(void) -{ -#ifdef HAVE_SYS_TIMERFD_H - struct itimerspec its; - - if (realtime_fd >= 0) return; - - realtime_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC); - if (realtime_fd < 0) return; - - memset(&its, 0, sizeof(its)); - its.it_value.tv_sec = 0x7ffffff0; // end of time - 0xf - if (timerfd_settime(realtime_fd, - TFD_TIMER_ABSTIME | TFD_TIMER_CANCELON_SET, - &its, NULL) < 0) - { - WRN("Couldn't arm timerfd to detect clock changes: %s", - strerror(errno)); - close(realtime_fd); - realtime_fd = -1; - return; - } - - ecore_main_fd_handler_add(realtime_fd, ECORE_FD_READ, - _realtime_update, NULL, NULL, NULL); -#endif -} - -static void -detect_time_changes_stop(void) -{ -#ifdef HAVE_SYS_TIMERFD_H - if (realtime_fd > 0) - { - close(realtime_fd); - realtime_fd = -1; - } -#endif -} - - #ifdef HAVE_LIBUV -static inline -void -_ecore_main_loop_uv_check(uv_check_t* handle EINA_UNUSED); -static void _ecore_main_loop_uv_prepare(uv_prepare_t* handle); +static inline void _ecore_main_loop_uv_check(uv_check_t *handle); +static void _ecore_main_loop_uv_prepare(uv_prepare_t *handle); -static -void _ecore_main_loop_timer_run(uv_timer_t* timer EINA_UNUSED) +static void +_ecore_main_loop_timer_run(uv_timer_t *timer EINA_UNUSED) { - if(_ecore_main_uv_idling) - { - _ecore_main_uv_idling = EINA_FALSE; - _ecore_idle_exiter_call(_mainloop_singleton); - _ecore_animator_run_reset(); - } - _ecore_time_loop_time = ecore_time_get(); - _ecore_main_loop_uv_check(NULL); - - _ecore_main_loop_uv_prepare(NULL); + Eo *obj = ML_OBJ; + Efl_Loop_Data *pd = ML_DAT; + + if (_ecore_main_uv_idling) + { + _ecore_main_uv_idling = EINA_FALSE; + _ecore_idle_exiter_call(obj); + _ecore_animator_run_reset(); + } + pd->loop_time = ecore_time_get(); + _ecore_main_loop_uv_check(NULL); + _ecore_main_loop_uv_prepare(NULL); } -static void _ecore_main_loop_uv_prepare(uv_prepare_t* handle); -static inline -void -_ecore_main_loop_uv_check(uv_check_t* handle EINA_UNUSED) +static inline void +_ecore_main_loop_uv_check(uv_check_t *handle EINA_UNUSED) { + Eo *obj = ML_OBJ; + Efl_Loop_Data *pd = ML_DAT; + DBG("_ecore_main_loop_uv_check idling? %d", (int)_ecore_main_uv_idling); in_main_loop++; + pd->in_loop = in_main_loop; - if(do_quit) - goto quit; + if (pd->do_quit) goto quit; do { - _ecore_main_fd_handlers_call(); - if (fd_handlers_with_buffer) - _ecore_main_fd_handlers_buf_call(); - _ecore_signal_received_process(); - _ecore_event_call(); - _ecore_main_fd_handlers_cleanup(); - _efl_loop_timer_expired_timers_call(_ecore_time_loop_time); + _ecore_main_fd_handlers_call(obj, pd); + if (pd->fd_handlers_with_buffer) + _ecore_main_fd_handlers_buf_call(obj, pd); + _ecore_signal_received_process(obj, pd); + efl_loop_message_process(obj); + _ecore_main_fd_handlers_cleanup(obj, pd); + _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time); } - while(fd_handlers_to_call); + while (pd->fd_handlers_to_call); quit: in_main_loop--; + pd->in_loop = in_main_loop; } #endif +static void +_ecore_main_loop_setup(Eo *obj, Efl_Loop_Data *pd) +{ + // Please note that this function is being also called in case of a bad + // fd to reset the main loop. +#ifdef HAVE_EPOLL + pd->epoll_fd = epoll_create(1); + if (pd->epoll_fd < 0) WRN("Failed to create epoll fd!"); + else + { + eina_file_close_on_exec(pd->epoll_fd, EINA_TRUE); + + pd->epoll_pid = getpid(); + + /* add polls on all our file descriptors */ + Ecore_Fd_Handler *fdh; + EINA_INLIST_FOREACH(pd->fd_handlers, fdh) + { + if (fdh->delete_me) continue; + _ecore_epoll_add(pd->epoll_fd, fdh->fd, + _ecore_poll_events_from_fdh(fdh), fdh); + _ecore_main_fdh_poll_add(pd, fdh); + } + } +#endif + + if (obj == ML_OBJ) + { +#ifdef HAVE_LIBUV + // XXX: FIXME: the below uv init should not assert but gracefully + // fail with errors + DBG("loading lib uv"); +# ifdef HAVE_NODEJS + void *lib = dlopen(NULL, RTLD_LAZY); +# else + void *lib = dlopen("libuv.so.1", RTLD_GLOBAL | RTLD_LAZY); +# endif + + if (lib && dlsym(lib, "uv_run")) + { + DBG("loaded lib uv"); + _dl_uv_run = dlsym(lib, "uv_run"); + assert(!!_dl_uv_run); + _dl_uv_stop = dlsym(lib, "uv_stop"); + assert(!!_dl_uv_stop); + _dl_uv_default_loop = dlsym(lib, "uv_default_loop"); + assert(!!_dl_uv_default_loop); + _dl_uv_poll_init_socket = dlsym(lib, "uv_poll_init_socket"); + assert(!!_dl_uv_poll_init_socket); + _dl_uv_poll_init = dlsym(lib, "uv_poll_init"); + assert(!!_dl_uv_poll_init); + _dl_uv_poll_start = dlsym(lib, "uv_poll_start"); + assert(!!_dl_uv_poll_start); + _dl_uv_poll_stop = dlsym(lib, "uv_poll_stop"); + assert(!!_dl_uv_poll_stop); + _dl_uv_timer_init = dlsym(lib, "uv_timer_init"); + assert(!!_dl_uv_timer_init); + _dl_uv_timer_start = dlsym(lib, "uv_timer_start"); + assert(!!_dl_uv_timer_start); + _dl_uv_timer_stop = dlsym(lib, "uv_timer_stop"); + assert(!!_dl_uv_timer_stop); + _dl_uv_prepare_init = dlsym(lib, "uv_prepare_init"); + assert(!!_dl_uv_prepare_init); + _dl_uv_prepare_start = dlsym(lib, "uv_prepare_start"); + assert(!!_dl_uv_prepare_start); + _dl_uv_prepare_stop = dlsym(lib, "uv_prepare_stop"); + assert(!!_dl_uv_prepare_stop); + _dl_uv_check_init = dlsym(lib, "uv_check_init"); + assert(!!_dl_uv_check_init); + _dl_uv_check_start = dlsym(lib, "uv_check_start"); + assert(!!_dl_uv_check_start); + _dl_uv_check_stop = dlsym(lib, "uv_check_stop"); + assert(!!_dl_uv_check_stop); + _dl_uv_close = dlsym(lib, "uv_close"); + assert(!!_dl_uv_close); + _dl_uv_loop_alive = dlsym(lib, "uv_loop_alive"); + assert(!!_dl_uv_loop_alive); + + //dlclose(lib); + + DBG("_dl_uv_prepare_init"); + _dl_uv_prepare_init(_dl_uv_default_loop(), &_ecore_main_uv_prepare); + DBG("_dl_uv_prepare_start"); + _dl_uv_prepare_start(&_ecore_main_uv_prepare, &_ecore_main_loop_uv_prepare); + DBG("_dl_uv_prepare_started"); + + DBG("_dl_uv_check_init"); + _dl_uv_check_init(_dl_uv_default_loop(), &_ecore_main_uv_check); + DBG("_dl_uv_check_start"); + _dl_uv_check_start(&_ecore_main_uv_check, &_ecore_main_loop_uv_check); + DBG("_dl_uv_check_started"); + + _dl_uv_timer_init(_dl_uv_default_loop(), &_ecore_main_uv_handle_timers); + } + // else + // DBG("did not load uv"); + DBG("loaded dlsyms uv"); +#endif + + // setup for the g_main_loop only integration +#ifdef USE_G_MAIN_LOOP + ecore_glib_source = g_source_new(&ecore_gsource_funcs, + sizeof(GSource)); + if (!ecore_glib_source) CRI("Failed to create glib source for epoll!"); + else + { + g_source_set_priority(ecore_glib_source, + G_PRIORITY_HIGH_IDLE + 20); +# ifdef HAVE_EPOLL + if (pd->epoll_fd >= 0) + { + // epoll multiplexes fds into the g_main_loop + ecore_epoll_fd.fd = pd->epoll_fd; + ecore_epoll_fd.events = G_IO_IN; + ecore_epoll_fd.revents = 0; + g_source_add_poll(ecore_glib_source, &ecore_epoll_fd); + } +# endif + // timerfd gives us better than millisecond accuracy + pd->timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); + if (pd->timer_fd < 0) WRN("failed to create timer fd!"); + else + { + eina_file_close_on_exec(pd->timer_fd, EINA_TRUE); + ecore_timer_fd.fd = pd->timer_fd; + ecore_timer_fd.events = G_IO_IN; + ecore_timer_fd.revents = 0; + g_source_add_poll(ecore_glib_source, &ecore_timer_fd); + } + + ecore_glib_source_id = g_source_attach(ecore_glib_source, NULL); + if (ecore_glib_source_id <= 0) + CRI("Failed to attach glib source to default context"); + } +#endif + } + _ecore_main_timechanges_start(obj); +} + +static void +_ecore_main_loop_clear(Eo *obj, Efl_Loop_Data *pd) +{ + if (!pd) return; + // Please note that _ecore_main_loop_shutdown is called in cycle to + // restart the main loop in case of a bad fd + if (obj == ML_OBJ) + { + _ecore_main_timechanges_stop(obj); +#ifdef USE_G_MAIN_LOOP + if (ecore_glib_source) + { + g_source_destroy(ecore_glib_source); + ecore_glib_source = NULL; + } +#endif +#ifdef HAVE_LIBUV + if (_dl_uv_run) + { + DBG("_ecore_main_loop_shutdown"); + _dl_uv_timer_stop(&_ecore_main_uv_handle_timers); + _dl_uv_close((uv_handle_t*)&_ecore_main_uv_handle_timers, 0); + } +#endif + } +#ifdef HAVE_EPOLL + if (pd->epoll_fd >= 0) + { + close(pd->epoll_fd); + pd->epoll_fd = -1; + } + if (pd->timer_fd >= 0) + { + close(pd->timer_fd); + pd->timer_fd = -1; + } +#endif +} + void _ecore_main_loop_init(void) { - // Please note that this function is being also called in case of a bad fd to reset the main loop. - DBG("_ecore_main_loop_init"); -#ifdef HAVE_EPOLL - epoll_fd = epoll_create(1); - if (epoll_fd < 0) - WRN("Failed to create epoll fd!"); - else - { - eina_file_close_on_exec(epoll_fd, EINA_TRUE); - - epoll_pid = getpid(); - - /* add polls on all our file descriptors */ - Ecore_Fd_Handler *fdh; - EINA_INLIST_FOREACH(fd_handlers, fdh) - { - if (fdh->delete_me) continue; - _ecore_epoll_add(epoll_fd, fdh->fd, - _ecore_poll_events_from_fdh(fdh), fdh); - _ecore_main_fdh_poll_add(fdh); - } - } -#endif - -#ifdef HAVE_LIBUV - { - DBG("loading lib uv"); -#ifdef HAVE_NODEJS - void* lib = dlopen(NULL, RTLD_LAZY); -#else - void* lib = dlopen("libuv.so", RTLD_GLOBAL | RTLD_LAZY); -#endif - - if(lib && dlsym(lib, "uv_run")) - { - DBG("loaded lib uv"); - _dl_uv_run = dlsym(lib, "uv_run"); - assert(!!_dl_uv_run); - _dl_uv_stop = dlsym(lib, "uv_stop"); - assert(!!_dl_uv_stop); - _dl_uv_default_loop = dlsym(lib, "uv_default_loop"); - assert(!!_dl_uv_default_loop); - _dl_uv_poll_init_socket = dlsym(lib, "uv_poll_init_socket"); - assert(!!_dl_uv_poll_init_socket); - _dl_uv_poll_init = dlsym(lib, "uv_poll_init"); - assert(!!_dl_uv_poll_init); - _dl_uv_poll_start = dlsym(lib, "uv_poll_start"); - assert(!!_dl_uv_poll_start); - _dl_uv_poll_stop = dlsym(lib, "uv_poll_stop"); - assert(!!_dl_uv_poll_stop); - _dl_uv_timer_init = dlsym(lib, "uv_timer_init"); - assert(!!_dl_uv_timer_init); - _dl_uv_timer_start = dlsym(lib, "uv_timer_start"); - assert(!!_dl_uv_timer_start); - _dl_uv_timer_stop = dlsym(lib, "uv_timer_stop"); - assert(!!_dl_uv_timer_stop); - _dl_uv_prepare_init = dlsym(lib, "uv_prepare_init"); - assert(!!_dl_uv_prepare_init); - _dl_uv_prepare_start = dlsym(lib, "uv_prepare_start"); - assert(!!_dl_uv_prepare_start); - _dl_uv_prepare_stop = dlsym(lib, "uv_prepare_stop"); - assert(!!_dl_uv_prepare_stop); - _dl_uv_check_init = dlsym(lib, "uv_check_init"); - assert(!!_dl_uv_check_init); - _dl_uv_check_start = dlsym(lib, "uv_check_start"); - assert(!!_dl_uv_check_start); - _dl_uv_check_stop = dlsym(lib, "uv_check_stop"); - assert(!!_dl_uv_check_stop); - _dl_uv_close = dlsym(lib, "uv_close"); - assert(!!_dl_uv_close); - _dl_uv_loop_alive = dlsym(lib, "uv_loop_alive"); - assert(!!_dl_uv_loop_alive); - - //dlclose(lib); - - DBG("_dl_uv_prepare_init"); - _dl_uv_prepare_init(_dl_uv_default_loop(), &_ecore_main_uv_prepare); - DBG("_dl_uv_prepare_start"); - _dl_uv_prepare_start(&_ecore_main_uv_prepare, &_ecore_main_loop_uv_prepare); - DBG("_dl_uv_prepare_started"); - - DBG("_dl_uv_check_init"); - _dl_uv_check_init(_dl_uv_default_loop(), &_ecore_main_uv_check); - DBG("_dl_uv_check_start"); - _dl_uv_check_start(&_ecore_main_uv_check, &_ecore_main_loop_uv_check); - DBG("_dl_uv_check_started"); - - _dl_uv_timer_init(_dl_uv_default_loop(), &_ecore_main_uv_handle_timers); - } - /* else */ - /* DBG("did not load uv"); */ - DBG("loaded dlsyms uv"); - } -#endif - - /* setup for the g_main_loop only integration */ -#ifdef USE_G_MAIN_LOOP - ecore_glib_source = g_source_new(&ecore_gsource_funcs, sizeof (GSource)); - if (!ecore_glib_source) - CRI("Failed to create glib source for epoll!"); - else - { - g_source_set_priority(ecore_glib_source, G_PRIORITY_HIGH_IDLE + 20); -#ifdef HAVE_EPOLL - if (epoll_fd >= 0) - { - /* epoll multiplexes fds into the g_main_loop */ - ecore_epoll_fd.fd = epoll_fd; - ecore_epoll_fd.events = G_IO_IN; - ecore_epoll_fd.revents = 0; - g_source_add_poll(ecore_glib_source, &ecore_epoll_fd); - } -#endif - /* timerfd gives us better than millisecond accuracy in g_main_loop */ - timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); - if (timer_fd < 0) - WRN("failed to create timer fd!"); - else - { - eina_file_close_on_exec(timer_fd, EINA_TRUE); - ecore_timer_fd.fd = timer_fd; - ecore_timer_fd.events = G_IO_IN; - ecore_timer_fd.revents = 0; - g_source_add_poll(ecore_glib_source, &ecore_timer_fd); - } - - ecore_glib_source_id = g_source_attach(ecore_glib_source, NULL); - if (ecore_glib_source_id <= 0) - CRI("Failed to attach glib source to default context"); - } -#endif - - detect_time_changes_start(); + if (!ecore_main_loop_get()) ERR("Cannot create main loop object"); + _ecore_main_loop_setup(ML_OBJ, ML_DAT); } void _ecore_main_loop_shutdown(void) { - // Please note that _ecore_main_loop_shutdown is called in cycle to restart the main loop in case of a bad fd - -#ifdef USE_G_MAIN_LOOP - if (ecore_glib_source) - { - g_source_destroy(ecore_glib_source); - ecore_glib_source = NULL; - } -#endif - - detect_time_changes_stop(); - -#ifdef HAVE_EPOLL - if (epoll_fd >= 0) - { - close(epoll_fd); - epoll_fd = -1; - } - epoll_pid = 0; -#endif - - if (timer_fd >= 0) - { - close(timer_fd); - timer_fd = -1; - } - -#ifdef HAVE_LIBUV - if(_dl_uv_run) - { - DBG("_ecore_main_loop_shutdown"); - _dl_uv_timer_stop(&_ecore_main_uv_handle_timers); - _dl_uv_close((uv_handle_t*)&_ecore_main_uv_handle_timers, 0); - } -#endif + if (!ML_OBJ) return; + _ecore_main_loop_clear(ML_OBJ, ML_DAT); +// XXX: this seemingly closes fd's it shouldn't.... :( fd 0? +// efl_del(ML_OBJ); + ML_OBJ = NULL; + ML_DAT = NULL; } -void * -_ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler) +void +_ecore_main_loop_iterate(Eo *obj, Efl_Loop_Data *pd) { - DBG("_ecore_main_fd_handler_del %p", fd_handler); - if (fd_handler->delete_me) + if (obj == ML_OBJ) { - ERR("fdh %p deleted twice", fd_handler); - return NULL; +#ifdef HAVE_LIBUV + if (!_dl_uv_run) + { +#endif +#ifndef USE_G_MAIN_LOOP + pd->loop_time = ecore_time_get(); + _ecore_main_loop_iterate_internal(obj, pd, 1); +#else + g_main_context_iteration(NULL, 0); +#endif +#ifdef HAVE_LIBUV + } + else + _dl_uv_run(_dl_uv_default_loop(), UV_RUN_ONCE | UV_RUN_NOWAIT); +#endif } + else + { + pd->loop_time = ecore_time_get(); + _ecore_main_loop_iterate_internal(obj, pd, 1); + } +} - fd_handler->delete_me = EINA_TRUE; - _ecore_main_fdh_poll_del(fd_handler); - fd_handlers_to_delete = eina_list_append(fd_handlers_to_delete, fd_handler); - if (fd_handler->prep_func && fd_handlers_with_prep) - 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; +int +_ecore_main_loop_iterate_may_block(Eo *obj, Efl_Loop_Data *pd, int may_block) +{ + if (obj == ML_OBJ) + { +#ifdef HAVE_LIBUV + if (!_dl_uv_run) + { +#endif +#ifndef USE_G_MAIN_LOOP + in_main_loop++; + pd->in_loop = in_main_loop; + pd->loop_time = ecore_time_get(); + _ecore_main_loop_iterate_internal(obj, pd, !may_block); + in_main_loop--; + pd->in_loop = in_main_loop; + return efl_loop_message_exists(obj); +#else + return g_main_context_iteration(NULL, may_block); +#endif +#ifdef HAVE_LIBUV + } + else + _dl_uv_run(_dl_uv_default_loop(), + may_block ? (UV_RUN_ONCE | UV_RUN_NOWAIT) : UV_RUN_ONCE); +#endif + } + else + { + pd->in_loop++; + pd->loop_time = ecore_time_get(); + _ecore_main_loop_iterate_internal(obj, pd, !may_block); + pd->in_loop--; + return efl_loop_message_exists(obj); + } + return 0; +} + +void +_ecore_main_loop_begin(Eo *obj, Efl_Loop_Data *pd) +{ + if (obj == ML_OBJ) + { + if (pd->in_loop > 0) + { + ERR("Beginning main loop() inside an existing main loop"); + return; + } +#ifdef HAVE_SYSTEMD + sd_notify(0, "READY=1"); +#endif +#ifdef HAVE_LIBUV + if (!_dl_uv_run) + { +#endif +#ifndef USE_G_MAIN_LOOP + in_main_loop++; + pd->in_loop = in_main_loop; + pd->loop_time = ecore_time_get(); + while (!pd->do_quit) + _ecore_main_loop_iterate_internal(obj, pd, 0); + pd->do_quit = 0; + in_main_loop--; + pd->in_loop = in_main_loop; +#else + if (!pd->do_quit) + { + if (!ecore_main_loop) + ecore_main_loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(ecore_main_loop); + } + pd->do_quit = 0; +#endif +#ifdef HAVE_LIBUV + } + else + { + DBG("uv_run"); + in_main_loop++; + pd->in_loop = in_main_loop; + pd->loop_time = ecore_time_get(); + while (!pd->do_quit) + _dl_uv_run(_dl_uv_default_loop(), UV_RUN_DEFAULT); + in_main_loop--; + pd->in_loop = in_main_loop; + pd->do_quit = 0; + DBG("quit"); + } +#endif + } + else + { + pd->in_loop++; + pd->loop_time = ecore_time_get(); + while (!pd->do_quit) + _ecore_main_loop_iterate_internal(obj, pd, 0); + pd->do_quit = 0; + pd->in_loop--; + } +} + +void +_ecore_main_loop_quit(Eo *obj, Efl_Loop_Data *pd) +{ + pd->do_quit = 1; + if (obj != ML_OBJ) return; +#ifdef USE_G_MAIN_LOOP + if (ecore_main_loop) g_main_loop_quit(ecore_main_loop); +#elif defined(HAVE_LIBUV) + if (_dl_uv_run) _dl_uv_stop(_dl_uv_default_loop()); +#endif } EAPI void ecore_main_loop_iterate(void) { EINA_MAIN_LOOP_CHECK_RETURN; -#ifdef HAVE_LIBUV - if(!_dl_uv_run) { -#endif -#ifndef USE_G_MAIN_LOOP - _ecore_time_loop_time = ecore_time_get(); - _ecore_main_loop_iterate_internal(1); -#else - g_main_context_iteration(NULL, 0); -#endif -#ifdef HAVE_LIBUV - } - else - _dl_uv_run(_dl_uv_default_loop(), UV_RUN_ONCE | UV_RUN_NOWAIT); -#endif + efl_loop_iterate(ML_OBJ); } EAPI int ecore_main_loop_iterate_may_block(int may_block) { EINA_MAIN_LOOP_CHECK_RETURN_VAL(0); -#ifdef HAVE_LIBUV - if(!_dl_uv_run) { -#endif -#ifndef USE_G_MAIN_LOOP - _ecore_time_loop_time = ecore_time_get(); -in_main_loop++; - _ecore_main_loop_iterate_internal(!may_block); -in_main_loop--; - return _ecore_event_exist(); -#else - return g_main_context_iteration(NULL, may_block); -#endif -#ifdef HAVE_LIBUV - } - else - _dl_uv_run(_dl_uv_default_loop(), may_block ? UV_RUN_ONCE | UV_RUN_NOWAIT : UV_RUN_ONCE); -#endif - return 0; + return efl_loop_iterate_may_block(ML_OBJ, may_block); } EAPI void @@ -1295,65 +1214,24 @@ ecore_main_loop_begin(void) { DBG("ecore_main_loop_begin"); EINA_MAIN_LOOP_CHECK_RETURN; - if (in_main_loop > 0) - { - ERR("Running ecore_main_loop_begin() inside an existing main loop"); - return; - } eina_evlog("+mainloop", NULL, 0.0, NULL); -#ifdef HAVE_SYSTEMD - sd_notify(0, "READY=1"); -#endif -#ifdef HAVE_LIBUV - if(!_dl_uv_run) { -#endif -#ifndef USE_G_MAIN_LOOP - in_main_loop++; - _ecore_time_loop_time = ecore_time_get(); - while (do_quit == 0) _ecore_main_loop_iterate_internal(0); - do_quit = 0; - in_main_loop--; -#else - if (!do_quit) - { - if (!ecore_main_loop) - ecore_main_loop = g_main_loop_new(NULL, FALSE); - g_main_loop_run(ecore_main_loop); - } - do_quit = 0; -#endif -#ifdef HAVE_LIBUV - } - else - { - DBG("uv_run"); - _ecore_time_loop_time = ecore_time_get(); - in_main_loop++; - while(!do_quit) - _dl_uv_run(_dl_uv_default_loop(), UV_RUN_DEFAULT); - in_main_loop--; - do_quit = 0; - DBG("quit"); - } -#endif + efl_loop_begin(ML_OBJ); eina_evlog("-mainloop", NULL, 0.0, NULL); } EAPI void ecore_main_loop_quit(void) { + Eina_Value v = EINA_VALUE_EMPTY; + int val = 0; + + eina_value_setup(&v, EINA_VALUE_TYPE_INT); + eina_value_set(&v, &val); EINA_MAIN_LOOP_CHECK_RETURN; - do_quit = 1; -#ifdef USE_G_MAIN_LOOP - if (ecore_main_loop) - g_main_loop_quit(ecore_main_loop); -#elif defined(HAVE_LIBUV) - if (_dl_uv_run) - _dl_uv_stop(_dl_uv_default_loop()); -#endif + efl_loop_quit(ML_OBJ, v); } -EAPI int +EAPI int ecore_main_loop_nested_get(void) { return in_main_loop; @@ -1381,7 +1259,10 @@ ecore_main_loop_select_func_get(void) } Ecore_Fd_Handler * -_ecore_main_fd_handler_add(int fd, +_ecore_main_fd_handler_add(Eo *obj, + Efl_Loop_Data *pd, + Eo *handler, + int fd, Ecore_Fd_Handler_Flags flags, Ecore_Fd_Cb func, const void *data, @@ -1397,36 +1278,63 @@ _ecore_main_fd_handler_add(int fd, fdh = ecore_fd_handler_calloc(1); if (!fdh) return NULL; ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER); - fdh->next_ready = NULL; + fdh->loop = obj; + fdh->loop_data = pd; + fdh->handler = handler; fdh->fd = fd; fdh->flags = flags; fdh->file = is_file; - if (_ecore_main_fdh_poll_add(fdh) < 0) + if (_ecore_main_fdh_poll_add(pd, fdh) < 0) { int err = errno; - ERR("Failed to add poll on fd %d (errno = %d: %s)!", fd, err, strerror(err)); + ERR("Failed to add poll on fd %d (errno = %d: %s)!", + fd, err, strerror(err)); ecore_fd_handler_mp_free(fdh); return NULL; } - fdh->read_active = EINA_FALSE; - fdh->write_active = EINA_FALSE; - fdh->error_active = EINA_FALSE; - fdh->delete_me = EINA_FALSE; fdh->func = func; fdh->data = (void *)data; fdh->buf_func = buf_func; if (buf_func) - fd_handlers_with_buffer = eina_list_append(fd_handlers_with_buffer, fdh); + pd->fd_handlers_with_buffer = eina_list_append + (pd->fd_handlers_with_buffer, fdh); fdh->buf_data = (void *)buf_data; if (is_file) - file_fd_handlers = eina_list_append(file_fd_handlers, fdh); - fd_handlers = (Ecore_Fd_Handler *) - eina_inlist_append(EINA_INLIST_GET(fd_handlers), + pd->file_fd_handlers = eina_list_append + (pd->file_fd_handlers, fdh); + pd->fd_handlers = (Ecore_Fd_Handler *) + eina_inlist_append(EINA_INLIST_GET(pd->fd_handlers), EINA_INLIST_GET(fdh)); return fdh; } +void * +_ecore_main_fd_handler_del(Eo *obj EINA_UNUSED, + Efl_Loop_Data *pd, + Ecore_Fd_Handler *fd_handler) +{ + DBG("_ecore_main_fd_handler_del %p", fd_handler); + if (fd_handler->delete_me) + { + ERR("fdh %p deleted twice", fd_handler); + return NULL; + } + + fd_handler->handler = NULL; + fd_handler->delete_me = EINA_TRUE; + _ecore_main_fdh_poll_del(pd, fd_handler); + pd->fd_handlers_to_delete = eina_list_append + (pd->fd_handlers_to_delete, fd_handler); + if (fd_handler->prep_func && pd->fd_handlers_with_prep) + pd->fd_handlers_with_prep = eina_list_remove + (pd->fd_handlers_with_prep, fd_handler); + if (fd_handler->buf_func && pd->fd_handlers_with_buffer) + pd->fd_handlers_with_buffer = eina_list_remove + (pd->fd_handlers_with_buffer, fd_handler); + return fd_handler->data; +} + EAPI Ecore_Fd_Handler * ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, @@ -1437,7 +1345,9 @@ ecore_main_fd_handler_add(int fd, { Ecore_Fd_Handler *fdh = NULL; EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - fdh = _ecore_main_fd_handler_add(fd, flags, func, data, buf_func, buf_data, EINA_FALSE); + fdh = _ecore_main_fd_handler_add(efl_loop_main_get(EFL_LOOP_CLASS), + ML_DAT, NULL, fd, flags, func, data, + buf_func, buf_data, EINA_FALSE); return fdh; } @@ -1450,44 +1360,11 @@ ecore_main_fd_handler_file_add(int fd, const void *buf_data) { EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - return _ecore_main_fd_handler_add(fd, flags, func, data, buf_func, buf_data, EINA_TRUE); + return _ecore_main_fd_handler_add(efl_loop_main_get(EFL_LOOP_CLASS), + ML_DAT, NULL, fd, flags, func, data, + buf_func, buf_data, EINA_TRUE); } -#ifdef _WIN32 -EAPI Ecore_Win32_Handler * -ecore_main_win32_handler_add(void *h, - Ecore_Win32_Handle_Cb func, - const void *data) -{ - Ecore_Win32_Handler *wh; - - EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); - if (!h || !func) return NULL; - - wh = ecore_win32_handler_calloc(1); - if (!wh) return NULL; - ECORE_MAGIC_SET(wh, ECORE_MAGIC_WIN32_HANDLER); - wh->h = (HANDLE)h; - wh->delete_me = EINA_FALSE; - wh->func = func; - wh->data = (void *)data; - win32_handlers = (Ecore_Win32_Handler *) - eina_inlist_append(EINA_INLIST_GET(win32_handlers), - EINA_INLIST_GET(wh)); - return wh; -} - -#else -EAPI Ecore_Win32_Handler * -ecore_main_win32_handler_add(void *h EINA_UNUSED, - Ecore_Win32_Handle_Cb func EINA_UNUSED, - const void *data EINA_UNUSED) -{ - return NULL; -} - -#endif - EAPI void * ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler) { @@ -1500,12 +1377,40 @@ ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler) "ecore_main_fd_handler_del"); return NULL; } - return _ecore_main_fd_handler_del(fd_handler); + return _ecore_main_fd_handler_del(ML_OBJ, ML_DAT, fd_handler); } #ifdef _WIN32 -static void * -_ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler) +EAPI Ecore_Win32_Handler * +_ecore_main_win32_handler_add(Eo *obj, + Efl_Loop_Data *pd, + Eo *handler, + void *h, + Ecore_Win32_Handle_Cb func, + const void *data) +{ + Efl_Loop_Data *pd = ML_DAT; + Ecore_Win32_Handler *wh; + + EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); + if (!h || !func) return NULL; + + wh = ecore_win32_handler_calloc(1); + if (!wh) return NULL; + ECORE_MAGIC_SET(wh, ECORE_MAGIC_WIN32_HANDLER); + wh->loop = obj; + wh->loop_data = pd; + wh->h = (HANDLE)h; + wh->func = func; + wh->data = (void *)data; + pd->win32_handlers = (Ecore_Win32_Handler *) + eina_inlist_append(EINA_INLIST_GET(pd->win32_handlers), + EINA_INLIST_GET(wh)); + return wh; +} + +void * +_ecore_main_win32_handler_del(Eo *obj, Efl_Loop_Data *pd, Ecore_Win32_Handler *win32_handler) { if (win32_handler->delete_me) { @@ -1514,10 +1419,22 @@ _ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler) } win32_handler->delete_me = EINA_TRUE; - win32_handlers_to_delete = eina_list_append(win32_handlers_to_delete, win32_handler); + win32_handler->handler = NULL; + pd->win32_handlers_to_delete = eina_list_append + (pd->win32_handlers_to_delete, win32_handler); return win32_handler->data; } +EAPI Ecore_Win32_Handler * +ecore_main_win32_handler_add(void *h, + Ecore_Win32_Handle_Cb func, + const void *data) +{ + EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); + return _ecore_main_win32_handler_add(efl_loop_main_get(EFL_LOOP_CLASS), + ML_DAT, NULL, func, data); +} + EAPI void * ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler) { @@ -1531,17 +1448,42 @@ ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler) "ecore_main_win32_handler_del"); return NULL; } - ret = _ecore_main_win32_handler_del(win32_handler); + ret = _ecore_main_win32_handler_del(ML_OBJ, ML_DAT, win32_handler); return ret; } - #else +EAPI Ecore_Win32_Handler * +_ecore_main_win32_handler_add(Eo *obj EINA_UNUSED, + Efl_Loop_Data *pd EINA_UNUSED, + Eo *handler EINA_UNUSED, + void *h EINA_UNUSED, + Ecore_Win32_Handle_Cb func EINA_UNUSED, + const void *data EINA_UNUSED) +{ + return NULL; +} + +void * +_ecore_main_win32_handler_del(Eo *obj EINA_UNUSED, + Efl_Loop_Data *pd EINA_UNUSED, + Ecore_Win32_Handler *win32_handler EINA_UNUSED) +{ + return NULL; +} + +EAPI Ecore_Win32_Handler * +ecore_main_win32_handler_add(void *h EINA_UNUSED, + Ecore_Win32_Handle_Cb func EINA_UNUSED, + const void *data EINA_UNUSED) +{ + return NULL; +} + EAPI void * ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler EINA_UNUSED) { return NULL; } - #endif EAPI void @@ -1549,20 +1491,23 @@ ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Prep_Cb func, const void *data) { + Efl_Loop_Data *pd = fd_handler->loop_data; EINA_MAIN_LOOP_CHECK_RETURN; 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 ; + return; } fd_handler->prep_func = func; fd_handler->prep_data = (void *)data; - if ((!fd_handlers_with_prep) || - (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); + if ((!pd->fd_handlers_with_prep) || + (pd->fd_handlers_with_prep && + (!eina_list_data_find(pd->fd_handlers_with_prep, fd_handler)))) + // FIXME: THIS WILL NOT SCALE WITH LOTS OF PREP FUNCTIONS!!! + pd->fd_handlers_with_prep = eina_list_append + (pd->fd_handlers_with_prep, fd_handler); } EAPI int @@ -1593,7 +1538,7 @@ ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, "ecore_main_fd_handler_active_get"); return EINA_FALSE; } - if ((flags & ECORE_FD_READ) && (fd_handler->read_active)) ret = EINA_TRUE; + 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; return ret; @@ -1603,99 +1548,117 @@ EAPI void ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags) { - int ret; - - EINA_MAIN_LOOP_CHECK_RETURN; + int ret = -1; 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 ; + return; } fd_handler->flags = flags; - ret = _ecore_main_fdh_poll_modify(fd_handler); + if (fd_handler->loop_data) + ret = _ecore_main_fdh_poll_modify(fd_handler->loop_data, fd_handler); if (ret < 0) + ERR("Failed to mod epoll fd %d, loop data=%p: %s!", + fd_handler->fd, fd_handler->loop_data, strerror(errno)); +} + +void +_ecore_main_content_clear(Efl_Loop_Data *pd) +{ + Efl_Promise *promise; + Efl_Future *future; + + EINA_LIST_FREE(pd->pending_futures, future) + efl_del(future); + Eina_List *tmp = pd->pending_promises; + pd->pending_promises = NULL; + EINA_LIST_FREE(tmp, promise) + ecore_loop_promise_fulfill(promise); + + while (pd->fd_handlers) { - ERR("Failed to mod epoll fd %d: %s!", fd_handler->fd, strerror(errno)); + Ecore_Fd_Handler *fdh = pd->fd_handlers; + + pd->fd_handlers = (Ecore_Fd_Handler *) + eina_inlist_remove(EINA_INLIST_GET(pd->fd_handlers), + EINA_INLIST_GET(fdh)); + if (fdh->handler) efl_del(fdh->handler); + else + { + ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE); + ecore_fd_handler_mp_free(fdh); + } } + if (pd) + { + if (pd->fd_handlers_with_buffer) + pd->fd_handlers_with_buffer = + eina_list_free(pd->fd_handlers_with_buffer); + if (pd->fd_handlers_with_prep) + pd->fd_handlers_with_prep = + eina_list_free(pd->fd_handlers_with_prep); + if (pd->file_fd_handlers) + pd->file_fd_handlers = + eina_list_free(pd->file_fd_handlers); + if (pd->fd_handlers_to_delete) + pd->fd_handlers_to_delete = + eina_list_free(pd->fd_handlers_to_delete); + pd->fd_handlers_to_call = NULL; + pd->fd_handlers_to_call_current = NULL; + } + + pd->do_quit = 0; + +#ifdef _WIN32 + while (pd->win32_handlers) + { + Ecore_Win32_Handler *wh = pd->win32_handlers; + + pd->win32_handlers = (Ecore_Win32_Handler *) + eina_inlist_remove(EINA_INLIST_GET(pd->win32_handlers), + EINA_INLIST_GET(wh)); + if (fdh->handler) efl_del(fdh->handler); + else + { + ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE); + ecore_win32_handler_mp_free(wh); + } + } + if (pd->win32_handlers_to_delete) + pd->win32_handlers_to_delete = + eina_list_free(pd->win32_handlers_to_delete); + pd->win32_handler_current = NULL; +#endif } void _ecore_main_shutdown(void) { - Efl_Promise *promise; - Efl_Future *future; + Efl_Loop_Data *pd = ML_DAT; - if (in_main_loop) + if (pd->in_loop) { - ERR("\n" - "*** ECORE WARNING: Calling ecore_shutdown() while still in the main loop.\n" - "*** Program may crash or behave strangely now."); + ERR("Calling ecore_shutdown() while still in the main loop!!!"); return; } - - EINA_LIST_FREE(_pending_futures, future) - efl_del(future); - - EINA_LIST_FREE(_pending_promises, promise) - ecore_loop_promise_fulfill(promise); - - while (fd_handlers) - { - Ecore_Fd_Handler *fdh; - - fdh = fd_handlers; - fd_handlers = (Ecore_Fd_Handler *)eina_inlist_remove(EINA_INLIST_GET(fd_handlers), - EINA_INLIST_GET(fdh)); - ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE); - ecore_fd_handler_mp_free(fdh); - } - if (fd_handlers_with_buffer) - fd_handlers_with_buffer = eina_list_free(fd_handlers_with_buffer); - if (fd_handlers_with_prep) - fd_handlers_with_prep = eina_list_free(fd_handlers_with_prep); - if (fd_handlers_to_delete) - fd_handlers_to_delete = eina_list_free(fd_handlers_to_delete); - if (file_fd_handlers) - file_fd_handlers = eina_list_free(file_fd_handlers); - - fd_handlers_to_call = NULL; - fd_handlers_to_call_current = NULL; - fd_handlers_to_delete = NULL; - fd_handler_current = NULL; - do_quit = 0; - -#ifdef _WIN32 - while (win32_handlers) - { - Ecore_Win32_Handler *wh; - - wh = win32_handlers; - win32_handlers = (Ecore_Win32_Handler *)eina_inlist_remove(EINA_INLIST_GET(win32_handlers), - EINA_INLIST_GET(wh)); - ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE); - ecore_win32_handler_mp_free(wh); - } - if (win32_handlers_to_delete) - win32_handlers_to_delete = eina_list_free(win32_handlers_to_delete); - win32_handlers_to_delete = NULL; - win32_handler_current = NULL; -#endif + _ecore_main_content_clear(pd); } static void -_ecore_main_prepare_handlers(void) +_ecore_main_prepare_handlers(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd) { Ecore_Fd_Handler *fdh; Eina_List *l, *l2; - /* call the prepare callback for all handlers with prep functions */ - EINA_LIST_FOREACH_SAFE(fd_handlers_with_prep, l, l2, fdh) + // call the prepare callback for all handlers with prep functions + EINA_LIST_FOREACH_SAFE(pd->fd_handlers_with_prep, l, l2, fdh) { if (!fdh) { - fd_handlers_with_prep = eina_list_remove_list(l, fd_handlers_with_prep); + pd->fd_handlers_with_prep = eina_list_remove_list + (l, pd->fd_handlers_with_prep); continue; } if (!fdh->delete_me && fdh->prep_func) @@ -1705,13 +1668,14 @@ _ecore_main_prepare_handlers(void) fdh->references--; } else - fd_handlers_with_prep = eina_list_remove_list(fd_handlers_with_prep, l); + pd->fd_handlers_with_prep = eina_list_remove_list + (pd->fd_handlers_with_prep, l); } } #if !defined(USE_G_MAIN_LOOP) static int -_ecore_main_select(double timeout) +_ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout) { struct timeval tv, *t; fd_set rfds, wfds, exfds; @@ -1720,8 +1684,8 @@ _ecore_main_select(double timeout) int max_fd, ret, err_no; t = NULL; - if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0))) /* finite() tests for NaN, too big, too small, and infinity. */ - { + if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0))) + { // finite() tests for NaN, too big, too small, and infinity. tv.tv_sec = 0; tv.tv_usec = 0; t = &tv; @@ -1747,15 +1711,14 @@ _ecore_main_select(double timeout) FD_ZERO(&wfds); FD_ZERO(&exfds); - /* call the prepare callback for all handlers */ - if (fd_handlers_with_prep) - _ecore_main_prepare_handlers(); + // call the prepare callback for all handlers + if (pd->fd_handlers_with_prep) _ecore_main_prepare_handlers(obj, pd); #ifdef HAVE_EPOLL - if (epoll_fd < 0) + if (pd->epoll_fd < 0) { #endif - EINA_INLIST_FOREACH(fd_handlers, fdh) + EINA_INLIST_FOREACH(pd->fd_handlers, fdh) { if (!fdh->delete_me) { @@ -1780,87 +1743,91 @@ _ecore_main_select(double timeout) #ifdef HAVE_EPOLL else { - /* polling on the epoll fd will wake when an fd in the epoll set is active */ - max_fd = _ecore_get_epoll_fd(); - FD_SET(max_fd, &rfds); + // polling on the epoll fd will wake when fd in the epoll set is active + max_fd = _ecore_get_epoll_fd(obj, pd); + FD_SET(max_fd, &rfds); } #endif - EINA_LIST_FOREACH(file_fd_handlers, l, fdh) - if (!fdh->delete_me) - { - if (fdh->flags & ECORE_FD_READ) - { - FD_SET(fdh->fd, &rfds); - if (fdh->fd > max_fd) max_fd = fdh->fd; - } - if (fdh->flags & ECORE_FD_WRITE) - { - FD_SET(fdh->fd, &wfds); - if (fdh->fd > max_fd) max_fd = fdh->fd; - } - if (fdh->flags & ECORE_FD_ERROR) - { - FD_SET(fdh->fd, &exfds); - if (fdh->fd > max_fd) max_fd = fdh->fd; - } - if (fdh->fd > max_fd) max_fd = fdh->fd; - } - if (_ecore_signal_count_get()) return -1; + EINA_LIST_FOREACH(pd->file_fd_handlers, l, fdh) + { + if (!fdh->delete_me) + { + if (fdh->flags & ECORE_FD_READ) + { + FD_SET(fdh->fd, &rfds); + if (fdh->fd > max_fd) max_fd = fdh->fd; + } + if (fdh->flags & ECORE_FD_WRITE) + { + FD_SET(fdh->fd, &wfds); + if (fdh->fd > max_fd) max_fd = fdh->fd; + } + if (fdh->flags & ECORE_FD_ERROR) + { + FD_SET(fdh->fd, &exfds); + if (fdh->fd > max_fd) max_fd = fdh->fd; + } + if (fdh->fd > max_fd) max_fd = fdh->fd; + } + } + if (_ecore_signal_count_get(obj, pd)) return -1; eina_evlog("RUN", NULL, 0.0, NULL); - _ecore_time_loop_time = ecore_time_get(); + pd->loop_time = ecore_time_get(); if (ret < 0) { #ifndef _WIN32 if (err_no == EINTR) return -1; - else if (err_no == EBADF) - _ecore_main_fd_handlers_bads_rem(); + else if (err_no == EBADF) _ecore_main_fd_handlers_bads_rem(obj, pd); #endif } if (ret > 0) { #ifdef HAVE_EPOLL - if (epoll_fd >= 0) - _ecore_main_fdh_epoll_mark_active(); + if (pd->epoll_fd >= 0) + _ecore_main_fdh_epoll_mark_active(obj, pd); else #endif { - EINA_INLIST_FOREACH(fd_handlers, fdh) + EINA_INLIST_FOREACH(pd->fd_handlers, fdh) { if (!fdh->delete_me) { if (FD_ISSET(fdh->fd, &rfds)) - fdh->read_active = EINA_TRUE; + fdh->read_active = EINA_TRUE; if (FD_ISSET(fdh->fd, &wfds)) fdh->write_active = EINA_TRUE; if (FD_ISSET(fdh->fd, &exfds)) fdh->error_active = EINA_TRUE; - _ecore_try_add_to_call_list(fdh); + _ecore_try_add_to_call_list(obj, pd, fdh); } } } - EINA_LIST_FOREACH(file_fd_handlers, l, fdh) + EINA_LIST_FOREACH(pd->file_fd_handlers, l, fdh) { if (!fdh->delete_me) { if (FD_ISSET(fdh->fd, &rfds)) - fdh->read_active = EINA_TRUE; + fdh->read_active = EINA_TRUE; if (FD_ISSET(fdh->fd, &wfds)) fdh->write_active = EINA_TRUE; if (FD_ISSET(fdh->fd, &exfds)) fdh->error_active = EINA_TRUE; - _ecore_try_add_to_call_list(fdh); + _ecore_try_add_to_call_list(obj, pd, fdh); } } - _ecore_main_fd_handlers_cleanup(); + _ecore_main_fd_handlers_cleanup(obj, pd); #ifdef _WIN32 - _ecore_main_win32_handlers_cleanup(); + _ecore_main_win32_handlers_cleanup(obj, pd); #endif return 1; } @@ -1872,14 +1839,14 @@ _ecore_main_select(double timeout) #ifndef _WIN32 # ifndef USE_G_MAIN_LOOP static void -_ecore_main_fd_handlers_bads_rem(void) +_ecore_main_fd_handlers_bads_rem(Eo *obj, Efl_Loop_Data *pd) { Ecore_Fd_Handler *fdh; Eina_Inlist *l; int found = 0; ERR("Removing bad fds"); - for (l = EINA_INLIST_GET(fd_handlers); l; ) + for (l = EINA_INLIST_GET(pd->fd_handlers); l; ) { fdh = (Ecore_Fd_Handler *)l; l = l->next; @@ -1898,8 +1865,9 @@ _ecore_main_fd_handlers_bads_rem(void) if (!fdh->delete_me) { fdh->delete_me = EINA_TRUE; - _ecore_main_fdh_poll_del(fdh); - fd_handlers_to_delete = eina_list_append(fd_handlers_to_delete, fdh); + _ecore_main_fdh_poll_del(pd, fdh); + pd->fd_handlers_to_delete = + eina_list_append(pd->fd_handlers_to_delete, fdh); } found++; } @@ -1907,12 +1875,14 @@ _ecore_main_fd_handlers_bads_rem(void) } else { - ERR("Problematic fd found at %d! setting it for delete", fdh->fd); + ERR("Problematic fd found at %d! setting it for delete", + fdh->fd); if (!fdh->delete_me) { fdh->delete_me = EINA_TRUE; - _ecore_main_fdh_poll_del(fdh); - fd_handlers_to_delete = eina_list_append(fd_handlers_to_delete, fdh); + _ecore_main_fdh_poll_del(pd, fdh); + pd->fd_handlers_to_delete = + eina_list_append(pd->fd_handlers_to_delete, fdh); } found++; @@ -1927,170 +1897,171 @@ _ecore_main_fd_handlers_bads_rem(void) ERR("No bad fd found. EEEK!"); # endif } - _ecore_main_fd_handlers_cleanup(); + _ecore_main_fd_handlers_cleanup(obj, pd); } # endif #endif static void -_ecore_main_fd_handlers_cleanup(void) +_ecore_main_fd_handlers_cleanup(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd) { Ecore_Fd_Handler *fdh, *last; Eina_List *l, *l2; - if (!fd_handlers_to_delete) return; - // Cleanup deleted caller from the list last = NULL; - fdh = fd_handlers_to_call; + fdh = pd->fd_handlers_to_call; while (fdh) { if (fdh->delete_me) { if (!last) - fd_handlers_to_call = fdh == fdh->next_ready ? NULL : fdh->next_ready; + pd->fd_handlers_to_call = fdh == fdh->next_ready ? + NULL : fdh->next_ready; else - last->next_ready = fdh == fdh->next_ready ? last : fdh->next_ready; - } - else - { - last = fdh; + last->next_ready = fdh == fdh->next_ready ? + last : fdh->next_ready; } + else last = fdh; - if (fdh == fdh->next_ready) - break; + if (fdh == fdh->next_ready) break; fdh = fdh->next_ready; } - EINA_LIST_FOREACH_SAFE(fd_handlers_to_delete, l, l2, fdh) + if (!pd->fd_handlers_to_delete) return; + EINA_LIST_FOREACH_SAFE(pd->fd_handlers_to_delete, l, l2, fdh) { if (!fdh) { - fd_handlers_to_delete = eina_list_remove_list(l, fd_handlers_to_delete); + pd->fd_handlers_to_delete = eina_list_remove_list + (l, pd->fd_handlers_to_delete); continue; } - /* fdh->delete_me should be set for all fdhs at the start of the list */ - if (fdh->references) - continue; - if (fd_handlers_to_call_current == fdh) - fd_handlers_to_call_current = NULL; - if (fdh->buf_func && fd_handlers_with_buffer) - fd_handlers_with_buffer = eina_list_remove(fd_handlers_with_buffer, fdh); - if (fdh->prep_func && fd_handlers_with_prep) - fd_handlers_with_prep = eina_list_remove(fd_handlers_with_prep, fdh); - fd_handlers = (Ecore_Fd_Handler *) - eina_inlist_remove(EINA_INLIST_GET(fd_handlers), EINA_INLIST_GET(fdh)); + if (fdh->references) continue; + if (pd->fd_handlers_to_call_current == fdh) + pd->fd_handlers_to_call_current = NULL; + if (fdh->buf_func && pd->fd_handlers_with_buffer) + pd->fd_handlers_with_buffer = eina_list_remove + (pd->fd_handlers_with_buffer, fdh); + if (fdh->prep_func && pd->fd_handlers_with_prep) + pd->fd_handlers_with_prep = eina_list_remove + (pd->fd_handlers_with_prep, fdh); + pd->fd_handlers = (Ecore_Fd_Handler *) + eina_inlist_remove(EINA_INLIST_GET(pd->fd_handlers), + EINA_INLIST_GET(fdh)); if (fdh->file) - file_fd_handlers = eina_list_remove(file_fd_handlers, fdh); + pd->file_fd_handlers = eina_list_remove(pd->file_fd_handlers, fdh); ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE); ecore_fd_handler_mp_free(fdh); - fd_handlers_to_delete = eina_list_remove_list(fd_handlers_to_delete, l); + pd->fd_handlers_to_delete = eina_list_remove_list + (pd->fd_handlers_to_delete, l); } } #ifdef _WIN32 static void -_ecore_main_win32_handlers_cleanup(void) +_ecore_main_win32_handlers_cleanup(Eo *obj, Efl_Loop_Data *pd) { Ecore_Win32_Handler *wh; - Eina_List *l; - Eina_List *l2; + Eina_List *l, *l2; - if (!win32_handlers_to_delete) return; - EINA_LIST_FOREACH_SAFE(win32_handlers_to_delete, l, l2, wh) + if (!pd->win32_handlers_to_delete) return; + EINA_LIST_FOREACH_SAFE(pd->win32_handlers_to_delete, l, l2, wh) { if (!wh) { - win32_handlers_to_delete = eina_list_remove_list(l, win32_handlers_to_delete); + pd->win32_handlers_to_delete = eina_list_remove_list + (l, pd->win32_handlers_to_delete); continue; } - /* wh->delete_me should be set for all whs at the start of the list */ - if (wh->references) - continue; - win32_handlers = (Ecore_Win32_Handler *) - eina_inlist_remove(EINA_INLIST_GET(win32_handlers), EINA_INLIST_GET(wh)); + // wh->delete_me should be set for all whs at the start of the list + if (wh->references) continue; + pd->win32_handlers = (Ecore_Win32_Handler *) + eina_inlist_remove(EINA_INLIST_GET(pd->win32_handlers), + EINA_INLIST_GET(wh)); ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE); ecore_win32_handler_mp_free(wh); - win32_handlers_to_delete = eina_list_remove_list(win32_handlers_to_delete, l); + pd->win32_handlers_to_delete = eina_list_remove_list + (pd->win32_handlers_to_delete, l); } } - #endif static void -_ecore_main_fd_handlers_call(void) +_ecore_main_fd_handlers_call(Eo *obj, Efl_Loop_Data *pd) { - /* grab a new list */ - if (!fd_handlers_to_call_current) - { - fd_handlers_to_call_current = fd_handlers_to_call; - fd_handlers_to_call = NULL; - } + // grab a new list + if (!pd->fd_handlers_to_call_current) + { + pd->fd_handlers_to_call_current = pd->fd_handlers_to_call; + pd->fd_handlers_to_call = NULL; + } - if (!fd_handlers_to_call_current) return; + if (!pd->fd_handlers_to_call_current) return; eina_evlog("+fd_handlers", NULL, 0.0, NULL); - while (fd_handlers_to_call_current) - { - Ecore_Fd_Handler *fdh = fd_handlers_to_call_current; + while (pd->fd_handlers_to_call_current) + { + Ecore_Fd_Handler *fdh = pd->fd_handlers_to_call_current; - if (!fdh->delete_me) - { - if ((fdh->read_active) || - (fdh->write_active) || - (fdh->error_active)) - { - fdh->references++; - if (!_ecore_call_fd_cb(fdh->func, fdh->data, fdh)) - { - if (!fdh->delete_me) - { - fdh->delete_me = EINA_TRUE; - _ecore_main_fdh_poll_del(fdh); - fd_handlers_to_delete = eina_list_append(fd_handlers_to_delete, fdh); - } - } - fdh->references--; + if (!fdh->delete_me) + { + if ((fdh->read_active) || + (fdh->write_active) || + (fdh->error_active)) + { + fdh->references++; + if (!_ecore_call_fd_cb(fdh->func, fdh->data, fdh)) + { + if (!fdh->delete_me) + { + fdh->delete_me = EINA_TRUE; + _ecore_main_fdh_poll_del(pd, fdh); + pd->fd_handlers_to_delete = eina_list_append + (pd->fd_handlers_to_delete, fdh); + } + } + fdh->references--; #ifdef EFL_EXTRA_SANITY_CHECKS - _ecore_fd_valid(); + _ecore_fd_valid(obj, pd); #endif + fdh->read_active = EINA_FALSE; + fdh->write_active = EINA_FALSE; + fdh->error_active = EINA_FALSE; + } + } - fdh->read_active = EINA_FALSE; - fdh->write_active = EINA_FALSE; - fdh->error_active = EINA_FALSE; - } - } + // stop when we point to ourselves + if (fdh->next_ready == fdh) + { + fdh->next_ready = NULL; + pd->fd_handlers_to_call_current = NULL; + break; + } - /* stop when we point to ourselves */ - if (fdh->next_ready == fdh) - { - fdh->next_ready = NULL; - fd_handlers_to_call_current = NULL; - break; - } - - fd_handlers_to_call_current = fdh->next_ready; - fdh->next_ready = NULL; + pd->fd_handlers_to_call_current = fdh->next_ready; + fdh->next_ready = NULL; } eina_evlog("-fd_handlers", NULL, 0.0, NULL); } static int -_ecore_main_fd_handlers_buf_call(void) +_ecore_main_fd_handlers_buf_call(Eo *obj, Efl_Loop_Data *pd) { Ecore_Fd_Handler *fdh; Eina_List *l, *l2; int ret; - if (!fd_handlers_with_buffer) return 0; + if (!pd->fd_handlers_with_buffer) return 0; eina_evlog("+fd_handlers_buf", NULL, 0.0, NULL); ret = 0; - EINA_LIST_FOREACH_SAFE(fd_handlers_with_buffer, l, l2, fdh) + EINA_LIST_FOREACH_SAFE(pd->fd_handlers_with_buffer, l, l2, fdh) { if (!fdh) { - fd_handlers_with_buffer = eina_list_remove_list(l, fd_handlers_with_buffer); + pd->fd_handlers_with_buffer = eina_list_remove_list + (l, pd->fd_handlers_with_buffer); continue; } if ((!fdh->delete_me) && fdh->buf_func) @@ -2100,12 +2071,13 @@ _ecore_main_fd_handlers_buf_call(void) { ret |= _ecore_call_fd_cb(fdh->func, fdh->data, fdh); fdh->read_active = EINA_TRUE; - _ecore_try_add_to_call_list(fdh); + _ecore_try_add_to_call_list(obj, pd, fdh); } fdh->references--; } else - fd_handlers_with_buffer = eina_list_remove_list(fd_handlers_with_buffer, l); + pd->fd_handlers_with_buffer = eina_list_remove_list + (pd->fd_handlers_with_buffer, l); } eina_evlog("-fd_handlers_buf", NULL, 0.0, NULL); return ret; @@ -2113,111 +2085,107 @@ _ecore_main_fd_handlers_buf_call(void) #ifdef HAVE_LIBUV static void -_ecore_main_loop_uv_prepare(uv_prepare_t* handle EINA_UNUSED) +_ecore_main_loop_uv_prepare(uv_prepare_t *handle EINA_UNUSED) { + Eo *obj = ML_OBJ; + Efl_Loop_Data *pd = ML_DAT; + double t = -1; + _dl_uv_timer_stop(&_ecore_main_uv_handle_timers); - if(in_main_loop == 0 && do_quit) + if ((pd->in_loop == 0) && (pd->do_quit)) { - _ecore_main_fd_handlers_cleanup(); + _ecore_main_fd_handlers_cleanup(obj, pd); - while (fd_handlers) - { - Ecore_Fd_Handler *fdh; + while (pd->fd_handlers) + { + Ecore_Fd_Handler *fdh = pd->fd_handlers; + pd->fd_handlers = (Ecore_Fd_Handler *) + eina_inlist_remove(EINA_INLIST_GET(pd->fd_handlers), + EINA_INLIST_GET(fdh)); + fdh->delete_me = 1; + _ecore_main_fdh_poll_del(pd, fdh); + ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE); + ecore_fd_handler_mp_free(fdh); + } + if (pd->fd_handlers_with_buffer) + pd->fd_handlers_with_buffer = eina_list_free(pd->fd_handlers_with_buffer); + if (pd->fd_handlers_with_prep) + pd->fd_handlers_with_prep = eina_list_free(pd->fd_handlers_with_prep); + if (pd->fd_handlers_to_delete) + pd->fd_handlers_to_delete = eina_list_free(pd->fd_handlers_to_delete); + if (pd->file_fd_handlers) + pd->file_fd_handlers = eina_list_free(pd->file_fd_handlers); - fdh = fd_handlers; - fd_handlers = (Ecore_Fd_Handler *)eina_inlist_remove(EINA_INLIST_GET(fd_handlers), - EINA_INLIST_GET(fdh)); - fdh->delete_me = 1; - _ecore_main_fdh_poll_del(fdh); - ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE); - ecore_fd_handler_mp_free(fdh); - } - if (fd_handlers_with_buffer) - fd_handlers_with_buffer = eina_list_free(fd_handlers_with_buffer); - if (fd_handlers_with_prep) - fd_handlers_with_prep = eina_list_free(fd_handlers_with_prep); - if (fd_handlers_to_delete) - fd_handlers_to_delete = eina_list_free(fd_handlers_to_delete); - if (file_fd_handlers) - file_fd_handlers = eina_list_free(file_fd_handlers); + pd->fd_handlers_to_call = NULL; + pd->fd_handlers_to_call_current = NULL; - fd_handlers_to_call = NULL; - fd_handlers_to_call_current = NULL; - fd_handlers_to_delete = NULL; - fd_handler_current = NULL; + _dl_uv_prepare_stop(&_ecore_main_uv_prepare); + _dl_uv_check_stop(&_ecore_main_uv_check); + _dl_uv_stop(_dl_uv_default_loop()); - _dl_uv_prepare_stop(&_ecore_main_uv_prepare); - _dl_uv_check_stop(&_ecore_main_uv_check); - _dl_uv_stop(_dl_uv_default_loop()); - - return; + return; } in_main_loop++; + pd->in_loop = in_main_loop; - if(!_ecore_main_uv_idling) + if (!_ecore_main_uv_idling) { _ecore_main_uv_idling = EINA_TRUE; - _ecore_idle_enterer_call(_mainloop_singleton); + _ecore_idle_enterer_call(obj); _ecore_throttle(); + _throttle_do(pd); } - double t = -1; - if(_ecore_main_uv_idling) + if (_ecore_main_uv_idling) { - _ecore_idler_all_call(_mainloop_singleton); - DBG("called idles"); - if(_ecore_idler_exist(_mainloop_singleton) || _ecore_event_exist()) - t = 0.0; + _ecore_idler_all_call(obj); + DBG("called idles"); + if (_ecore_idler_exist(_obj) || efl_loop_message_exists(obj)) t = 0.0; } - if (do_quit) + if (pd->do_quit) { - DBG("do quit outside loop"); + DBG("do quit outside loop"); - if(_ecore_main_uv_idling) - { - _ecore_idle_exiter_call(_mainloop_singleton); - _ecore_animator_run_reset(); - - _ecore_main_uv_idling = EINA_FALSE; - } - - t = -1; - - _ecore_time_loop_time = ecore_time_get(); - _efl_loop_timer_enable_new(); - - goto done; + if (_ecore_main_uv_idling) + { + _ecore_idle_exiter_call(obj); + _ecore_animator_run_reset(); + _ecore_main_uv_idling = EINA_FALSE; + } + t = -1; + pd->loop_time = ecore_time_get(); + _efl_loop_timer_enable_new(obj, pd); + goto done; } - assert(!fd_handlers_to_call); + assert(!pd->fd_handlers_to_call); - _ecore_time_loop_time = ecore_time_get(); - _efl_loop_timer_enable_new(); - if (_efl_loop_timers_exists() || t >= 0) + pd->loop_time = ecore_time_get(); + _efl_loop_timer_enable_new(obj, pd); + if (_efl_loop_timers_exists(obj, pd) || (t >= 0)) { - double tnext = _efl_loop_timer_next_get(); - if (t < 0 || (tnext >= 0 && tnext < t)) t = tnext; - DBG("Should awake after %f", t); - - if (t >= 0.0) - { - //_dl_uv_timer_stop(&_ecore_main_uv_handle_timers); - _dl_uv_timer_start(&_ecore_main_uv_handle_timers, &_ecore_main_loop_timer_run, t * 1000 - , 0); - } - else - DBG("Is not going to awake with timer"); + double tnext = _efl_loop_timer_next_get(obj, pd); + + if ((t < 0) || ((tnext >= 0) && (tnext < t))) t = tnext; + DBG("Should awake after %f", t); + + if (t >= 0.0) + { + // _dl_uv_timer_stop(&_ecore_main_uv_handle_timers); + _dl_uv_timer_start(&_ecore_main_uv_handle_timers, + &_ecore_main_loop_timer_run, + t * 1000, 0); + } + else DBG("Is not going to awake with timer"); } - else - DBG("Is not going to awake with timer"); - - done: - if (fd_handlers_with_prep) - _ecore_main_prepare_handlers(); + else DBG("Is not going to awake with timer"); +done: + if (pd->fd_handlers_with_prep) _ecore_main_prepare_handlers(obj, pd); in_main_loop--; + pd->in_loop = in_main_loop; } #endif @@ -2229,56 +2197,57 @@ enum { }; static int -_ecore_main_loop_spin_core(void) +_ecore_main_loop_spin_core(Eo *obj, Efl_Loop_Data *pd) { - /* as we are spinning we need to update loop time per spin */ - _ecore_time_loop_time = ecore_time_get(); - /* call all idlers */ - _ecore_idler_all_call(_mainloop_singleton); - /* which returns false if no more idelrs exist */ - if (!_ecore_idler_exist(_mainloop_singleton)) return SPIN_RESTART; - /* sneaky - drop through or if checks - the first one to succeed - * drops through and returns "continue" so further ones dont run */ - if ((_ecore_main_select(0.0) > 0) || (_ecore_event_exist()) || - (_ecore_signal_count_get() > 0) || (do_quit)) - return LOOP_CONTINUE; - /* default - spin more */ - return SPIN_MORE; + // as we are spinning we need to update loop time per spin + pd->loop_time = ecore_time_get(); + // call all idlers + _ecore_idler_all_call(obj); + // which returns false if no more idelrs exist + if (!_ecore_idler_exist(obj)) return SPIN_RESTART; + // sneaky - drop through or if checks - the first one to succeed + // drops through and returns "continue" so further ones dont run + if ((_ecore_main_select(obj, pd, 0.0) > 0) || + (efl_loop_message_exists(obj)) || + (_ecore_signal_count_get(obj, pd) > 0) || (pd->do_quit)) + return LOOP_CONTINUE; + // default - spin more + return SPIN_MORE; } static int -_ecore_main_loop_spin_no_timers(void) +_ecore_main_loop_spin_no_timers(Eo *obj, Efl_Loop_Data *pd) { - /* if we have idlers we HAVE to spin and handle everything - * in a polling way - spin in a tight polling loop */ - for (;; ) - { - int action = _ecore_main_loop_spin_core(); - if (action != SPIN_MORE) return action; - /* if an idler has added a timer then we need to go through - * the start of the spin cycle again to handle cases properly */ - if (_efl_loop_timers_exists()) return SPIN_RESTART; - } - /* just contiune handling events etc. */ - return LOOP_CONTINUE; + // if we have idlers we HAVE to spin and handle everything + // in a polling way - spin in a tight polling loop + for (;;) + { + int action = _ecore_main_loop_spin_core(obj, pd); + if (action != SPIN_MORE) return action; + // if an idler has added a timer then we need to go through + // the start of the spin cycle again to handle cases properly + if (_efl_loop_timers_exists(obj, pd)) return SPIN_RESTART; + } + // just contiune handling events etc. + return LOOP_CONTINUE; } static int -_ecore_main_loop_spin_timers(void) +_ecore_main_loop_spin_timers(Eo *obj, Efl_Loop_Data *pd) { - /* if we have idlers we HAVE to spin and handle everything - * in a polling way - spin in a tight polling loop */ - for (;; ) - { - int action = _ecore_main_loop_spin_core(); - if (action != SPIN_MORE) return action; - /* if next timer expires now or in the past - stop spinning and - * continue the mainloop walk as our "select" timeout has - * expired now */ - if (_efl_loop_timer_next_get() <= 0.0) return LOOP_CONTINUE; - } - /* just contiune handling events etc. */ - return LOOP_CONTINUE; + // if we have idlers we HAVE to spin and handle everything + // in a polling way - spin in a tight polling loop + for (;;) + { + int action = _ecore_main_loop_spin_core(obj, pd); + if (action != SPIN_MORE) return action; + // if next timer expires now or in the past - stop spinning and + // continue the mainloop walk as our "select" timeout has + // expired now + if (_efl_loop_timer_next_get(obj, pd) <= 0.0) return LOOP_CONTINUE; + } + // just contiune handling events etc. + return LOOP_CONTINUE; } static void @@ -2297,163 +2266,168 @@ _ecore_fps_marker_2(void) } static void -_ecore_main_loop_iterate_internal(int once_only) +_ecore_main_loop_iterate_internal(Eo *obj, Efl_Loop_Data *pd, int once_only) { double next_time = -1.0; Eo *f, *p; - in_main_loop++; - - /* destroy all optional futures */ - EINA_LIST_FREE(_pending_futures, f) - efl_del(f); - - /* and propagate all promise value */ - EINA_LIST_FREE(_pending_promises, p) - ecore_loop_promise_fulfill(p); - - /* expire any timers */ - _efl_loop_timer_expired_timers_call(_ecore_time_loop_time); - - /* process signals into events .... */ - _ecore_signal_received_process(); - /* if as a result of timers/animators or signals we have accumulated - * events, then instantly handle them */ - if (_ecore_event_exist()) + if (obj == ML_OBJ) { - /* but first conceptually enter an idle state */ - _ecore_idle_enterer_call(_mainloop_singleton); + in_main_loop++; + pd->in_loop = in_main_loop; + } + // destroy all optional futures + EINA_LIST_FREE(pd->pending_futures, f) efl_del(f); + // and propagate all promise value + Eina_List *tmp = pd->pending_promises; + pd->pending_promises = NULL; + EINA_LIST_FREE(tmp, p) ecore_loop_promise_fulfill(p); + // expire any timers + _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time); + // process signals into events .... + if (obj == ML_OBJ) _ecore_signal_received_process(obj, pd); + // if as a result of timers/animators or signals we have accumulated + // events, then instantly handle them + if (efl_loop_message_exists(obj)) + { + // but first conceptually enter an idle state + _ecore_idle_enterer_call(obj); _ecore_throttle(); - /* now quickly poll to see which input fd's are active */ - _ecore_main_select(0.0); - /* allow newly queued timers to expire from now on */ - _efl_loop_timer_enable_new(); - /* go straight to processing the events we had queued */ + _throttle_do(pd); + // now quickly poll to see which input fd's are active + _ecore_main_select(obj, pd, 0.0); + // allow newly queued timers to expire from now on + _efl_loop_timer_enable_new(obj, pd); + // go straight to processing the events we had queued goto process_all; } if (once_only) { - /* in once_only mode we should quickly poll for inputs, signals - * if we got any events or signals, allow new timers to process. - * use bitwise or to force both conditions to be tested and - * merged together */ - if (_ecore_main_select(0.0) | _ecore_signal_count_get()) + // in once_only mode we should quickly poll for inputs, signals + // if we got any events or signals, allow new timers to process. + // use bitwise or to force both conditions to be tested and + // merged together + if (_ecore_main_select(obj, pd, 0.0) | + _ecore_signal_count_get(obj, pd)) { - _efl_loop_timer_enable_new(); + _efl_loop_timer_enable_new(obj, pd); goto process_all; } } else { - /* call idle enterers ... */ - _ecore_idle_enterer_call(_mainloop_singleton); + // call idle enterers ... + _ecore_idle_enterer_call(obj); _ecore_throttle(); + _throttle_do(pd); } - /* if these calls caused any buffered events to appear - deal with them */ - if (fd_handlers_with_buffer) - _ecore_main_fd_handlers_buf_call(); + // if these calls caused any buffered events to appear - deal with them + if (pd->fd_handlers_with_buffer) + _ecore_main_fd_handlers_buf_call(obj, pd); - /* if there are any (buffered fd handling may generate them) - * then jump to processing them */ - if (_ecore_event_exist()) + // if there are any (buffered fd handling may generate them) + // then jump to processing them */ + if (efl_loop_message_exists(obj)) { - _ecore_main_select(0.0); - _efl_loop_timer_enable_new(); + _ecore_main_select(obj, pd, 0.0); + _efl_loop_timer_enable_new(obj, pd); goto process_all; } if (once_only) { - /* in once_only mode enter idle here instead and then return */ - _ecore_idle_enterer_call(_mainloop_singleton); + // in once_only mode enter idle here instead and then return + _ecore_idle_enterer_call(obj); _ecore_throttle(); - _efl_loop_timer_enable_new(); + _throttle_do(pd); + _efl_loop_timer_enable_new(obj, pd); goto done; } - _ecore_fps_marker_1(); + if (obj == ML_OBJ) _ecore_fps_marker_1(); - /* start of the sleeping or looping section */ -start_loop: /*-*************************************************************/ - /* We could be looping here without exiting the function and we need to - process future and promise before the next waiting period. */ - /* destroy all optional futures */ - EINA_LIST_FREE(_pending_futures, f) - efl_del(f); - - /* and propagate all promise value */ - EINA_LIST_FREE(_pending_promises, p) - ecore_loop_promise_fulfill(p); - - /* any timers re-added as a result of these are allowed to go */ - _efl_loop_timer_enable_new(); - /* if we have been asked to quit the mainloop then exit at this point */ - if (do_quit) + // start of the sleeping or looping section +start_loop: //-************************************************************* + // We could be looping here without exiting the function and we need to + // process future and promise before the next waiting period. + // destroy all optional futures + EINA_LIST_FREE(pd->pending_futures, f) efl_del(f); + // and propagate all promise value + tmp = pd->pending_promises; + pd->pending_promises = NULL; + EINA_LIST_FREE(tmp, p) ecore_loop_promise_fulfill(p); + // any timers re-added as a result of these are allowed to go + _efl_loop_timer_enable_new(obj, pd); + // if we have been asked to quit the mainloop then exit at this point + if (pd->do_quit) { - _efl_loop_timer_enable_new(); + _efl_loop_timer_enable_new(obj, pd); goto done; } - if (!_ecore_event_exist()) + if (!efl_loop_message_exists(obj)) { - /* init flags */ - next_time = _efl_loop_timer_next_get(); - /* no idlers */ - if (!_ecore_idler_exist(_mainloop_singleton)) + // init flags + next_time = _efl_loop_timer_next_get(obj, pd); + // no idlers + if (!_ecore_idler_exist(obj)) { - /* sleep until timeout or forever (-1.0) waiting for on fds */ - _ecore_main_select(next_time); + // sleep until timeout or forever (-1.0) waiting for on fds + _ecore_main_select(obj, pd, next_time); } else { int action = LOOP_CONTINUE; - /* no timers - spin */ - if (next_time < 0) action = _ecore_main_loop_spin_no_timers(); + // no timers - spin + if (next_time < 0) action = _ecore_main_loop_spin_no_timers(obj, pd); /* timers - spin */ - else action = _ecore_main_loop_spin_timers(); + else action = _ecore_main_loop_spin_timers(obj, pd); if (action == SPIN_RESTART) goto start_loop; } } - _ecore_fps_marker_2(); + if (obj == ML_OBJ) _ecore_fps_marker_2(); - /* actually wake up and deal with input, events etc. */ -process_all: /*-*********************************************************/ + // actually wake up and deal with input, events etc. +process_all: //-********************************************************* - /* we came out of our "wait state" so idle has exited */ + // we came out of our "wait state" so idle has exited if (!once_only) { - _ecore_animator_run_reset(); - _ecore_idle_exiter_call(_mainloop_singleton); + _ecore_animator_run_reset(); // XXX: + _ecore_idle_exiter_call(obj); } - /* call the fd handler per fd that became alive... */ - /* this should read or write any data to the monitored fd and then */ - /* post events onto the ecore event pipe if necessary */ - _ecore_main_fd_handlers_call(); - if (fd_handlers_with_buffer) _ecore_main_fd_handlers_buf_call(); - /* process signals into events .... */ - _ecore_signal_received_process(); - /* handle events ... */ - _ecore_event_call(); - _ecore_main_fd_handlers_cleanup(); + // call the fd handler per fd that became alive... + // this should read or write any data to the monitored fd and then + // post events onto the ecore event pipe if necessary + _ecore_main_fd_handlers_call(obj, pd); + if (pd->fd_handlers_with_buffer) _ecore_main_fd_handlers_buf_call(obj, pd); + // process signals into events .... + _ecore_signal_received_process(obj, pd); + // handle events ... + efl_loop_message_process(obj); // XXX: event queue per loop + _ecore_main_fd_handlers_cleanup(obj, pd); if (once_only) { - /* if in once_only mode handle idle exiting */ - _ecore_idle_enterer_call(_mainloop_singleton); + // if in once_only mode handle idle exiting + _ecore_idle_enterer_call(obj); _ecore_throttle(); + _throttle_do(pd); } -done: /*-*****************************************************************/ - /* Agressively flush animator */ +done: //-***************************************************************** + // Agressively flush animator _ecore_animator_flush(); if (!once_only) + eina_slstr_local_clear(); // Free all short lived strings + + if (obj == ML_OBJ) { - /* Free all short lived strings */ - eina_slstr_local_clear(); + in_main_loop--; + pd->in_loop = in_main_loop; } - in_main_loop--; } #endif @@ -2461,24 +2435,20 @@ done: /*-*****************************************************************/ #ifdef _WIN32 typedef struct { - DWORD objects_nbr; + DWORD objects_nbr; HANDLE *objects; - DWORD timeout; + DWORD timeout; } Ecore_Main_Win32_Thread_Data; static unsigned int __stdcall _ecore_main_win32_objects_wait_thread(void *data) { - Ecore_Main_Win32_Thread_Data *td; - DWORD result; - - td = (Ecore_Main_Win32_Thread_Data *)data; - result = MsgWaitForMultipleObjects(td->objects_nbr, - (const HANDLE *)td->objects, - FALSE, - td->timeout, - QS_ALLINPUT); - return result; + Ecore_Main_Win32_Thread_Data *td = (Ecore_Main_Win32_Thread_Data *)data; + return MsgWaitForMultipleObjects(td->objects_nbr, + (const HANDLE *)td->objects, + FALSE, + td->timeout, + QS_ALLINPUT); } static DWORD @@ -2488,26 +2458,19 @@ _ecore_main_win32_objects_wait(DWORD objects_nbr, { Ecore_Main_Win32_Thread_Data *threads_data; HANDLE *threads_handles; - DWORD threads_nbr; - DWORD threads_remain; - DWORD objects_idx; - DWORD result; - DWORD i; + DWORD threads_nbr threads_remain, objects_idx, result, i; if (objects_nbr < MAXIMUM_WAIT_OBJECTS) return MsgWaitForMultipleObjects(objects_nbr, objects, EINA_FALSE, timeout, QS_ALLINPUT); - /* - * too much objects, so we launch a bunch of threads to - * wait for, each one calls MsgWaitForMultipleObjects - */ + // too much objects, so we launch a bunch of threads to + // wait for, each one calls MsgWaitForMultipleObjects threads_nbr = objects_nbr / (MAXIMUM_WAIT_OBJECTS - 1); threads_remain = objects_nbr % (MAXIMUM_WAIT_OBJECTS - 1); - if (threads_remain > 0) - threads_nbr++; + if (threads_remain > 0) threads_nbr++; if (threads_nbr > MAXIMUM_WAIT_OBJECTS) { @@ -2522,7 +2485,8 @@ _ecore_main_win32_objects_wait(DWORD objects_nbr, return WAIT_FAILED; } - threads_data = (Ecore_Main_Win32_Thread_Data *)malloc(threads_nbr * sizeof(Ecore_Main_Win32_Thread_Data)); + threads_data = (Ecore_Main_Win32_Thread_Data *) + malloc(threads_nbr * sizeof(Ecore_Main_Win32_Thread_Data)); if (!threads_data) { ERR("Can not allocate memory for the waiting thread."); @@ -2546,12 +2510,9 @@ _ecore_main_win32_objects_wait(DWORD objects_nbr, objects_idx += (MAXIMUM_WAIT_OBJECTS - 1); } - threads_handles[i] = (HANDLE)_beginthreadex(NULL, - 0, - _ecore_main_win32_objects_wait_thread, - &threads_data[i], - 0, - NULL); + threads_handles[i] = (HANDLE)_beginthreadex + (NULL, 0, _ecore_main_win32_objects_wait_thread, + &threads_data[i], 0, NULL); if (!threads_handles[i]) { DWORD j; @@ -2567,22 +2528,21 @@ _ecore_main_win32_objects_wait(DWORD objects_nbr, result = WaitForMultipleObjects(threads_nbr, threads_handles, - FALSE, /* we wait until one thread is signaled */ + FALSE, // we wait until one thread signaled INFINITE); if (result < (WAIT_OBJECT_0 + threads_nbr)) { DWORD wait_res; - /* - * One of the thread callback has exited so we retrieve - * its exit status, that is the returned value of - * MsgWaitForMultipleObjects() - */ + // One of the thread callback has exited so we retrieve + // its exit status, that is the returned value of + // MsgWaitForMultipleObjects() if (GetExitCodeThread(threads_handles[result - WAIT_OBJECT_0], &wait_res)) { - WaitForMultipleObjects(threads_nbr, threads_handles, TRUE, INFINITE); + WaitForMultipleObjects(threads_nbr, threads_handles, + TRUE, INFINITE); for (i = 0; i < threads_nbr; i++) CloseHandle(threads_handles[i]); free(threads_data); @@ -2598,13 +2558,12 @@ _ecore_main_win32_objects_wait(DWORD objects_nbr, goto close_thread; } - close_thread: +close_thread: WaitForMultipleObjects(threads_nbr, threads_handles, TRUE, INFINITE); - for (i = 0; i < threads_nbr; i++) - CloseHandle(threads_handles[i]); - free_threads_data: + for (i = 0; i < threads_nbr; i++) CloseHandle(threads_handles[i]); +free_threads_data: free(threads_data); - free_threads_handles: +free_threads_handles: free(threads_handles); return WAIT_FAILED; @@ -2615,7 +2574,6 @@ _stdin_wait_thread(void *data EINA_UNUSED) { int c = getc(stdin); ungetc(c, stdin); - return 0; } @@ -2626,39 +2584,41 @@ _ecore_main_win32_select(int nfds EINA_UNUSED, fd_set *exceptfds, struct timeval *tv) { + Eo *obj = ML_OBJ; + Efl_Loop_Data *pd = ML_DAT; HANDLE *objects; - static HANDLE stdin_wait_thread = INVALID_HANDLE_VALUE; - Eina_Bool stdin_thread_done = EINA_FALSE; - HANDLE stdin_handle; int *sockets; Ecore_Fd_Handler *fdh; Ecore_Win32_Handler *wh; + static HANDLE stdin_wait_thread = INVALID_HANDLE_VALUE; + HANDLE stdin_handle; + DWORD result, timeout; + MSG msg; unsigned int fds_nbr = 0; unsigned int objects_nbr = 0; unsigned int events_nbr = 0; - DWORD result; - DWORD timeout; - MSG msg; unsigned int i; int res; + Eina_Bool stdin_thread_done = EINA_FALSE; - fds_nbr = eina_inlist_count(EINA_INLIST_GET(fd_handlers)); + fds_nbr = eina_inlist_count(EINA_INLIST_GET(pd->fd_handlers)); sockets = (int *)malloc(fds_nbr * sizeof(int)); - if (!sockets) - return -1; + if (!sockets) return -1; - objects = (HANDLE)malloc((fds_nbr + eina_inlist_count(EINA_INLIST_GET(win32_handlers))) * sizeof(HANDLE)); + objects = (HANDLE)malloc((fds_nbr + + eina_inlist_count + (EINA_INLIST_GET(pd->win32_handlers))) + * sizeof(HANDLE)); if (!objects) { free(sockets); return -1; } - /* Create an event object per socket */ - EINA_INLIST_FOREACH(fd_handlers, fdh) + // Create an event object per socket + EINA_INLIST_FOREACH(pd->fd_handlers, fdh) { - if (fdh->delete_me) - continue; + if (fdh->delete_me) continue; WSAEVENT event; long network_event; @@ -2691,11 +2651,10 @@ _ecore_main_win32_select(int nfds EINA_UNUSED, } } stdin_handle = GetStdHandle(STD_INPUT_HANDLE); - /* store the HANDLEs in the objects to wait for */ - EINA_INLIST_FOREACH(win32_handlers, wh) + // store the HANDLEs in the objects to wait for + EINA_INLIST_FOREACH(pd->win32_handlers, wh) { - if (wh->delete_me) - continue; + if (wh->delete_me) continue; if (wh->h == stdin_handle) { @@ -2708,26 +2667,21 @@ _ecore_main_win32_select(int nfds EINA_UNUSED, NULL); objects[objects_nbr] = stdin_wait_thread; } - else - { - objects[objects_nbr] = wh->h; - } + else objects[objects_nbr] = wh->h; objects_nbr++; } - /* Empty the queue before waiting */ + // Empty the queue before waiting while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } - /* Wait for any message sent or posted to this queue */ - /* or for one of the passed handles be set to signaled. */ - if (!tv) - timeout = INFINITE; - else - timeout = (DWORD)((tv->tv_sec * 1000.0) + (tv->tv_usec / 1000.0)); + // Wait for any message sent or posted to this queue + // or for one of the passed handles be set to signaled. + if (!tv) timeout = INFINITE; + else timeout = (DWORD)((tv->tv_sec * 1000.0) + (tv->tv_usec / 1000.0)); if (timeout == 0) { @@ -2738,15 +2692,10 @@ _ecore_main_win32_select(int nfds EINA_UNUSED, result = _ecore_main_win32_objects_wait(objects_nbr, (const HANDLE *)objects, timeout); - - if (readfds) - FD_ZERO(readfds); - if (writefds) - FD_ZERO(writefds); - if (exceptfds) - FD_ZERO(exceptfds); - - /* The result tells us the type of event we have. */ + if (readfds) FD_ZERO(readfds); + if (writefds) FD_ZERO(writefds); + if (exceptfds) FD_ZERO(exceptfds); + // The result tells us the type of event we have. if (result == WAIT_FAILED) { WRN("%s", evil_last_error_get()); @@ -2764,7 +2713,6 @@ _ecore_main_win32_select(int nfds EINA_UNUSED, TranslateMessage(&msg); DispatchMessage(&msg); } - res = 0; } else if (result < WAIT_OBJECT_0 + events_nbr) @@ -2772,39 +2720,37 @@ _ecore_main_win32_select(int nfds EINA_UNUSED, WSANETWORKEVENTS network_event; WSAEnumNetworkEvents(sockets[result], objects[result], &network_event); - - if ((network_event.lNetworkEvents & (FD_READ | FD_CONNECT | FD_ACCEPT)) && readfds) + if ((network_event.lNetworkEvents & + (FD_READ | FD_CONNECT | FD_ACCEPT)) && readfds) FD_SET(sockets[result], readfds); - if ((network_event.lNetworkEvents & (FD_WRITE | FD_CLOSE)) && writefds) + if ((network_event.lNetworkEvents & + (FD_WRITE | FD_CLOSE)) && writefds) FD_SET(sockets[result], writefds); if ((network_event.lNetworkEvents & FD_OOB) && exceptfds) FD_SET(sockets[result], exceptfds); - res = 1; } else if ((result >= (WAIT_OBJECT_0 + events_nbr)) && (result < (WAIT_OBJECT_0 + objects_nbr))) { - if (!win32_handler_current) - { - /* regular main loop, start from head */ - win32_handler_current = win32_handlers; - } + if (!pd->win32_handler_current) + // regular main loop, start from head + pd->win32_handler_current = pd->win32_handlers; else - { - /* recursive main loop, continue from where we were */ - win32_handler_current = (Ecore_Win32_Handler *)EINA_INLIST_GET(win32_handler_current)->next; - } + // recursive main loop, continue from where we were + pd->win32_handler_current = (Ecore_Win32_Handler *) + EINA_INLIST_GET(pd->win32_handler_current)->next; if (objects[result - WAIT_OBJECT_0] == stdin_wait_thread) stdin_thread_done = EINA_TRUE; - while (win32_handler_current) + while (pd->win32_handler_current) { - wh = win32_handler_current; + wh = pd->win32_handler_current; - if (objects[result - WAIT_OBJECT_0] == wh->h || - (objects[result - WAIT_OBJECT_0] == stdin_wait_thread && wh->h == stdin_handle)) + if ((objects[result - WAIT_OBJECT_0] == wh->h) || + ((objects[result - WAIT_OBJECT_0] == stdin_wait_thread) && + (wh->h == stdin_handle))) { if (!wh->delete_me) { @@ -2812,13 +2758,16 @@ _ecore_main_win32_select(int nfds EINA_UNUSED, if (!wh->func(wh->data, wh)) { wh->delete_me = EINA_TRUE; - win32_handlers_to_delete = eina_list_append(win32_handlers_to_delete, wh); + pd->win32_handlers_to_delete = eina_list_append + (pd->win32_handlers_to_delete, wh); } wh->references--; } } - if (win32_handler_current) /* may have changed in recursive main loops */ - win32_handler_current = (Ecore_Win32_Handler *)EINA_INLIST_GET(win32_handler_current)->next; + if (pd->win32_handler_current) + // may have changed in recursive main loops + pd->win32_handler_current = (Ecore_Win32_Handler *) + EINA_INLIST_GET(pd->win32_handler_current)->next; } res = 1; } @@ -2828,508 +2777,14 @@ _ecore_main_win32_select(int nfds EINA_UNUSED, res = -1; } -err : - /* Remove event objects again */ +err: + // Remove event objects again for (i = 0; i < events_nbr; i++) WSACloseEvent(objects[i]); - if (stdin_thread_done) - stdin_wait_thread = INVALID_HANDLE_VALUE; + if (stdin_thread_done) stdin_wait_thread = INVALID_HANDLE_VALUE; free(objects); free(sockets); return res; } - #endif - -Eo *_mainloop_singleton = NULL; - -EOLIAN static Efl_Loop * -_efl_loop_main_get(Efl_Class *klass EINA_UNUSED, void *_pd EINA_UNUSED) -{ - if (!_mainloop_singleton) - { - _mainloop_singleton = efl_add(EFL_LOOP_CLASS, NULL); - } - - return _mainloop_singleton; -} - -EAPI Eo * -ecore_main_loop_get(void) -{ - return efl_loop_main_get(EFL_LOOP_CLASS); -} - -EOLIAN static void -_efl_loop_iterate(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) -{ - ecore_main_loop_iterate(); -} - -EOLIAN static int _efl_loop_iterate_may_block(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED, int may_block) -{ - return ecore_main_loop_iterate_may_block(may_block); -} - -// FIXME: This should return an Eina_Value, but that doesn't work at the moment -EOLIAN static Eina_Value * -_efl_loop_begin(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) -{ - ecore_main_loop_begin(); - return &_ecore_exit_code; -} - -EOLIAN static void -_efl_loop_quit(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED, Eina_Value exit_code) -{ - ecore_main_loop_quit(); - _ecore_exit_code = exit_code; -} - -EAPI void -efl_exit(int exit_code) -{ - Eina_Value v = EINA_VALUE_EMPTY; - - eina_value_setup(&v, EINA_VALUE_TYPE_INT); - eina_value_set(&v, &exit_code); - efl_loop_quit(ecore_main_loop_get(), v); -} - -EOLIAN static Efl_Object * -_efl_loop_efl_object_provider_find(Eo *obj, Efl_Loop_Data *pd, const Efl_Object *klass) -{ - Efl_Object *r; - - if (klass == EFL_LOOP_CLASS) return obj; - - r = eina_hash_find(pd->providers, &klass); - if (r) return r; - - return efl_provider_find(efl_super(obj, EFL_LOOP_CLASS), klass); -} - -EAPI int -efl_loop_exit_code_process(Eina_Value *value) -{ - const Eina_Value_Type *t = eina_value_type_get(value); - int r = 0; - - if (t == EINA_VALUE_TYPE_UCHAR || - t == EINA_VALUE_TYPE_USHORT || - t == EINA_VALUE_TYPE_UINT || - t == EINA_VALUE_TYPE_ULONG || - t == EINA_VALUE_TYPE_UINT64 || - t == EINA_VALUE_TYPE_CHAR || - t == EINA_VALUE_TYPE_SHORT || - t == EINA_VALUE_TYPE_INT || - t == EINA_VALUE_TYPE_LONG || - t == EINA_VALUE_TYPE_INT64 || - t == EINA_VALUE_TYPE_FLOAT || - t == EINA_VALUE_TYPE_DOUBLE) - { - Eina_Value v = EINA_VALUE_EMPTY; - - eina_value_setup(&v, EINA_VALUE_TYPE_INT); - if (!eina_value_convert(&v, value)) - r = -1; - else - eina_value_get(&v, &v); - } - else - { - FILE *out = stdout; - char *msg; - - msg = eina_value_to_string(value); - - if (t == EINA_VALUE_TYPE_ERROR) - { - r = -1; - out = stderr; - } - - fprintf(out, "%s\n", msg); - } - - return r; -} - -static void -_poll_trigger(void *data, const Efl_Event *event) -{ - Eo *parent = efl_parent_get(event->object); - - efl_event_callback_call(parent, data, NULL); -} - -static void -_check_event_catcher_add(void *data, const Efl_Event *event) -{ - const Efl_Callback_Array_Item *array = event->info; - Efl_Loop_Data *pd = data; - int i; - - for (i = 0; array[i].desc != NULL; i++) - { - if (array[i].desc == EFL_LOOP_EVENT_IDLE) - { - ++pd->idlers; - } - // XXX: all the below are kind of bad. ecore_pollers were special. - // they all woke up at the SAME time based on interval, (all pollers - // of interval 1 woke up together, those with 2 woke up when 1 and - // 2 woke up, 4 woke up together along with 1 and 2 etc. - // the below means they will just go off whenever but at a pre - // defined interval - 1/60th, 6 and 66 seconds. not really great - // pollers probably should be less frequent that 1/60th even on poll - // high, medium probably down to 1-2 sec and low - yes maybe 30 or 60 - // sec... still - not timed to wake up together. :( - else if (array[i].desc == EFL_LOOP_EVENT_POLL_HIGH) - { - if (!pd->poll_high) - { - // Would be better to have it in sync with normal wake up - // of the main loop for better energy efficiency, I guess. - pd->poll_high = efl_add(EFL_LOOP_TIMER_CLASS, event->object, - efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TICK, _poll_trigger, EFL_LOOP_EVENT_POLL_HIGH), - efl_loop_timer_interval_set(efl_added, 1.0/60.0)); - } - ++pd->pollers.high; - } - else if (array[i].desc == EFL_LOOP_EVENT_POLL_MEDIUM) - { - if (!pd->poll_medium) - { - pd->poll_medium = efl_add(EFL_LOOP_TIMER_CLASS, event->object, - efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TICK, _poll_trigger, EFL_LOOP_EVENT_POLL_MEDIUM), - efl_loop_timer_interval_set(efl_added, 6)); - } - ++pd->pollers.medium; - } - else if (array[i].desc == EFL_LOOP_EVENT_POLL_LOW) - { - if (!pd->poll_low) - { - pd->poll_low = efl_add(EFL_LOOP_TIMER_CLASS, event->object, - efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TICK, _poll_trigger, EFL_LOOP_EVENT_POLL_LOW), - efl_loop_timer_interval_set(efl_added, 66)); - } - ++pd->pollers.low; - } - } -} - -static void -_check_event_catcher_del(void *data, const Efl_Event *event) -{ - const Efl_Callback_Array_Item *array = event->info; - Efl_Loop_Data *pd = data; - int i; - - for (i = 0; array[i].desc != NULL; i++) - { - if (array[i].desc == EFL_LOOP_EVENT_IDLE) - { - --pd->idlers; - } - else if (array[i].desc == EFL_LOOP_EVENT_POLL_HIGH) - { - --pd->pollers.high; - if (!pd->pollers.high) - { - efl_del(pd->poll_high); - pd->poll_high = NULL; - } - } - else if (array[i].desc == EFL_LOOP_EVENT_POLL_MEDIUM) - { - --pd->pollers.medium; - if (!pd->pollers.medium) - { - efl_del(pd->poll_medium); - pd->poll_medium = NULL; - } - } - else if (array[i].desc == EFL_LOOP_EVENT_POLL_LOW) - { - --pd->pollers.low; - if (!pd->pollers.low) - { - efl_del(pd->poll_low); - pd->poll_low = NULL; - } - } - } -} - -EFL_CALLBACKS_ARRAY_DEFINE(event_catcher_watch, - { EFL_EVENT_CALLBACK_ADD, _check_event_catcher_add }, - { EFL_EVENT_CALLBACK_DEL, _check_event_catcher_del }); - -EOLIAN static Efl_Object * -_efl_loop_efl_object_constructor(Eo *obj, Efl_Loop_Data *pd) -{ - obj = efl_constructor(efl_super(obj, EFL_LOOP_CLASS)); - if (!obj) return NULL; - - efl_event_callback_array_add(obj, event_catcher_watch(), pd); - - pd->providers = eina_hash_pointer_new(EINA_FREE_CB(efl_unref)); - - return obj; -} - -EOLIAN static void -_efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd) -{ - eina_hash_free(pd->providers); - - efl_del(pd->poll_low); - efl_del(pd->poll_medium); - efl_del(pd->poll_high); - - efl_destructor(efl_super(obj, EFL_LOOP_CLASS)); -} - -static void -_efl_loop_arguments_cleanup(Eina_Array *arga) -{ - Eina_Stringshare *s; - - while ((s = eina_array_pop(arga))) - eina_stringshare_del(s); - eina_array_free(arga); -} - -static Eina_Value -_efl_loop_arguments_send(void *data, const Eina_Value v, - const Eina_Future *dead EINA_UNUSED) -{ - static Eina_Bool initialization = EINA_TRUE; - Efl_Loop_Arguments arge; - Eina_Array *arga = data; - - if (v.type == EINA_VALUE_TYPE_ERROR) - goto on_error; - - arge.argv = arga; - arge.initialization = initialization; - initialization = EINA_FALSE; - - efl_event_callback_call(ecore_main_loop_get(), EFL_LOOP_EVENT_ARGUMENTS, &arge); - - on_error: - _efl_loop_arguments_cleanup(arga); - - return v; -} - -// It doesn't make sense to send those argument to any other mainloop -// As it also doesn't make sense to allow anyone to override this, so -// should be internal for sure, not even protected. -EAPI void -ecore_loop_arguments_send(int argc, const char **argv) -{ - Eina_Future *job; - Eina_Array *arga; - int i = 0; - - arga = eina_array_new(argc); - for (i = 0; i < argc; i++) - eina_array_push(arga, eina_stringshare_add(argv[i])); - - job = eina_future_then(efl_loop_job(ecore_main_loop_get()), - _efl_loop_arguments_send, arga); - efl_future_Eina_FutureXXX_then(ecore_main_loop_get(), job); -} - -// Only one main loop handle for now -void -ecore_loop_future_register(Efl_Loop *l EINA_UNUSED, Efl_Future *f) -{ - _pending_futures = eina_list_append(_pending_futures, f); -} - -void -ecore_loop_future_unregister(Efl_Loop *l EINA_UNUSED, Efl_Future *f) -{ - _pending_futures = eina_list_remove(_pending_futures, f); -} - -void -ecore_loop_promise_register(Efl_Loop *l EINA_UNUSED, Efl_Promise *p) -{ - _pending_promises = eina_list_append(_pending_promises, p); -} - -void -ecore_loop_promise_unregister(Efl_Loop *l EINA_UNUSED, Efl_Promise *p) -{ - _pending_promises = eina_list_remove(_pending_promises, p); -} - -static Eina_Future * -_efl_loop_job(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED) -{ - // 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)); -} - -static void -_efl_loop_idle_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED) -{ - Efl_Loop_Promise_Simple_Data *d = data; - ecore_idler_del(d->idler); - efl_loop_promise_simple_data_mp_free(d); -} - -static Eina_Bool -_efl_loop_idle_done(void *data) -{ - Efl_Loop_Promise_Simple_Data *d = data; - eina_promise_resolve(d->promise, EINA_VALUE_EMPTY); - efl_loop_promise_simple_data_mp_free(d); - return EINA_FALSE; -} - -static Eina_Future * -_efl_loop_idle(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED) -{ - Efl_Loop_Promise_Simple_Data *d; - Eina_Promise *p; - - d = efl_loop_promise_simple_data_calloc(1); - EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL); - - 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); - // d is dead if p is NULL - EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL); - d->promise = p; - - // NOTE: Eolian should do efl_future_then() to bind future to object. - return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p)); - - idler_error: - efl_loop_promise_simple_data_mp_free(d); - return NULL; -} - -static void -_efl_loop_timeout_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED) -{ - Efl_Loop_Promise_Simple_Data *d = data; - ecore_timer_del(d->timer); - efl_loop_promise_simple_data_mp_free(d); -} - -static Eina_Bool -_efl_loop_timeout_done(void *data) -{ - Efl_Loop_Promise_Simple_Data *d = data; - eina_promise_resolve(d->promise, EINA_VALUE_EMPTY); - efl_loop_promise_simple_data_mp_free(d); - return EINA_FALSE; -} - -static Eina_Future * -_efl_loop_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, double time) -{ - Efl_Loop_Promise_Simple_Data *d; - Eina_Promise *p; - - d = efl_loop_promise_simple_data_calloc(1); - EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL); - - d->timer = ecore_timer_add(time, _efl_loop_timeout_done, 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); - // d is dead if p is NULL - EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL); - d->promise = p; - - // NOTE: Eolian should do efl_future_then() to bind future to object. - return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p)); - - timer_error: - efl_loop_promise_simple_data_mp_free(d); - return NULL; -} - -static Eina_Bool -_efl_loop_register(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, const Efl_Class *klass, const Efl_Object *provider) -{ - // The passed object does not provide that said class. - if (!efl_isa(provider, klass)) return EINA_FALSE; - - // Note: I would prefer to use efl_xref here, but I can't figure a nice way to - // call efl_xunref on hash destruction. - return eina_hash_add(pd->providers, &klass, efl_ref(provider)); -} - -static Eina_Bool -_efl_loop_unregister(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, const Efl_Class *klass, const Efl_Object *provider) -{ - return eina_hash_del(pd->providers, &klass, provider); -} - -Efl_Version _app_efl_version = { 0, 0, 0, 0, NULL, NULL }; - -EWAPI void -efl_build_version_set(int vmaj, int vmin, int vmic, int revision, - const char *flavor, const char *build_id) -{ - // note: EFL has not been initialized yet at this point (ie. no eina call) - _app_efl_version.major = vmaj; - _app_efl_version.minor = vmin; - _app_efl_version.micro = vmic; - _app_efl_version.revision = revision; - free((char *) _app_efl_version.flavor); - free((char *) _app_efl_version.build_id); - _app_efl_version.flavor = flavor ? strdup(flavor) : NULL; - _app_efl_version.build_id = build_id ? strdup(build_id) : NULL; -} - -EOLIAN static const Efl_Version * -_efl_loop_app_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) -{ - return &_app_efl_version; -} - -EOLIAN static const Efl_Version * -_efl_loop_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) -{ - /* vanilla EFL: flavor = NULL */ - static const Efl_Version version = { - .major = VMAJ, - .minor = VMIN, - .micro = VMIC, - .revision = VREV, - .build_id = EFL_BUILD_ID, - .flavor = NULL - }; - - return &version; -} - -EAPI Eina_Future_Scheduler * -efl_loop_future_scheduler_get(Eo *obj) -{ - if (!obj) return NULL; - - if (efl_isa(obj, EFL_LOOP_CLASS)) - return _ecore_event_future_scheduler_get(); - - return efl_loop_future_scheduler_get(efl_loop_get(obj)); -} - -#include "efl_loop.eo.c" diff --git a/src/lib/ecore/ecore_main_common.h b/src/lib/ecore/ecore_main_common.h new file mode 100644 index 0000000000..f015549877 --- /dev/null +++ b/src/lib/ecore/ecore_main_common.h @@ -0,0 +1,96 @@ +////////////////////////////////////////////////////////////////////////// +#if defined(HAVE_SYS_EPOLL_H) +# define HAVE_EPOLL 1 +# include +#else + +# define HAVE_EPOLL 0 +# define EPOLLIN 1 +# define EPOLLPRI 2 +# define EPOLLOUT 4 +# define EPOLLERR 8 + +# define EPOLL_CTL_ADD 1 +# define EPOLL_CTL_DEL 2 +# define EPOLL_CTL_MOD 3 + +typedef union epoll_data +{ + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; +} epoll_data_t; + +struct epoll_event +{ + uint32_t events; + epoll_data_t data; +}; + +static inline int +epoll_create(int size EINA_UNUSED) +{ + return -1; +} + +static inline int +epoll_wait(int epfd EINA_UNUSED, + struct epoll_event *events EINA_UNUSED, + int maxevents EINA_UNUSED, + int timeout EINA_UNUSED) +{ + return -1; +} + +static inline int +epoll_ctl(int epfd EINA_UNUSED, + int op EINA_UNUSED, + int fd EINA_UNUSED, + struct epoll_event *event EINA_UNUSED) +{ + return -1; +} +#endif + +////////////////////////////////////////////////////////////////////////// +#ifdef HAVE_SYS_TIMERFD_H +# include +#else +/* fallback code if we don't have real timerfd - reduces number of ifdefs */ +# ifndef CLOCK_MONOTONIC +# define CLOCK_MONOTONIC 0 /* bogus value */ +# endif +# ifndef TFD_NONBLOCK +# define TFD_NONBLOCK 0 /* bogus value */ +# endif +#endif /* HAVE_SYS_TIMERFD_H */ + +#ifndef TFD_TIMER_ABSTIME +# define TFD_TIMER_ABSTIME (1 << 0) +#endif +#ifndef TFD_TIMER_CANCEL_ON_SET +# define TFD_TIMER_CANCEL_ON_SET (1 << 1) +#endif + +#ifndef TIME_T_MAX +# define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1) +#endif + +#ifndef HAVE_TIMERFD_CREATE +static inline int +timerfd_create(int clockid EINA_UNUSED, + int flags EINA_UNUSED) +{ + return -1; +} + +static inline int +timerfd_settime(int fd EINA_UNUSED, + int flags EINA_UNUSED, + const struct itimerspec *new_value EINA_UNUSED, + struct itimerspec *old_value EINA_UNUSED) +{ + return -1; +} +#endif /* HAVE_TIMERFD_CREATE */ diff --git a/src/lib/ecore/ecore_main_timechanges.c b/src/lib/ecore/ecore_main_timechanges.c new file mode 100644 index 0000000000..b0f6d33b7c --- /dev/null +++ b/src/lib/ecore/ecore_main_timechanges.c @@ -0,0 +1,88 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Ecore.h" +#include "ecore_private.h" +#include "lib/ecore/ecore_main_common.h" + +#ifdef HAVE_SYS_TIMERFD_H + +static Eo *realtime_obj = NULL; + +static void +_cb_read(void *data EINA_UNUSED, const Efl_Event *event) +{ + Eo *loop = efl_provider_find(event->object, EFL_LOOP_CLASS); + int fd = efl_loop_handler_fd_get(event->object); + char buf[8]; + + if (read(fd, buf, sizeof(buf)) >= 0) return; + DBG("system clock changed"); + // XXX: ecore event needs to be eo loop api's + ecore_event_add(ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED, NULL, NULL, NULL); + _ecore_main_timechanges_stop(loop); + _ecore_main_timechanges_start(loop); +} + +static void +_cb_del(void *data EINA_UNUSED, const Efl_Event *event) +{ + int fd = efl_loop_handler_fd_get(event->object); + if (event->object == realtime_obj) realtime_obj = NULL; + close(fd); +} + +EFL_CALLBACKS_ARRAY_DEFINE(_event_watch, + { EFL_LOOP_HANDLER_EVENT_READ, _cb_read }, + { EFL_EVENT_DEL, _cb_del }); +#endif + +void +_ecore_main_timechanges_start(Eo *obj) +{ +#ifdef HAVE_SYS_TIMERFD_H + struct itimerspec its; + int fd; + + if (realtime_obj) return; + + fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC); + if (fd < 0) return; + + memset(&its, 0, sizeof(its)); + its.it_value.tv_sec = TIME_T_MAX; // end of time - 0xf + if (timerfd_settime(fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, + &its, NULL) < 0) + { + WRN("Couldn't arm timerfd to detect clock changes: %s", strerror(errno)); + close(fd); + return; + } + realtime_obj = + efl_add(EFL_LOOP_HANDLER_CLASS, obj, + efl_loop_handler_fd_set(efl_added, fd), + efl_loop_handler_active_set(efl_added, ECORE_FD_READ), + efl_event_callback_array_add(efl_added, _event_watch(), NULL)); +#endif +} + +void +_ecore_main_timechanges_stop(Eo *obj EINA_UNUSED) +{ +#ifdef HAVE_SYS_TIMERFD_H + if (!realtime_obj) return; + efl_del(realtime_obj); + realtime_obj = NULL; +#endif +} diff --git a/src/lib/ecore/ecore_pipe.c b/src/lib/ecore/ecore_pipe.c index d85d0bf54f..c8fbb87ae4 100644 --- a/src/lib/ecore/ecore_pipe.c +++ b/src/lib/ecore/ecore_pipe.c @@ -56,16 +56,12 @@ #define PIPE_FD_INVALID -1 #ifdef _WIN32 - # include - # define pipe_write(fd, buffer, size) send((fd), (char *)(buffer), size, 0) # define pipe_read(fd, buffer, size) recv((fd), (char *)(buffer), size, 0) # define pipe_close(fd) closesocket(fd) # define PIPE_FD_ERROR SOCKET_ERROR - #else - # ifdef HAVE_SYS_EPOLL_H # include # endif /* HAVE_SYS_EPOLL_H */ @@ -74,23 +70,21 @@ # endif # include # include - # define pipe_write(fd, buffer, size) write((fd), buffer, size) # define pipe_read(fd, buffer, size) read((fd), buffer, size) # define pipe_close(fd) close(fd) # define PIPE_FD_ERROR -1 - #endif /* ! _WIN32 */ #include "Ecore.h" #include "ecore_private.h" -/* How of then we should retry to write to the pipe */ +// How of then we should retry to write to the pipe #define ECORE_PIPE_WRITE_RETRY 6 struct _Ecore_Pipe { - ECORE_MAGIC; + ECORE_MAGIC; int fd_read; int fd_write; Ecore_Fd_Handler *fd_handler; @@ -116,11 +110,7 @@ EAPI Ecore_Pipe * ecore_pipe_add(Ecore_Pipe_Cb handler, const void *data) { - Ecore_Pipe *p; - - p = _ecore_pipe_add(handler, data); - - return p; + return _ecore_pipe_add(handler, data); } EAPI void * @@ -138,11 +128,11 @@ ecore_pipe_read_close(Ecore_Pipe *p) if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE)) { ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read_close"); - return ; + return; } if (p->fd_handler) { - _ecore_main_fd_handler_del(p->fd_handler); + _ecore_main_fd_handler_del(ML_OBJ, ML_DAT, p->fd_handler); p->fd_handler = NULL; } if (p->fd_read != PIPE_FD_INVALID) @@ -166,11 +156,11 @@ ecore_pipe_freeze(Ecore_Pipe *p) if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE)) { ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read_freeze"); - return ; + return; } if (p->fd_handler) { - _ecore_main_fd_handler_del(p->fd_handler); + _ecore_main_fd_handler_del(ML_OBJ, ML_DAT, p->fd_handler); p->fd_handler = NULL; } } @@ -182,16 +172,12 @@ ecore_pipe_thaw(Ecore_Pipe *p) if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE)) { ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read_thaw"); - return ; - } - if (!p->fd_handler && p->fd_read != PIPE_FD_INVALID) - { - p->fd_handler = ecore_main_fd_handler_add(p->fd_read, - ECORE_FD_READ, - _ecore_pipe_read, - p, - NULL, NULL); + return; } + if ((!p->fd_handler) && (p->fd_read != PIPE_FD_INVALID)) + p->fd_handler = ecore_main_fd_handler_add(p->fd_read, ECORE_FD_READ, + _ecore_pipe_read, p, + NULL, NULL); } EAPI int @@ -208,7 +194,7 @@ ecore_pipe_write_close(Ecore_Pipe *p) if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE)) { ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_write_close"); - return ; + return; } if (p->fd_write != PIPE_FD_INVALID) { @@ -244,8 +230,7 @@ ecore_pipe_write(Ecore_Pipe *p, if (p->fd_write == PIPE_FD_INVALID) goto out; - /* First write the len into the pipe */ - do + do // First write the len into the pipe { ret = pipe_write(p->fd_write, &nbytes, sizeof(nbytes)); if (ret == sizeof(nbytes)) @@ -255,19 +240,19 @@ ecore_pipe_write(Ecore_Pipe *p, } else if (ret > 0) { - /* XXX What should we do here? */ - ERR("The length of the data was not written complete" - " to the pipe"); - goto out; + // XXX What should we do here? + ERR("The length of the data was not written complete" + " to the pipe"); + goto out; } - else if (ret == PIPE_FD_ERROR && errno == EPIPE) + else if ((ret == PIPE_FD_ERROR) && (errno == EPIPE)) { pipe_close(p->fd_write); p->fd_write = PIPE_FD_INVALID; goto out; } - else if (ret == PIPE_FD_ERROR && errno == EINTR) - /* try it again */ + else if ((ret == PIPE_FD_ERROR) && (errno == EINTR)) + // try it again ; else { @@ -280,8 +265,7 @@ ecore_pipe_write(Ecore_Pipe *p, if (retry != ECORE_PIPE_WRITE_RETRY) goto out; - /* and now pass the data to the pipe */ - do + do // and now pass the data to the pipe { ret = pipe_write(p->fd_write, ((unsigned char *)buffer) + already_written, @@ -289,22 +273,22 @@ ecore_pipe_write(Ecore_Pipe *p, if (ret == (ssize_t)(nbytes - already_written)) { - ok = EINA_TRUE; - goto out; + ok = EINA_TRUE; + goto out; } else if (ret >= 0) { already_written -= ret; continue; } - else if (ret == PIPE_FD_ERROR && errno == EPIPE) + else if ((ret == PIPE_FD_ERROR) && (errno == EPIPE)) { pipe_close(p->fd_write); p->fd_write = PIPE_FD_INVALID; goto out; } - else if (ret == PIPE_FD_ERROR && errno == EINTR) - /* try it again */ + else if ((ret == PIPE_FD_ERROR) && (errno == EINTR)) + // try it again ; else { @@ -336,8 +320,7 @@ ecore_pipe_full_add(Ecore_Pipe_Cb handler, p = ecore_pipe_calloc(1); if (!p) return NULL; - if (fd_read == -1 && - fd_write == -1) + if ((fd_read == -1) && (fd_write == -1)) { if (pipe(fds)) { @@ -349,8 +332,8 @@ ecore_pipe_full_add(Ecore_Pipe_Cb handler, } else { - fd_read = fd_read == -1 ? PIPE_FD_INVALID : fd_read; - fd_write = fd_write == -1 ? PIPE_FD_INVALID : fd_write; + fd_read = (fd_read == -1) ? PIPE_FD_INVALID : fd_read; + fd_write = (fd_write == -1) ? PIPE_FD_INVALID : fd_write; } ECORE_MAGIC_SET(p, ECORE_MAGIC_PIPE); @@ -359,10 +342,8 @@ ecore_pipe_full_add(Ecore_Pipe_Cb handler, p->handler = handler; p->data = data; - if (!read_survive_fork) - eina_file_close_on_exec(fd_read, EINA_TRUE); - if (!write_survive_fork) - eina_file_close_on_exec(fd_write, EINA_TRUE); + if (!read_survive_fork) eina_file_close_on_exec(fd_read, EINA_TRUE); + if (!write_survive_fork) eina_file_close_on_exec(fd_write, EINA_TRUE); #if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_SYS_TIMERFD_H) struct epoll_event pollev = { 0 }; @@ -381,23 +362,17 @@ ecore_pipe_full_add(Ecore_Pipe_Cb handler, if (fcntl(p->fd_read, F_SETFL, O_NONBLOCK) < 0) ERR("can't set pipe to NONBLOCK"); - p->fd_handler = ecore_main_fd_handler_add(p->fd_read, - ECORE_FD_READ, - _ecore_pipe_read, - p, - NULL, NULL); - + p->fd_handler = ecore_main_fd_handler_add(p->fd_read, ECORE_FD_READ, + _ecore_pipe_read, p, NULL, NULL); return p; } -/* Private functions */ +// Private functions Ecore_Pipe * _ecore_pipe_add(Ecore_Pipe_Cb handler, const void *data) { - return ecore_pipe_full_add(handler, data, - -1, -1, - EINA_FALSE, EINA_FALSE); + return ecore_pipe_full_add(handler, data, -1, -1, EINA_FALSE, EINA_FALSE); } void * @@ -420,7 +395,8 @@ _ecore_pipe_del(Ecore_Pipe *p) #endif p->delete_me = EINA_TRUE; if (p->handling > 0) return (void *)p->data; - if (p->fd_handler) _ecore_main_fd_handler_del(p->fd_handler); + if (p->fd_handler) _ecore_main_fd_handler_del(ML_OBJ, ML_DAT, + p->fd_handler); if (p->fd_read != PIPE_FD_INVALID) pipe_close(p->fd_read); if (p->fd_write != PIPE_FD_INVALID) pipe_close(p->fd_write); p->fd_handler = NULL; @@ -435,10 +411,7 @@ static void _ecore_pipe_unhandle(Ecore_Pipe *p) { p->handling--; - if (p->delete_me) - { - _ecore_pipe_del(p); - } + if (p->delete_me) _ecore_pipe_del(p); } #if ! defined(HAVE_SYS_EPOLL_H) || ! defined(HAVE_SYS_TIMERFD_H) @@ -455,23 +428,21 @@ _ecore_pipe_wait(Ecore_Pipe *p, int total = 0; EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1); - if (p->fd_read == PIPE_FD_INVALID) - return -1; + if (p->fd_read == PIPE_FD_INVALID) return -1; FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&exset); FD_SET(p->fd_read, &rset); - if (wait >= 0.0) - end = ecore_time_get() + wait; + if (wait >= 0.0) end = ecore_time_get() + wait; timeout = wait; - while (message_count > 0 && (timeout > 0.0 || wait <= 0.0)) + while ((message_count > 0) && ((timeout > 0.0) || (wait <= 0.0))) { if (wait >= 0.0) { - /* finite() tests for NaN, too big, too small, and infinity. */ + // finite() tests for NaN, too big, too small, and infinity. if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0))) { tv.tv_sec = 0; @@ -490,10 +461,7 @@ _ecore_pipe_wait(Ecore_Pipe *p, } t = &tv; } - else - { - t = NULL; - } + else t = NULL; ret = main_loop_select(p->fd_read + 1, &rset, &wset, &exset, t); @@ -506,10 +474,7 @@ _ecore_pipe_wait(Ecore_Pipe *p, p->message = 0; _ecore_pipe_unhandle(p); } - else if (ret == 0) - { - break; - } + else if (ret == 0) break; else if (errno != EINTR) { if (p->fd_read != PIPE_FD_INVALID) @@ -520,8 +485,7 @@ _ecore_pipe_wait(Ecore_Pipe *p, break; } - if (wait >= 0.0) - timeout = end - ecore_time_get(); + if (wait >= 0.0) timeout = end - ecore_time_get(); } return total; @@ -538,18 +502,17 @@ _ecore_pipe_wait(Ecore_Pipe *p, double timeout; int ret; int total = 0; - int time_exit=-1; + int time_exit = -1; Eina_Bool fd_read_found; Eina_Bool fd_timer_found; struct itimerspec tspec_new; EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1); - if (p->fd_read == PIPE_FD_INVALID) - return -1; + if (p->fd_read == PIPE_FD_INVALID) return -1; timeout = wait; int sec, usec; - if ( wait >= 0.0) + if (wait >= 0.0) { if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0))) { @@ -571,45 +534,45 @@ _ecore_pipe_wait(Ecore_Pipe *p, tspec_new.it_interval.tv_sec = 0; tspec_new.it_interval.tv_nsec = 0; timerfd_settime(p->timerfd, 0, &tspec_new, NULL); - } + } } while ((ret = epoll_wait(p->pollfd, pollincoming, 2, time_exit)) > 0) { - fd_read_found = EINA_FALSE; - fd_timer_found = EINA_FALSE; + fd_read_found = EINA_FALSE; + fd_timer_found = EINA_FALSE; - for (int i = 0; i < ret;i++) - { - if ((&p->fd_read == pollincoming[i].data.ptr)) - fd_read_found = EINA_TRUE; - if ((&p->timerfd == pollincoming[i].data.ptr)) - fd_timer_found = EINA_TRUE; - } + for (int i = 0; i < ret;i++) + { + if ((&p->fd_read == pollincoming[i].data.ptr)) + fd_read_found = EINA_TRUE; + if ((&p->timerfd == pollincoming[i].data.ptr)) + fd_timer_found = EINA_TRUE; + } - p->handling++; - if (fd_read_found) - { - _ecore_pipe_read(p, NULL); - message_count -= p->message; - total += p->message; - p->message = 0; - if (message_count <= 0) - { - _ecore_pipe_unhandle(p); - break; - } - } + p->handling++; + if (fd_read_found) + { + _ecore_pipe_read(p, NULL); + message_count -= p->message; + total += p->message; + p->message = 0; + if (message_count <= 0) + { + _ecore_pipe_unhandle(p); + break; + } + } - if ((fd_timer_found) && (p->timerfd != PIPE_FD_INVALID)) - { - if (pipe_read(p->timerfd, &timerfdbuf, sizeof(timerfdbuf)) - < (int)sizeof(int64_t)) - WRN("Could not read timerfd data"); - _ecore_pipe_unhandle(p); - break; - } - _ecore_pipe_unhandle(p); + if ((fd_timer_found) && (p->timerfd != PIPE_FD_INVALID)) + { + if (pipe_read(p->timerfd, &timerfdbuf, sizeof(timerfdbuf)) < + (int)sizeof(int64_t)) + WRN("Could not read timerfd data"); + _ecore_pipe_unhandle(p); + break; + } + _ecore_pipe_unhandle(p); } if (ret < 0) { @@ -623,7 +586,6 @@ _ecore_pipe_wait(Ecore_Pipe *p, WRN("The call was interrupted by a signal handler before any of the requested epoll_event " "occurred or the timeout expired; see signal(7)."); } - return total; } @@ -641,10 +603,7 @@ _ecore_pipe_handler_call(Ecore_Pipe *p, p->len = 0; p->message++; - if (!p->delete_me) - { - p->handler(data, buf, len); - } + if (!p->delete_me) p->handler(data, buf, len); // free p->passed_data free(buf); @@ -662,64 +621,63 @@ _ecore_pipe_read(void *data, { ssize_t ret; - /* if we already have read some data we don't need to read the len - * but to finish the already started job - */ + // if we already have read some data we don't need to read the len + // but to finish the already started job if (p->len == 0) { - /* read the len of the passed data */ - ret = pipe_read(p->fd_read, &p->len, sizeof(p->len)); + // read the len of the passed data + ret = pipe_read(p->fd_read, &p->len, sizeof(p->len)); - /* catch the non error case first */ - /* read amount ok - nothing more to do */ - if (ret == sizeof(p->len)) - ; - else if (ret > 0) - { - /* we got more data than we asked for - definite error */ - ERR("Only read %i bytes from the pipe, although" - " we need to read %i bytes.", - (int)ret, (int)sizeof(p->len)); - _ecore_pipe_unhandle(p); - return ECORE_CALLBACK_CANCEL; - } - else if (ret == 0) - { - /* we got no data */ - if (i == 0) - { - /* no data on first try through means an error */ - _ecore_pipe_handler_call(p, NULL, 0); - pipe_close(p->fd_read); - p->fd_read = PIPE_FD_INVALID; - p->fd_handler = NULL; - _ecore_pipe_unhandle(p); - return ECORE_CALLBACK_CANCEL; - } - else - { - /* no data after first loop try is ok */ - _ecore_pipe_unhandle(p); - return ECORE_CALLBACK_RENEW; - } - } + // catch the non error case first + // read amount ok - nothing more to do + if (ret == sizeof(p->len)) + ; + else if (ret > 0) + { + // we got more data than we asked for - definite error + ERR("Only read %i bytes from the pipe, although" + " we need to read %i bytes.", + (int)ret, (int)sizeof(p->len)); + _ecore_pipe_unhandle(p); + return ECORE_CALLBACK_CANCEL; + } + else if (ret == 0) + { + // we got no data + if (i == 0) + { + // no data on first try through means an error + _ecore_pipe_handler_call(p, NULL, 0); + pipe_close(p->fd_read); + p->fd_read = PIPE_FD_INVALID; + p->fd_handler = NULL; + _ecore_pipe_unhandle(p); + return ECORE_CALLBACK_CANCEL; + } + else + { + // no data after first loop try is ok + _ecore_pipe_unhandle(p); + return ECORE_CALLBACK_RENEW; + } + } #ifndef _WIN32 - else if ((ret == PIPE_FD_ERROR) && - ((errno == EINTR) || (errno == EAGAIN))) + else if ((ret == PIPE_FD_ERROR) && + ((errno == EINTR) || (errno == EAGAIN))) { - _ecore_pipe_unhandle(p); - return ECORE_CALLBACK_RENEW; - } - else - { - ERR("An unhandled error (ret: %i errno: %i [%s])" - "occurred while reading from the pipe the length", - (int)ret, errno, strerror(errno)); - _ecore_pipe_unhandle(p); + _ecore_pipe_unhandle(p); return ECORE_CALLBACK_RENEW; } + else + { + ERR("An unhandled error (ret: %i errno: %i [%s])" + "occurred while reading from the pipe the length", + (int)ret, errno, strerror(errno)); + _ecore_pipe_unhandle(p); + return ECORE_CALLBACK_RENEW; + } #else - else /* ret == PIPE_FD_ERROR is the only other case on Windows */ + else // ret == PIPE_FD_ERROR is the only other case on Windows { if (WSAGetLastError() != WSAEWOULDBLOCK) { @@ -733,10 +691,9 @@ _ecore_pipe_read(void *data, } #endif } - - /* if somehow we got less than or equal to 0 we got an errnoneous - * messages so call callback with null and len we got. this case should - * never happen */ + // if somehow we got less than or equal to 0 we got an errnoneous + // messages so call callback with null and len we got. this case should + // never happen if (p->len == 0) { _ecore_pipe_handler_call(p, NULL, 0); @@ -744,15 +701,15 @@ _ecore_pipe_read(void *data, return ECORE_CALLBACK_RENEW; } - /* we dont have a buffer to hold the data, so alloc it */ + // we dont have a buffer to hold the data, so alloc it if (!p->passed_data) { p->passed_data = malloc(p->len); - /* alloc failed - error case */ + // alloc failed - error case if (!p->passed_data) { _ecore_pipe_handler_call(p, NULL, 0); - /* close the pipe */ + // close the pipe pipe_close(p->fd_read); p->fd_read = PIPE_FD_INVALID; p->fd_handler = NULL; @@ -761,27 +718,27 @@ _ecore_pipe_read(void *data, } } - /* and read the passed data */ + // and read the passed data ret = pipe_read(p->fd_read, ((unsigned char *)p->passed_data) + p->already_read, p->len - p->already_read); - /* catch the non error case first */ - /* if we read enough data to finish the message/buffer */ + // catch the non error case first + // if we read enough data to finish the message/buffer if (ret == (ssize_t)(p->len - p->already_read)) _ecore_pipe_handler_call(p, p->passed_data, p->len); else if (ret > 0) { - /* more data left to read */ - p->already_read += (unsigned int) ret; - _ecore_pipe_unhandle(p); - return ECORE_CALLBACK_RENEW; + // more data left to read + p->already_read += (unsigned int)ret; + _ecore_pipe_unhandle(p); + return ECORE_CALLBACK_RENEW; } else if (ret == 0) { - /* 0 bytes to read - could be more to read next select wake up */ - _ecore_pipe_unhandle(p); - return ECORE_CALLBACK_RENEW; + // 0 bytes to read - could be more to read next select wake up + _ecore_pipe_unhandle(p); + return ECORE_CALLBACK_RENEW; } #ifndef _WIN32 else if ((ret == PIPE_FD_ERROR) && @@ -799,7 +756,7 @@ _ecore_pipe_read(void *data, return ECORE_CALLBACK_RENEW; } #else - else /* ret == PIPE_FD_ERROR is the only other case on Windows */ + else // ret == PIPE_FD_ERROR is the only other case on Windows { if (WSAGetLastError() != WSAEWOULDBLOCK) { @@ -810,8 +767,7 @@ _ecore_pipe_read(void *data, _ecore_pipe_unhandle(p); return ECORE_CALLBACK_CANCEL; } - else - break; + else break; } #endif } diff --git a/src/lib/ecore/ecore_private.h b/src/lib/ecore/ecore_private.h index 366c169943..d9a44ce989 100644 --- a/src/lib/ecore/ecore_private.h +++ b/src/lib/ecore/ecore_private.h @@ -83,22 +83,84 @@ 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_Data Efl_Loop_Data; + +typedef struct _Message_Handler Message_Handler; +typedef struct _Message Message; + +struct _Message_Handler +{ + Eo *handler; + const Eo *klass; +}; + +struct _Message +{ + EINA_INLIST; + Eo *handler; + Eo *message; + Eina_Bool delete_me; +}; + struct _Efl_Loop_Data { - Eina_Hash *providers; + double loop_time; + Eina_Hash *providers; - Ecore_Timer *poll_high; - Ecore_Timer *poll_medium; - Ecore_Timer *poll_low; + Ecore_Timer *poll_high; + Ecore_Timer *poll_medium; + Ecore_Timer *poll_low; - int idlers; + Eina_List *exes; // only used in main loop (for now?) + + Eina_List *fd_handlers_obj; + + Ecore_Fd_Handler *fd_handlers; + Eina_List *fd_handlers_with_prep; + Eina_List *file_fd_handlers; + Eina_List *fd_handlers_with_buffer; + Eina_List *fd_handlers_to_delete; + Ecore_Fd_Handler *fd_handlers_to_call; + Ecore_Fd_Handler *fd_handlers_to_call_current; + +# ifdef _WIN32 + Ecore_Win32_Handler *win32_handlers; + Ecore_Win32_Handler *win32_handler_current; + Eina_List *win32_handlers_to_delete; +# endif + + Eina_List *pending_futures; + Eina_List *pending_promises; + + Eina_Inarray *message_handlers; + Eina_Inlist *message_queue; + unsigned int message_walking; + + unsigned int throttle; + + int epoll_fd; + pid_t epoll_pid; + int timer_fd; + + double last_check; + Eina_Inlist *timers; + Eina_Inlist *suspended; + Efl_Loop_Timer_Data *timer_current; + int timers_added; + + Eina_Value exit_code; + + int idlers; + int in_loop; struct { - int high; - int medium; - int low; + int high; + int medium; + int low; } pollers; + + Eina_Bool do_quit; }; #define EVAS_FRAME_QUEUING 1 /* for test */ @@ -167,13 +229,11 @@ EAPI void _ecore_magic_fail(const void *d, void _ecore_time_init(void); void *_efl_loop_timer_del(Ecore_Timer *timer); -void _efl_loop_timer_shutdown(void); -void _efl_loop_timer_enable_new(void); -double _efl_loop_timer_next_get(void); -void _efl_loop_timer_expired_timers_call(double when); -int _efl_loop_timers_exists(void); - -int _efl_loop_timer_expired_call(double when); +void _efl_loop_timer_enable_new(Eo *obj, Efl_Loop_Data *pd); +double _efl_loop_timer_next_get(Eo *obj, Efl_Loop_Data *pd); +void _efl_loop_timer_expired_timers_call(Eo *obj, Efl_Loop_Data *pd, double when); +int _efl_loop_timers_exists(Eo *obj, Efl_Loop_Data *pd); +int _efl_loop_timer_expired_call(Eo *obj, Efl_Loop_Data *pd, double when); Ecore_Factorized_Idle *_ecore_factorized_idle_add(const Efl_Callback_Array_Item*desc, Ecore_Task_Cb func, @@ -200,7 +260,6 @@ Ecore_Event *_ecore_event_add(int type, Ecore_End_Cb func_free, void *data); void _ecore_event_call(void); -void *_ecore_event_handler_del(Ecore_Event_Handler *event_handler); Ecore_Timer *_ecore_exe_doomsday_clock_get(Ecore_Exe *exe); void _ecore_exe_doomsday_clock_set(Ecore_Exe *exe, @@ -219,16 +278,32 @@ int _ecore_pipe_wait(Ecore_Pipe *p, double wait); void *_ecore_pipe_del(Ecore_Pipe *p); -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, - Eina_Bool is_file); -void *_ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler); +Ecore_Fd_Handler *_ecore_main_fd_handler_add(Eo *obj, + Efl_Loop_Data *pd, + Eo *handler, + int fd, + Ecore_Fd_Handler_Flags flags, + Ecore_Fd_Cb func, + const void *data, + Ecore_Fd_Cb buf_func, + const void *buf_data, + Eina_Bool is_file); +void *_ecore_main_fd_handler_del(Eo *obj, + Efl_Loop_Data *pd, + Ecore_Fd_Handler *fd_handler); +Ecore_Win32_Handler * +_ecore_main_win32_handler_add(Eo *obj, + Efl_Loop_Data *pd, + Eo *handler, + void *h, + Ecore_Win32_Handle_Cb func, + const void *data); +void * +_ecore_main_win32_handler_del(Eo *obj, + Efl_Loop_Data *pd, + Ecore_Win32_Handler *win32_handler); +void _ecore_main_content_clear(Efl_Loop_Data *pd); void _ecore_main_shutdown(void); #if defined (_WIN32) || defined (__lv2ppu__) || defined (HAVE_EXOTIC) @@ -236,18 +311,18 @@ static inline void _ecore_signal_shutdown(void) { } static inline void _ecore_signal_init(void) { } -static inline void _ecore_signal_received_process(void) { } +static inline void _ecore_signal_received_process(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) { } -static inline int _ecore_signal_count_get(void) { return 0; } +static inline int _ecore_signal_count_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) { return 0; } -static inline void _ecore_signal_call(void) { } +static inline void _ecore_signal_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) { } #else void _ecore_signal_shutdown(void); void _ecore_signal_init(void); -void _ecore_signal_received_process(void); -int _ecore_signal_count_get(void); -void _ecore_signal_call(void); +void _ecore_signal_received_process(Eo *obj, Efl_Loop_Data *pd); +int _ecore_signal_count_get(Eo *obj, Efl_Loop_Data *pd); +void _ecore_signal_call(Eo *obj, Efl_Loop_Data *pd); #endif void _ecore_exe_init(void); @@ -283,6 +358,11 @@ void _ecore_job_shutdown(void); void _ecore_main_loop_init(void); void _ecore_main_loop_shutdown(void); +void _ecore_main_loop_iterate(Eo *obj, Efl_Loop_Data *pd); +int _ecore_main_loop_iterate_may_block(Eo *obj, Efl_Loop_Data *pd, int may_block); +void _ecore_main_loop_begin(Eo *obj, Efl_Loop_Data *pd); +void _ecore_main_loop_quit(Eo *obj, Efl_Loop_Data *pd); + void _ecore_coroutine_init(void); void _ecore_coroutine_shutdown(void); @@ -290,6 +370,17 @@ void _ecore_throttle(void); void _ecore_main_call_flush(void); +void _ecore_main_timechanges_start(Eo *obj); +void _ecore_main_timechanges_stop(Eo *obj); + +Eina_Bool _ecore_event_do_filter(void *handler_pd, Eo *msg_handler, Eo *msg); +void _ecore_event_filters_call(Eo *obj, Efl_Loop_Data *pd); +void _efl_loop_messages_filter(Eo *obj, Efl_Loop_Data *pd, void *handler_pd); +void _efl_loop_messages_call(Eo *obj, Efl_Loop_Data *pd, void *func, void *data); + +void _efl_loop_message_send_info_set(Eo *obj, Eina_Inlist *node, Eo *loop, Efl_Loop_Data *loop_data); +void _efl_loop_message_unsend(Eo *obj); + static inline Eina_Bool _ecore_call_task_cb(Ecore_Task_Cb func, void *data) @@ -348,7 +439,6 @@ _ecore_call_fd_cb(Ecore_Fd_Cb func, } extern int _ecore_fps_debug; -extern double _ecore_time_loop_time; extern Eina_Bool _ecore_glib_always_integrate; extern Ecore_Select_Function main_loop_select; extern int in_main_loop; @@ -362,9 +452,9 @@ void ecore_mempool_shutdown(void); size_t _ecore_sizeof_##TYPE = sizeof (TYPE); //GENERIC_ALLOC_FREE_HEADER(Ecore_Animator, ecore_animator); -GENERIC_ALLOC_FREE_HEADER(Ecore_Event_Handler, ecore_event_handler); -GENERIC_ALLOC_FREE_HEADER(Ecore_Event_Filter, ecore_event_filter); -GENERIC_ALLOC_FREE_HEADER(Ecore_Event, ecore_event); +//GENERIC_ALLOC_FREE_HEADER(Ecore_Event_Handler, ecore_event_handler); +//GENERIC_ALLOC_FREE_HEADER(Ecore_Event_Filter, ecore_event_filter); +//GENERIC_ALLOC_FREE_HEADER(Ecore_Event, ecore_event); //GENERIC_ALLOC_FREE_HEADER(Ecore_Idle_Exiter, ecore_idle_exiter); //GENERIC_ALLOC_FREE_HEADER(Ecore_Idle_Enterer, ecore_idle_enterer); //GENERIC_ALLOC_FREE_HEADER(Ecore_Idler, ecore_idler); @@ -381,6 +471,11 @@ GENERIC_ALLOC_FREE_HEADER(Ecore_Win32_Handler, ecore_win32_handler); #undef GENERIC_ALLOC_FREE_HEADER extern Eo *_mainloop_singleton; +extern Efl_Loop_Data *_mainloop_singleton_data; +#define ML_OBJ _mainloop_singleton +#define ML_DAT _mainloop_singleton_data +//#define ML_DAT efl_data_scope_get(ML_OBJ, EFL_LOOP_CLASS) + extern Efl_Version _app_efl_version; void ecore_loop_future_register(Efl_Loop *l, Efl_Future *f); @@ -392,6 +487,9 @@ void ecore_loop_promise_fulfill(Efl_Promise *p); // access to direct input cb #define ECORE_EVAS_INTERNAL +#define EFL_LOOP_DATA efl_data_scope_get(efl_loop_main_get(EFL_LOOP_CLASS), EFL_LOOP_CLASS) + + #undef EAPI #define EAPI diff --git a/src/lib/ecore/ecore_signal.c b/src/lib/ecore/ecore_signal.c index 795dab439f..450342a2c7 100644 --- a/src/lib/ecore/ecore_signal.c +++ b/src/lib/ecore/ecore_signal.c @@ -57,27 +57,27 @@ static Eina_Bool _ecore_signal_exe_exit_delay(void *data); //#define MAXSIGQ 256 // 32k #define MAXSIGQ 64 // 8k -static volatile sig_atomic_t sig_count = 0; +static volatile sig_atomic_t sig_count = 0; static volatile sig_atomic_t sigchld_count = 0; static volatile sig_atomic_t sigusr1_count = 0; static volatile sig_atomic_t sigusr2_count = 0; -static volatile sig_atomic_t sighup_count = 0; +static volatile sig_atomic_t sighup_count = 0; static volatile sig_atomic_t sigquit_count = 0; -static volatile sig_atomic_t sigint_count = 0; +static volatile sig_atomic_t sigint_count = 0; static volatile sig_atomic_t sigterm_count = 0; #ifdef SIGPWR -static volatile sig_atomic_t sigpwr_count = 0; +static volatile sig_atomic_t sigpwr_count = 0; #endif static volatile siginfo_t sigchld_info[MAXSIGQ]; static volatile siginfo_t sigusr1_info[MAXSIGQ]; static volatile siginfo_t sigusr2_info[MAXSIGQ]; -static volatile siginfo_t sighup_info[MAXSIGQ]; +static volatile siginfo_t sighup_info [MAXSIGQ]; static volatile siginfo_t sigquit_info[MAXSIGQ]; -static volatile siginfo_t sigint_info[MAXSIGQ]; +static volatile siginfo_t sigint_info [MAXSIGQ]; static volatile siginfo_t sigterm_info[MAXSIGQ]; #ifdef SIGPWR -static volatile siginfo_t sigpwr_info[MAXSIGQ]; +static volatile siginfo_t sigpwr_info [MAXSIGQ]; #endif #if defined(SIG_ATOMIC_MAX) @@ -108,22 +108,22 @@ _ecore_signal_shutdown(void) _ecore_signal_callback_set(SIGCHLD, (Signal_Handler)SIG_DFL); _ecore_signal_callback_set(SIGUSR1, (Signal_Handler)SIG_DFL); _ecore_signal_callback_set(SIGUSR2, (Signal_Handler)SIG_DFL); - _ecore_signal_callback_set(SIGHUP, (Signal_Handler)SIG_DFL); + _ecore_signal_callback_set(SIGHUP, (Signal_Handler)SIG_DFL); _ecore_signal_callback_set(SIGQUIT, (Signal_Handler)SIG_DFL); - _ecore_signal_callback_set(SIGINT, (Signal_Handler)SIG_DFL); + _ecore_signal_callback_set(SIGINT, (Signal_Handler)SIG_DFL); _ecore_signal_callback_set(SIGTERM, (Signal_Handler)SIG_DFL); #ifdef SIGPWR - _ecore_signal_callback_set(SIGPWR, (Signal_Handler)SIG_DFL); - sigpwr_count = 0; + _ecore_signal_callback_set(SIGPWR, (Signal_Handler)SIG_DFL); + sigpwr_count = 0; #endif sigchld_count = 0; sigusr1_count = 0; sigusr2_count = 0; - sighup_count = 0; + sighup_count = 0; sigquit_count = 0; - sigint_count = 0; + sigint_count = 0; sigterm_count = 0; - sig_count = 0; + sig_count = 0; } void @@ -134,36 +134,35 @@ _ecore_signal_init(void) _ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback_sigchld); _ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback_sigusr1); _ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback_sigusr2); - _ecore_signal_callback_set(SIGHUP, _ecore_signal_callback_sighup); + _ecore_signal_callback_set(SIGHUP, _ecore_signal_callback_sighup); _ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback_sigquit); - _ecore_signal_callback_set(SIGINT, _ecore_signal_callback_sigint); + _ecore_signal_callback_set(SIGINT, _ecore_signal_callback_sigint); _ecore_signal_callback_set(SIGTERM, _ecore_signal_callback_sigterm); #ifdef SIGPWR - _ecore_signal_callback_set(SIGPWR, _ecore_signal_callback_sigpwr); + _ecore_signal_callback_set(SIGPWR, _ecore_signal_callback_sigpwr); #endif } void -_ecore_signal_received_process(void) +_ecore_signal_received_process(Eo *obj, Efl_Loop_Data *pd) { - while (_ecore_signal_count_get()) _ecore_signal_call(); + while (_ecore_signal_count_get(obj, pd)) _ecore_signal_call(obj, pd); } int -_ecore_signal_count_get(void) +_ecore_signal_count_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) { return sig_count; } static void -_ecore_signal_generic_free(void *data EINA_UNUSED, - void *event) +_ecore_signal_generic_free(void *data EINA_UNUSED, void *event) { free(event); } void -_ecore_signal_call(void) +_ecore_signal_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) { volatile sig_atomic_t n; sigset_t oldset, newset; @@ -233,7 +232,9 @@ _ecore_signal_call(void) if ((n < MAXSIGQ) && (sigchld_info[n].si_signo)) e->data = sigchld_info[n]; /* No need to clone this. */ - if ((e->exe) && (ecore_exe_flags_get(e->exe) & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR))) + if ((e->exe) && + (ecore_exe_flags_get(e->exe) & + (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR))) { /* We want to report the Last Words of the exe, so delay this event. * This is twice as relevant for stderr. @@ -257,18 +258,18 @@ _ecore_signal_call(void) * check to see for Last Words, and only delay if there are any. * This has it's own set of problems. */ - Ecore_Timer *doomsday_clock; + Ecore_Timer *doomsday_clock; - doomsday_clock = _ecore_exe_doomsday_clock_get(e->exe); - IF_FN_DEL(ecore_timer_del, doomsday_clock); - doomsday_clock = ecore_timer_add - (0.1, _ecore_signal_exe_exit_delay, e); - _ecore_exe_doomsday_clock_set(e->exe, doomsday_clock); + doomsday_clock = _ecore_exe_doomsday_clock_get(e->exe); + IF_FN_DEL(ecore_timer_del, doomsday_clock); + doomsday_clock = ecore_timer_add + (0.1, _ecore_signal_exe_exit_delay, e); + _ecore_exe_doomsday_clock_set(e->exe, doomsday_clock); } else { - _ecore_event_add(ECORE_EXE_EVENT_DEL, e, - _ecore_exe_event_del_free, NULL); + ecore_event_add(ECORE_EXE_EVENT_DEL, e, + _ecore_exe_event_del_free, NULL); } } } @@ -291,8 +292,8 @@ _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, - _ecore_signal_generic_free, NULL); + ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, + _ecore_signal_generic_free, NULL); } sig_count--; } @@ -313,8 +314,8 @@ _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, - _ecore_signal_generic_free, NULL); + ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, + _ecore_signal_generic_free, NULL); } sig_count--; } @@ -333,8 +334,8 @@ _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, - _ecore_signal_generic_free, NULL); + ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, + _ecore_signal_generic_free, NULL); } sig_count--; } @@ -355,8 +356,8 @@ _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, - _ecore_signal_generic_free, NULL); + ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, + _ecore_signal_generic_free, NULL); } sig_count--; } @@ -377,8 +378,8 @@ _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, - _ecore_signal_generic_free, NULL); + ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, + _ecore_signal_generic_free, NULL); } sig_count--; } @@ -399,8 +400,8 @@ _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, - _ecore_signal_generic_free, NULL); + ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, + _ecore_signal_generic_free, NULL); } sig_count--; } @@ -420,15 +421,15 @@ _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, - _ecore_signal_generic_free, NULL); + ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, + _ecore_signal_generic_free, NULL); } sig_count--; } sigpwr_count = 0; #endif sig_count = 0; - + sigprocmask(SIG_SETMASK, &oldset, NULL); eina_evlog("-signals", NULL, 0.0, NULL); } @@ -609,8 +610,8 @@ _ecore_signal_exe_exit_delay(void *data) if (e) { _ecore_exe_doomsday_clock_set(e->exe, NULL); - _ecore_event_add(ECORE_EXE_EVENT_DEL, e, - _ecore_exe_event_del_free, NULL); + ecore_event_add(ECORE_EXE_EVENT_DEL, e, + _ecore_exe_event_del_free, NULL); } return ECORE_CALLBACK_CANCEL; } diff --git a/src/lib/ecore/ecore_time.c b/src/lib/ecore/ecore_time.c index 1fafd62179..e96e80a9f5 100644 --- a/src/lib/ecore/ecore_time.c +++ b/src/lib/ecore/ecore_time.c @@ -24,7 +24,6 @@ static Eina_Bool _ecore_time_got_clock_id = EINA_FALSE; #elif defined(__APPLE__) && defined(__MACH__) static double _ecore_time_clock_conversion = 1e-9; #endif -double _ecore_time_loop_time = -1.0; EAPI double ecore_time_get(void) @@ -37,9 +36,9 @@ ecore_time_get(void) if (EINA_UNLIKELY(clock_gettime(_ecore_time_clock_id, &t))) { - CRI("Cannot get current time."); - /* Try to at least return the latest value retrieved*/ - return _ecore_time_loop_time; + CRI("Cannot get current time"); + // Try to at least return the latest value retrieved + return ecore_loop_time_get(); } return (double)t.tv_sec + (((double)t.tv_nsec) / 1000000000.0); @@ -68,13 +67,13 @@ ecore_time_unix_get(void) EAPI double ecore_loop_time_get(void) { - return _ecore_time_loop_time; + return efl_loop_time_get(ML_OBJ); } EAPI void ecore_loop_time_set(double t) { - _ecore_time_loop_time = t; + efl_loop_time_set(ML_OBJ, t); } /*-******************** Internal methods ********************************/ @@ -86,7 +85,7 @@ ecore_loop_time_set(double t) void _ecore_time_init(void) { -#if defined (HAVE_CLOCK_GETTIME) || defined (EXOTIC_PROVIDE_CLOCK_GETTIME) +#if defined(HAVE_CLOCK_GETTIME) || defined(EXOTIC_PROVIDE_CLOCK_GETTIME) struct timespec t; if (_ecore_time_got_clock_id) return; @@ -95,41 +94,32 @@ _ecore_time_init(void) { _ecore_time_clock_id = CLOCK_MONOTONIC; _ecore_time_got_clock_id = EINA_TRUE; - DBG("using CLOCK_MONOTONIC."); + DBG("using CLOCK_MONOTONIC"); } else if (!clock_gettime(CLOCK_REALTIME, &t)) { - /* may go backwards */ - _ecore_time_clock_id = CLOCK_REALTIME; - _ecore_time_got_clock_id = EINA_TRUE; - WRN("CLOCK_MONOTONIC not available. Fallback to CLOCK_REALTIME."); + // may go backwards + _ecore_time_clock_id = CLOCK_REALTIME; + _ecore_time_got_clock_id = EINA_TRUE; + WRN("CLOCK_MONOTONIC not available. Fallback to CLOCK_REALTIME"); } else - { - CRI("Cannot get a valid clock_gettime() clock id! " - "Fallback to unix time."); - } + CRI("Cannot get a valid clock_gettime() clock id! Fallback to unix time"); #else # ifndef _WIN32 # if defined(__APPLE__) && defined(__MACH__) mach_timebase_info_data_t info; kern_return_t err = mach_timebase_info(&info); if (err == 0) - { - _ecore_time_clock_conversion = 1e-9 * (double)info.numer / (double)info.denom; - } +   _ecore_time_clock_conversion = 1e-9 * (double)info.numer / (double)info.denom; else - { - WRN("Unable to get timebase info. Fallback to nanoseconds."); - } + WRN("Unable to get timebase info. Fallback to nanoseconds"); # else -# warning "Your platform isn't supported yet" - CRI("Platform does not support clock_gettime. " - "Fallback to unix time."); +# warning "Your platform isn't supported yet" + CRI("Platform does not support clock_gettime. Fallback to unix time"); # endif # endif #endif - - _ecore_time_loop_time = ecore_time_get(); + ecore_loop_time_set(ecore_time_get()); } diff --git a/src/lib/ecore/ecore_timer.c b/src/lib/ecore/ecore_timer.c index b2f8801459..106544558b 100644 --- a/src/lib/ecore/ecore_timer.c +++ b/src/lib/ecore/ecore_timer.c @@ -13,45 +13,46 @@ #define MY_CLASS EFL_LOOP_TIMER_CLASS #define MY_CLASS_NAME "Efl_Loop_Timer" -#define ECORE_TIMER_CHECK(obj) \ - if (!efl_isa((obj), MY_CLASS)) \ - return +#define ECORE_TIMER_CHECK(obj) if (!efl_isa((obj), MY_CLASS)) return + +struct _Ecore_Timer_Legacy +{ + Ecore_Task_Cb func; + + const void *data; + + Eina_Bool inside_call : 1; + Eina_Bool delete_me : 1; +}; struct _Efl_Loop_Timer_Data { EINA_INLIST; Eo *object; + Eo *loop; + Efl_Loop_Data *loop_data; - double in; - double at; - double pending; + double in; + double at; + double pending; - int listening; + int listening; - unsigned char just_added : 1; - unsigned char frozen : 1; - unsigned char initialized : 1; - unsigned char noparent : 1; + Eina_Bool just_added : 1; + Eina_Bool frozen : 1; + Eina_Bool initialized : 1; + Eina_Bool noparent : 1; + Eina_Bool constructed : 1; + Eina_Bool finalized : 1; }; -typedef struct _Efl_Loop_Timer_Data Efl_Loop_Timer_Data; +typedef struct _Ecore_Timer_Legacy Ecore_Timer_Legacy; -static void _efl_loop_timer_util_delay(Efl_Loop_Timer_Data *timer, - double add); -static void _efl_loop_timer_util_instanciate(Efl_Loop_Timer_Data *timer); -static void _efl_loop_timer_set(Efl_Loop_Timer_Data *timer, - double at, - double in); +static void _efl_loop_timer_util_delay(Efl_Loop_Timer_Data *timer, double add); +static void _efl_loop_timer_util_instanciate(Efl_Loop_Data *loop, Efl_Loop_Timer_Data *timer); +static void _efl_loop_timer_set(Efl_Loop_Timer_Data *timer, double at, double in); -static Eina_Inlist *timers = NULL; -static Eina_Inlist *suspended = NULL; - -static Efl_Loop_Timer_Data *timer_current = NULL; - -static int timers_added = 0; - -static double last_check = 0.0; static double precision = 10.0 / 1000000.0; EAPI double @@ -65,20 +66,15 @@ EAPI void ecore_timer_precision_set(double value) { EINA_MAIN_LOOP_CHECK_RETURN; - - if (value < 0.0) - { - ERR("Precision %f less than zero, ignored", value); - return ; - } + if (value < 0.0) value = 0.0; precision = value; } static void _check_timer_event_catcher_add(void *data, const Efl_Event *event) { - const Efl_Callback_Array_Item *array = event->info; Efl_Loop_Timer_Data *timer = data; + const Efl_Callback_Array_Item *array = event->info; int i; for (i = 0; array[i].desc != NULL; i++) @@ -86,7 +82,7 @@ _check_timer_event_catcher_add(void *data, const Efl_Event *event) if (array[i].desc == EFL_LOOP_TIMER_EVENT_TICK) { if (timer->listening++ > 0) return; - _efl_loop_timer_util_instanciate(timer); + _efl_loop_timer_util_instanciate(timer->loop_data, timer); // No need to walk more than once per array as you can not del // a partial array return; @@ -97,8 +93,8 @@ _check_timer_event_catcher_add(void *data, const Efl_Event *event) static void _check_timer_event_catcher_del(void *data, const Efl_Event *event) { - const Efl_Callback_Array_Item *array = event->info; Efl_Loop_Timer_Data *timer = data; + const Efl_Callback_Array_Item *array = event->info; int i; for (i = 0; array[i].desc != NULL; i++) @@ -106,7 +102,7 @@ _check_timer_event_catcher_del(void *data, const Efl_Event *event) if (array[i].desc == EFL_LOOP_TIMER_EVENT_TICK) { if ((--timer->listening) > 0) return; - _efl_loop_timer_util_instanciate(timer); + _efl_loop_timer_util_instanciate(timer->loop_data, timer); return; } } @@ -120,59 +116,38 @@ EOLIAN static Eo * _efl_loop_timer_efl_object_constructor(Eo *obj, Efl_Loop_Timer_Data *timer) { efl_constructor(efl_super(obj, MY_CLASS)); - efl_event_callback_array_add(obj, timer_watch(), timer); - efl_wref_add(obj, &timer->object); - timer->initialized = EINA_FALSE; timer->in = -1.0; - + timer->constructed = EINA_TRUE; return obj; } EOLIAN static Eo * _efl_loop_timer_efl_object_finalize(Eo *obj, Efl_Loop_Timer_Data *pd) { - if (pd->at < ecore_loop_time_get()) - { - pd->at = ecore_time_get() + pd->in; - } - else - { - pd->at += pd->in; - } + if (pd->at < ecore_loop_time_get()) pd->at = ecore_time_get() + pd->in; + else pd->at += pd->in; - if (pd->in < 0) + pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS); + pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS); + + if (pd->in < 0.0) { ERR("You need to specify the interval of a timer to create a valid timer."); return NULL; } - pd->initialized = EINA_TRUE; - + pd->finalized = EINA_TRUE; _efl_loop_timer_set(pd, pd->at, pd->in); - return efl_finalize(efl_super(obj, MY_CLASS)); } -typedef struct _Ecore_Timer_Legacy Ecore_Timer_Legacy; -struct _Ecore_Timer_Legacy -{ - Ecore_Task_Cb func; - - const void *data; - - Eina_Bool inside_call : 1; - Eina_Bool delete_me : 1; -}; - static void _ecore_timer_legacy_del(void *data, const Efl_Event *event EINA_UNUSED) { - Ecore_Timer_Legacy *legacy = data; - - free(legacy); + free(data); } static void @@ -181,11 +156,10 @@ _ecore_timer_legacy_tick(void *data, const Efl_Event *event) Ecore_Timer_Legacy *legacy = data; legacy->inside_call = 1; - if (!_ecore_call_task_cb(legacy->func, (void*)legacy->data) || + if (!_ecore_call_task_cb(legacy->func, (void *)legacy->data) || legacy->delete_me) efl_del(event->object); - else - legacy->inside_call = 0; + else legacy->inside_call = 0; } EFL_CALLBACKS_ARRAY_DEFINE(legacy_timer, @@ -193,9 +167,7 @@ EFL_CALLBACKS_ARRAY_DEFINE(legacy_timer, { EFL_EVENT_DEL, _ecore_timer_legacy_del }); EAPI Ecore_Timer * -ecore_timer_add(double in, - Ecore_Task_Cb func, - const void *data) +ecore_timer_add(double in, Ecore_Task_Cb func, const void *data) { Ecore_Timer_Legacy *legacy; Eo *timer; @@ -210,14 +182,11 @@ ecore_timer_add(double in, efl_event_callback_array_add(efl_added, legacy_timer(), legacy), efl_key_data_set(efl_added, "_legacy", legacy), efl_loop_timer_interval_set(efl_added, in)); - return timer; } EAPI Ecore_Timer * -ecore_timer_loop_add(double in, - Ecore_Task_Cb func, - const void *data) +ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data) { Ecore_Timer_Legacy *legacy; Eo *timer; @@ -233,7 +202,6 @@ ecore_timer_loop_add(double in, efl_key_data_set(efl_added, "_legacy", legacy), efl_loop_timer_loop_reset(efl_added), efl_loop_timer_interval_set(efl_added, in)); - return timer; } @@ -256,41 +224,28 @@ ecore_timer_del(Ecore_Timer *timer) return NULL; } - data = (void*) legacy->data; - - if (legacy->inside_call) - legacy->delete_me = EINA_TRUE; - else - efl_del(timer); - + data = (void *)legacy->data; + if (legacy->inside_call) legacy->delete_me = EINA_TRUE; + else efl_del(timer); return data; } EOLIAN static void _efl_loop_timer_interval_set(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer, double in) { - EINA_MAIN_LOOP_CHECK_RETURN; if (in < 0.0) in = 0.0; - timer->in = in; } EOLIAN static double _efl_loop_timer_interval_get(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) { - double ret = -1.0; - - EINA_MAIN_LOOP_CHECK_RETURN_VAL(ret); - ret = timer->in; - - return ret; + return timer->in; } EOLIAN static void _efl_loop_timer_delay(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *pd, double add) { - EINA_MAIN_LOOP_CHECK_RETURN; - _efl_loop_timer_util_delay(pd, add); } @@ -298,23 +253,20 @@ EOLIAN static void _efl_loop_timer_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) { double now, add; - EINA_MAIN_LOOP_CHECK_RETURN; + if (!timer->loop_data) return; // Do not reset the current timer while inside the callback - if (timer_current == timer) return ; + if (timer->loop_data->timer_current == timer) return; now = ecore_time_get(); - if (!timer->initialized) { timer->at = now; return; } - if (timer->frozen) - add = timer->pending; - else - add = timer->at - now; + if (timer->frozen) add = timer->pending; + else add = timer->at - now; _efl_loop_timer_util_delay(timer, timer->in - add); } @@ -322,102 +274,80 @@ EOLIAN static void _efl_loop_timer_loop_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) { double now, add; - EINA_MAIN_LOOP_CHECK_RETURN; + if (!timer->loop_data) return; // Do not reset the current timer while inside the callback - if (timer_current == timer) return ; + if (timer->loop_data->timer_current == timer) return; now = ecore_loop_time_get(); - if (!timer->initialized) { timer->at = now; - return ; + return; } - if (timer->frozen) - add = timer->pending; - else - add = timer->at - now; + if (timer->frozen) add = timer->pending; + else add = timer->at - now; _efl_loop_timer_util_delay(timer, timer->in - add); } EOLIAN static double _efl_loop_timer_pending_get(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) { - double now; - double ret = 0.0; - - EINA_MAIN_LOOP_CHECK_RETURN_VAL(ret); + double now, ret = 0.0; now = ecore_time_get(); - - if (timer->frozen) - ret = timer->pending; - else - ret = timer->at - now; - + if (timer->frozen) ret = timer->pending; + else ret = timer->at - now; return ret; } EAPI void ecore_timer_freeze(Ecore_Timer *timer) { - EINA_MAIN_LOOP_CHECK_RETURN; ECORE_TIMER_CHECK(timer); efl_event_freeze(timer); } EOLIAN static void -_efl_loop_timer_efl_object_event_freeze(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) +_efl_loop_timer_efl_object_event_freeze(Eo *obj, Efl_Loop_Timer_Data *timer) { double now; - EINA_MAIN_LOOP_CHECK_RETURN; - efl_event_freeze(efl_super(obj, MY_CLASS)); - - /* Timer already frozen */ - if (timer->frozen) - return; + // Timer already frozen + if (timer->frozen) return; if (EINA_UNLIKELY(!timer->initialized)) { - ERR("Attempt freezing an non initialized timer."); + ERR("Attempt freezing an non unfinalized timer."); return; } - now = ecore_loop_time_get(); + now = efl_loop_time_get(timer->loop); timer->pending = timer->at - now; - timer->at = 0.0; timer->frozen = 1; - _efl_loop_timer_util_instanciate(timer); + _efl_loop_timer_util_instanciate(timer->loop_data, timer); } EAPI Eina_Bool ecore_timer_freeze_get(Ecore_Timer *timer) { - int r = 0; - EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE); - r = efl_event_freeze_count_get(timer); - return !!r; + return !!efl_event_freeze_count_get(timer); } EOLIAN static int _efl_loop_timer_efl_object_event_freeze_count_get(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) { - EINA_MAIN_LOOP_CHECK_RETURN_VAL(0); - return timer->frozen; } EAPI void ecore_timer_thaw(Ecore_Timer *timer) { - EINA_MAIN_LOOP_CHECK_RETURN; ECORE_TIMER_CHECK(timer); efl_event_thaw(timer); } @@ -427,17 +357,16 @@ _efl_loop_timer_efl_object_event_thaw(Eo *obj, Efl_Loop_Timer_Data *timer) { double now; - EINA_MAIN_LOOP_CHECK_RETURN; - efl_event_thaw(efl_super(obj, MY_CLASS)); - /* Timer not frozen */ - if (!timer->frozen) - return ; + if (!timer->frozen) return; // Timer not frozen - suspended = eina_inlist_remove(suspended, EINA_INLIST_GET(timer)); + if (timer->loop_data) + { + timer->loop_data->suspended = eina_inlist_remove + (timer->loop_data->suspended, EINA_INLIST_GET(timer)); + } now = ecore_time_get(); - _efl_loop_timer_set(timer, timer->pending + now, timer->in); } @@ -448,139 +377,130 @@ ecore_timer_dump(void) } static void -_efl_loop_timer_util_instanciate(Efl_Loop_Timer_Data *timer) +_efl_loop_timer_util_loop_clear(Efl_Loop_Timer_Data *pd) { - Efl_Loop_Timer_Data *t2; Eina_Inlist *first; + if (!pd->loop_data) return; + // Check if we are the current timer, if so move along + if (pd->loop_data->timer_current == pd) + pd->loop_data->timer_current = (Efl_Loop_Timer_Data *) + EINA_INLIST_GET(pd)->next; + // Remove the timer from all possible pending list - first = eina_inlist_first(EINA_INLIST_GET(timer)); - if (first == timers) - timers = eina_inlist_remove(timers, EINA_INLIST_GET(timer)); - else if (first == suspended) - suspended = eina_inlist_remove(suspended, EINA_INLIST_GET(timer)); + first = eina_inlist_first(EINA_INLIST_GET(pd)); + if (first == pd->loop_data->timers) + pd->loop_data->timers = eina_inlist_remove + (pd->loop_data->timers, EINA_INLIST_GET(pd)); + else if (first == pd->loop_data->suspended) + pd->loop_data->suspended = eina_inlist_remove + (pd->loop_data->suspended, EINA_INLIST_GET(pd)); +} + +static void +_efl_loop_timer_util_instanciate(Efl_Loop_Data *loop, Efl_Loop_Timer_Data *timer) +{ + Efl_Loop_Timer_Data *t2; + + if (!loop) return; + _efl_loop_timer_util_loop_clear(timer); // And start putting it back where it belong - if (!timer->listening || timer->frozen || timer->at <= 0.0 || timer->in < 0.0) + if ((!timer->listening) || (timer->frozen) || + (timer->at <= 0.0) || (timer->in < 0.0)) { - suspended = eina_inlist_prepend(suspended, EINA_INLIST_GET(timer)); - return ; + loop->suspended = eina_inlist_prepend(loop->suspended, + EINA_INLIST_GET(timer)); + return; } if (!timer->initialized) { ERR("Trying to instantiate an uninitialized timer is impossible."); - return ; + return; } - EINA_INLIST_REVERSE_FOREACH(timers, t2) + EINA_INLIST_REVERSE_FOREACH(loop->timers, t2) { if (timer->at > t2->at) { - timers = eina_inlist_append_relative(timers, - EINA_INLIST_GET(timer), - EINA_INLIST_GET(t2)); + loop->timers = eina_inlist_append_relative(loop->timers, + EINA_INLIST_GET(timer), + EINA_INLIST_GET(t2)); return; } } - timers = eina_inlist_prepend(timers, EINA_INLIST_GET(timer)); + loop->timers = eina_inlist_prepend(loop->timers, EINA_INLIST_GET(timer)); } static void -_efl_loop_timer_util_delay(Efl_Loop_Timer_Data *timer, - double add) +_efl_loop_timer_util_delay(Efl_Loop_Timer_Data *timer, double add) { if (!timer->initialized) { ERR("Impossible to delay an uninitialized timer."); - return ; + return; } - if (timer->frozen) { timer->pending += add; - return ; + return; } - _efl_loop_timer_set(timer, timer->at + add, timer->in); } EOLIAN static void -_efl_loop_timer_efl_object_parent_set(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *pd, Efl_Object *parent) +_efl_loop_timer_efl_object_parent_set(Eo *obj, Efl_Loop_Timer_Data *pd, Efl_Object *parent) { - Eina_Inlist *first; - - first = eina_inlist_first(EINA_INLIST_GET(pd)); - if (first == timers) - timers = eina_inlist_remove(timers, EINA_INLIST_GET(pd)); - else if (first == suspended) - suspended = eina_inlist_remove(suspended, EINA_INLIST_GET(pd)); - efl_parent_set(efl_super(obj, EFL_LOOP_TIMER_CLASS), parent); - if (efl_parent_get(obj) != parent) - return ; + if ((!pd->constructed) || (!pd->finalized)) return; - if (parent != NULL) - { - _efl_loop_timer_util_instanciate(pd); - pd->noparent = EINA_FALSE; - } - else - { - pd->noparent = EINA_TRUE; - } + _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 (efl_parent_get(obj) != parent) return; + + _efl_loop_timer_util_instanciate(pd->loop_data, pd); + + if (parent != NULL) pd->noparent = EINA_FALSE; + else pd->noparent = EINA_TRUE; } EOLIAN static void _efl_loop_timer_efl_object_destructor(Eo *obj, Efl_Loop_Timer_Data *pd) { - Eina_Inlist *first; - - // Check if we are the current timer, if so move along - if (timer_current == pd) - timer_current = (Efl_Loop_Timer_Data *)EINA_INLIST_GET(pd)->next; - - // Remove the timer from all possible pending list - first = eina_inlist_first(EINA_INLIST_GET(pd)); - if (first == timers) - timers = eina_inlist_remove(timers, EINA_INLIST_GET(pd)); - else if (first == suspended) - suspended = eina_inlist_remove(suspended, EINA_INLIST_GET(pd)); - + _efl_loop_timer_util_loop_clear(pd); efl_destructor(efl_super(obj, MY_CLASS)); } void -_efl_loop_timer_shutdown(void) -{ - timer_current = NULL; -} - -void -_efl_loop_timer_enable_new(void) +_efl_loop_timer_enable_new(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd) { Efl_Loop_Timer_Data *timer; - if (!timers_added) return; - timers_added = 0; - EINA_INLIST_FOREACH(timers, timer) timer->just_added = 0; + if (!pd->timers_added) return; + pd->timers_added = 0; + EINA_INLIST_FOREACH(pd->timers, timer) timer->just_added = 0; } int -_efl_loop_timers_exists(void) +_efl_loop_timers_exists(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd) { - return !!timers; + return !!pd->timers; } static inline Ecore_Timer * -_efl_loop_timer_first_get(void) +_efl_loop_timer_first_get(Eo *ob EINA_UNUSED, Efl_Loop_Data *pd) { Efl_Loop_Timer_Data *timer; - EINA_INLIST_FOREACH(timers, timer) - if (!timer->just_added) return timer->object; - + EINA_INLIST_FOREACH(pd->timers, timer) + { + if (!timer->just_added) return timer->object; + } return NULL; } @@ -595,41 +515,40 @@ _efl_loop_timer_after_get(Efl_Loop_Timer_Data *base) { if (EINA_UNLIKELY(!timer->initialized)) continue; // This shouldn't happen if (timer->at >= maxtime) break; - if (!timer->just_added) - valid_timer = timer; + if (!timer->just_added) valid_timer = timer; } - return valid_timer; } double -_efl_loop_timer_next_get(void) +_efl_loop_timer_next_get(Eo *obj, Efl_Loop_Data *pd) { Ecore_Timer *object; Efl_Loop_Timer_Data *first; double now; double in; - object = _efl_loop_timer_first_get(); + object = _efl_loop_timer_first_get(obj, pd); if (!object) return -1; first = _efl_loop_timer_after_get(efl_data_scope_get(object, MY_CLASS)); - now = ecore_loop_time_get(); in = first->at - now; if (in < 0) in = 0; - return in; } static inline void -_efl_loop_timer_reschedule(Efl_Loop_Timer_Data *timer, - double when) +_efl_loop_timer_reschedule(Efl_Loop_Timer_Data *timer, double when) { if (timer->frozen) return; - if (timers && !timer->noparent) - timers = eina_inlist_remove(timers, EINA_INLIST_GET(timer)); + if (timer->loop_data) + { + if (timer->loop_data->timers && (!timer->noparent)) + timer->loop_data->timers = eina_inlist_remove + (timer->loop_data->timers, EINA_INLIST_GET(timer)); + } /* if the timer would have gone off more than 15 seconds ago, * assume that the system hung and set the timer to go off @@ -647,51 +566,51 @@ _efl_loop_timer_reschedule(Efl_Loop_Timer_Data *timer, } void -_efl_loop_timer_expired_timers_call(double when) +_efl_loop_timer_expired_timers_call(Eo *obj, Efl_Loop_Data *pd, double when) { - /* call the first expired timer until no expired timers exist */ - while (_efl_loop_timer_expired_call(when)) ; + // call the first expired timer until no expired timers exist + while (_efl_loop_timer_expired_call(obj, pd, when)); } int -_efl_loop_timer_expired_call(double when) +_efl_loop_timer_expired_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, double when) { - if (!timers) return 0; - if (last_check > when) + if (!pd->timers) return 0; + if (pd->last_check > when) { Efl_Loop_Timer_Data *timer; - /* User set time backwards */ - EINA_INLIST_FOREACH(timers, timer) timer->at -= (last_check - when); + // User set time backwards + EINA_INLIST_FOREACH(pd->timers, timer) + timer->at -= (pd->last_check - when); } - last_check = when; + pd->last_check = when; - if (!timer_current) - { - /* regular main loop, start from head */ - timer_current = (Efl_Loop_Timer_Data *)timers; - } + if (!pd->timer_current) // regular main loop, start from head + pd->timer_current = (Efl_Loop_Timer_Data *)pd->timers; else { - /* recursive main loop, continue from where we were */ - Efl_Loop_Timer_Data *timer_old = timer_current; + // recursive main loop, continue from where we were + Efl_Loop_Timer_Data *timer_old = pd->timer_current; - timer_current = (Efl_Loop_Timer_Data *)EINA_INLIST_GET(timer_current)->next; + pd->timer_current = (Efl_Loop_Timer_Data *) + EINA_INLIST_GET(pd->timer_current)->next; _efl_loop_timer_reschedule(timer_old, when); } - while (timer_current) + while (pd->timer_current) { - Efl_Loop_Timer_Data *timer = timer_current; + Efl_Loop_Timer_Data *timer = pd->timer_current; if (timer->at > when) { - timer_current = NULL; /* ended walk, next should restart. */ + pd->timer_current = NULL; // ended walk, next should restart. return 0; } if (timer->just_added) { - timer_current = (Efl_Loop_Timer_Data *)EINA_INLIST_GET(timer_current)->next; + pd->timer_current = (Efl_Loop_Timer_Data *) + EINA_INLIST_GET(pd->timer_current)->next; continue; } @@ -700,11 +619,11 @@ _efl_loop_timer_expired_call(double when) efl_event_callback_call(timer->object, EFL_LOOP_TIMER_EVENT_TICK, NULL); eina_evlog("-timer", timer, 0.0, NULL); - /* may have changed in recursive main loops */ - /* this current timer can not die yet as we hold a reference on it */ - if (timer_current) - timer_current = (Efl_Loop_Timer_Data *)EINA_INLIST_GET(timer_current)->next; - + // may have changed in recursive main loops + // this current timer can not die yet as we hold a reference on it + if (pd->timer_current) + pd->timer_current = (Efl_Loop_Timer_Data *) + EINA_INLIST_GET(pd->timer_current)->next; _efl_loop_timer_reschedule(timer, when); efl_unref(timer->object); } @@ -712,19 +631,17 @@ _efl_loop_timer_expired_call(double when) } static void -_efl_loop_timer_set(Efl_Loop_Timer_Data *timer, - double at, - double in) +_efl_loop_timer_set(Efl_Loop_Timer_Data *timer, double at, double in) { - timers_added = 1; + if (!timer->loop_data) return; + timer->loop_data->timers_added = 1; timer->at = at; timer->in = in; timer->just_added = 1; timer->initialized = 1; timer->frozen = 0; timer->pending = 0.0; - - _efl_loop_timer_util_instanciate(timer); + _efl_loop_timer_util_instanciate(timer->loop_data, timer); } #include "efl_loop_timer.eo.c" diff --git a/src/lib/ecore/efl_loop.c b/src/lib/ecore/efl_loop.c new file mode 100644 index 0000000000..661bf654a9 --- /dev/null +++ b/src/lib/ecore/efl_loop.c @@ -0,0 +1,717 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include "Ecore.h" +#include "ecore_private.h" + +#include "ecore_main_common.h" + +typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data; +typedef struct _Efl_Internal_Promise Efl_Internal_Promise; + +struct _Efl_Loop_Promise_Simple_Data +{ + union { + Ecore_Timer *timer; + Ecore_Idler *idler; + }; + Eina_Promise *promise; +}; +GENERIC_ALLOC_SIZE_DECLARE(Efl_Loop_Promise_Simple_Data); + +EOLIAN static Efl_Loop_Message_Handler * +_efl_loop_message_handler_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Loop *loop, const Efl_Class *klass) +{ + Message_Handler mh = { 0 }, *mh2; + Efl_Loop_Data *ld = efl_data_scope_get(loop, EFL_LOOP_CLASS); + unsigned int i, n; + + if (!ld) return NULL; + n = eina_inarray_count(ld->message_handlers); + for (i = 0; i < n; i++) + { + mh2 = eina_inarray_nth(ld->message_handlers, i); + if (mh2->klass == klass) return mh2->handler; + } + mh.klass = klass; + mh.handler = efl_add(klass, loop); + eina_inarray_push(ld->message_handlers, &mh); + return mh.handler; +} + +Efl_Version _app_efl_version = { 0, 0, 0, 0, NULL, NULL }; + +Eo *_mainloop_singleton = NULL; +Efl_Loop_Data *_mainloop_singleton_data = NULL; + +static void +_mainloop_singleton_cb_del(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED) +{ + _mainloop_singleton = NULL; + _mainloop_singleton_data = NULL; +} + +EFL_CALLBACKS_ARRAY_DEFINE(_mainloop_singleton_callbacks, + { EFL_EVENT_DEL, _mainloop_singleton_cb_del }); + +EOLIAN static Efl_Loop * +_efl_loop_main_get(Efl_Class *klass EINA_UNUSED, void *_pd EINA_UNUSED) +{ + if (_mainloop_singleton) return _mainloop_singleton; + _mainloop_singleton = efl_add(EFL_LOOP_CLASS, NULL); + _mainloop_singleton_data = efl_data_scope_get(_mainloop_singleton, + EFL_LOOP_CLASS); + efl_event_callback_array_add(_mainloop_singleton, + _mainloop_singleton_callbacks(), NULL); + return _mainloop_singleton; +} + +EAPI Eo * +ecore_main_loop_get(void) +{ + return efl_loop_main_get(EFL_LOOP_CLASS); +} + +EOLIAN static void +_efl_loop_iterate(Eo *obj, Efl_Loop_Data *pd) +{ + _ecore_main_loop_iterate(obj, pd); +} + +EOLIAN static int +_efl_loop_iterate_may_block(Eo *obj, Efl_Loop_Data *pd, int may_block) +{ + return _ecore_main_loop_iterate_may_block(obj, pd, may_block); +} + +// FIXME: This should return an Eina_Value, but that doesn't work at the moment +EOLIAN static Eina_Value * +_efl_loop_begin(Eo *obj, Efl_Loop_Data *pd) +{ + _ecore_main_loop_begin(obj, pd); + return &(pd->exit_code); +} + +EOLIAN static void +_efl_loop_quit(Eo *obj, Efl_Loop_Data *pd, Eina_Value exit_code) +{ + _ecore_main_loop_quit(obj, pd); + pd->exit_code = exit_code; +} + +EOLIAN static void +_efl_loop_time_set(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, double t) +{ + pd->loop_time = t; +} + +EOLIAN static double +_efl_loop_time_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd) +{ + return pd->loop_time; +} + +EAPI void +efl_exit(int exit_code) +{ + Eina_Value v = EINA_VALUE_EMPTY; + + eina_value_setup(&v, EINA_VALUE_TYPE_INT); + eina_value_set(&v, &exit_code); + efl_loop_quit(ecore_main_loop_get(), v); +} + +EOLIAN static Efl_Object * +_efl_loop_efl_object_provider_find(Eo *obj, Efl_Loop_Data *pd, const Efl_Object *klass) +{ + Efl_Object *r; + + if (klass == EFL_LOOP_CLASS) return obj; + + r = eina_hash_find(pd->providers, &klass); + if (r) return r; + + return efl_provider_find(efl_super(obj, EFL_LOOP_CLASS), klass); +} + +EAPI int +efl_loop_exit_code_process(Eina_Value *value) +{ + const Eina_Value_Type *t = eina_value_type_get(value); + int r = 0; + + if (t == EINA_VALUE_TYPE_UCHAR || + t == EINA_VALUE_TYPE_USHORT || + t == EINA_VALUE_TYPE_UINT || + t == EINA_VALUE_TYPE_ULONG || + t == EINA_VALUE_TYPE_UINT64 || + t == EINA_VALUE_TYPE_CHAR || + t == EINA_VALUE_TYPE_SHORT || + t == EINA_VALUE_TYPE_INT || + t == EINA_VALUE_TYPE_LONG || + t == EINA_VALUE_TYPE_INT64 || + t == EINA_VALUE_TYPE_FLOAT || + t == EINA_VALUE_TYPE_DOUBLE) + { + Eina_Value v = EINA_VALUE_EMPTY; + + eina_value_setup(&v, EINA_VALUE_TYPE_INT); + if (!eina_value_convert(&v, value)) r = -1; + else eina_value_get(&v, &v); + } + else + { + FILE *out = stdout; + char *msg; + + msg = eina_value_to_string(value); + + if (t == EINA_VALUE_TYPE_ERROR) + { + r = -1; + out = stderr; + } + fprintf(out, "%s\n", msg); + } + return r; +} + +static void +_poll_trigger(void *data, const Efl_Event *event) +{ + Eo *parent = efl_parent_get(event->object); + + efl_event_callback_call(parent, data, NULL); +} + +static void +_check_event_catcher_add(void *data, const Efl_Event *event) +{ + const Efl_Callback_Array_Item *array = event->info; + Efl_Loop_Data *pd = data; + int i; + + for (i = 0; array[i].desc != NULL; i++) + { + if (array[i].desc == EFL_LOOP_EVENT_IDLE) + { + ++pd->idlers; + } + // XXX: all the below are kind of bad. ecore_pollers were special. + // they all woke up at the SAME time based on interval, (all pollers + // of interval 1 woke up together, those with 2 woke up when 1 and + // 2 woke up, 4 woke up together along with 1 and 2 etc. + // the below means they will just go off whenever but at a pre + // defined interval - 1/60th, 6 and 66 seconds. not really great + // pollers probably should be less frequent that 1/60th even on poll + // high, medium probably down to 1-2 sec and low - yes maybe 30 or 60 + // sec... still - not timed to wake up together. :( + else if (array[i].desc == EFL_LOOP_EVENT_POLL_HIGH) + { + if (!pd->poll_high) + { + // Would be better to have it in sync with normal wake up + // of the main loop for better energy efficiency, I guess. + pd->poll_high = efl_add + (EFL_LOOP_TIMER_CLASS, event->object, + efl_event_callback_add(efl_added, + EFL_LOOP_TIMER_EVENT_TICK, + _poll_trigger, + EFL_LOOP_EVENT_POLL_HIGH), + efl_loop_timer_interval_set(efl_added, 1.0 / 60.0)); + } + ++pd->pollers.high; + } + else if (array[i].desc == EFL_LOOP_EVENT_POLL_MEDIUM) + { + if (!pd->poll_medium) + { + pd->poll_medium = efl_add + (EFL_LOOP_TIMER_CLASS, event->object, + efl_event_callback_add(efl_added, + EFL_LOOP_TIMER_EVENT_TICK, + _poll_trigger, + EFL_LOOP_EVENT_POLL_MEDIUM), + efl_loop_timer_interval_set(efl_added, 6)); + } + ++pd->pollers.medium; + } + else if (array[i].desc == EFL_LOOP_EVENT_POLL_LOW) + { + if (!pd->poll_low) + { + pd->poll_low = efl_add + (EFL_LOOP_TIMER_CLASS, event->object, + efl_event_callback_add(efl_added, + EFL_LOOP_TIMER_EVENT_TICK, + _poll_trigger, + EFL_LOOP_EVENT_POLL_LOW), + efl_loop_timer_interval_set(efl_added, 66)); + } + ++pd->pollers.low; + } + } +} + +static void +_check_event_catcher_del(void *data, const Efl_Event *event) +{ + const Efl_Callback_Array_Item *array = event->info; + Efl_Loop_Data *pd = data; + int i; + + for (i = 0; array[i].desc != NULL; i++) + { + if (array[i].desc == EFL_LOOP_EVENT_IDLE) + { + --pd->idlers; + } + else if (array[i].desc == EFL_LOOP_EVENT_POLL_HIGH) + { + --pd->pollers.high; + if (!pd->pollers.high) + { + ecore_timer_del(pd->poll_high); + pd->poll_high = NULL; + } + } + else if (array[i].desc == EFL_LOOP_EVENT_POLL_MEDIUM) + { + --pd->pollers.medium; + if (!pd->pollers.medium) + { + ecore_timer_del(pd->poll_medium); + pd->poll_medium = NULL; + } + } + else if (array[i].desc == EFL_LOOP_EVENT_POLL_LOW) + { + --pd->pollers.low; + if (!pd->pollers.low) + { + ecore_timer_del(pd->poll_low); + pd->poll_low = NULL; + } + } + } +} + +EFL_CALLBACKS_ARRAY_DEFINE(event_catcher_watch, + { EFL_EVENT_CALLBACK_ADD, _check_event_catcher_add }, + { EFL_EVENT_CALLBACK_DEL, _check_event_catcher_del }); + +EOLIAN static Efl_Object * +_efl_loop_efl_object_constructor(Eo *obj, Efl_Loop_Data *pd) +{ + obj = efl_constructor(efl_super(obj, EFL_LOOP_CLASS)); + if (!obj) return NULL; + + efl_event_callback_array_add(obj, event_catcher_watch(), pd); + + pd->loop_time = ecore_time_get(); + pd->providers = eina_hash_pointer_new(EINA_FREE_CB(efl_unref)); + pd->message_handlers = eina_inarray_new(sizeof(Message_Handler), 32); +#ifdef HAVE_EPOLL + pd->epoll_fd = -1; +#endif +#ifdef USE_G_MAIN_LOOP + pd->timer_fd = -1; +#endif + return obj; +} + +EOLIAN static void +_efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd) +{ + _ecore_main_content_clear(pd); + + eina_hash_free(pd->providers); + pd->providers = NULL; + + efl_del(pd->poll_low); + pd->poll_low = NULL; + efl_del(pd->poll_medium); + pd->poll_medium = NULL; + efl_del(pd->poll_high); + pd->poll_high = NULL; + + eina_inarray_free(pd->message_handlers); + pd->message_handlers = NULL; + + efl_destructor(efl_super(obj, EFL_LOOP_CLASS)); +} + +static void +_efl_loop_arguments_cleanup(Eina_Array *arga) +{ + Eina_Stringshare *s; + + while ((s = eina_array_pop(arga))) eina_stringshare_del(s); + eina_array_free(arga); +} + +static void +_efl_loop_arguments_send(void *data, const Efl_Event *ev EINA_UNUSED) +{ + static Eina_Bool initialization = EINA_TRUE; + Efl_Loop_Arguments arge; + Eina_Array *arga = data; + + arge.argv = arga; + arge.initialization = initialization; + initialization = EINA_FALSE; + + efl_event_callback_call(ecore_main_loop_get(), + EFL_LOOP_EVENT_ARGUMENTS, &arge); + + _efl_loop_arguments_cleanup(arga); +} + +static void +_efl_loop_arguments_cancel(void *data, const Efl_Event *ev EINA_UNUSED) +{ + _efl_loop_arguments_cleanup(data); +} + +// It doesn't make sense to send those argument to any other mainloop +// As it also doesn't make sense to allow anyone to override this, so +// should be internal for sure, not even protected. +EAPI void +ecore_loop_arguments_send(int argc, const char **argv) +{ + Eina_Future *job; + Eina_Array *arga; + int i = 0; + + arga = eina_array_new(argc); + for (i = 0; i < argc; i++) + eina_array_push(arga, eina_stringshare_add(argv[i])); + + job = eina_future_then(efl_loop_job(ecore_main_loop_get()), + _efl_loop_arguments_send, arga); + efl_future_Eina_FutureXXX_then(ecore_main_loop_get(), job); +} + +// Only one main loop handle for now +void +ecore_loop_future_register(Efl_Loop *l, Efl_Future *f) +{ + Efl_Loop_Data *pd; + + if (l == ML_OBJ) pd = ML_DAT; + else pd = efl_data_scope_get(l, EFL_LOOP_CLASS); + if (!pd) return; + + pd->pending_futures = eina_list_append(pd->pending_futures, f); +} + +void +ecore_loop_future_unregister(Efl_Loop *l, Efl_Future *f) +{ + Efl_Loop_Data *pd; + + if (l == ML_OBJ) pd = ML_DAT; + else pd = efl_data_scope_get(l, EFL_LOOP_CLASS); + if (!pd) return; + + pd->pending_futures = eina_list_remove(pd->pending_futures, f); +} + +void +ecore_loop_promise_register(Efl_Loop *l, Efl_Promise *p) +{ + Efl_Loop_Data *pd; + + if (l == ML_OBJ) pd = ML_DAT; + else pd = efl_data_scope_get(l, EFL_LOOP_CLASS); + if (!pd) return; + + pd->pending_promises = eina_list_append(pd->pending_promises, p); +} + +void +ecore_loop_promise_unregister(Efl_Loop *l, Efl_Promise *p) +{ + Efl_Loop_Data *pd; + + if (l == ML_OBJ) pd = ML_DAT; + else pd = efl_data_scope_get(l, EFL_LOOP_CLASS); + if (!pd) return; + + pd->pending_promises = eina_list_remove(pd->pending_promises, p); +} + +static Eina_Future * +_efl_loop_job(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED) +{ + // 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)); +} + +EOLIAN static void +_efl_loop_throttle_set(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, double amount) +{ + pd->throttle = ((double)amount) * 1000000.0; +} + +EOLIAN static double +_efl_loop_throttle_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd) +{ + return (double)(pd->throttle) / 1000000.0; +} + +static void +_efl_loop_idle_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED) +{ + Efl_Loop_Promise_Simple_Data *d = data; + ecore_idler_del(d->idler); + efl_loop_promise_simple_data_mp_free(d); +} + +static Eina_Bool +_efl_loop_idle_done(void *data) +{ + Efl_Loop_Promise_Simple_Data *d = data; + eina_promise_resolve(d->promise, EINA_VALUE_EMPTY); + efl_loop_promise_simple_data_mp_free(d); + return EINA_FALSE; +} + +static Eina_Future * +_efl_loop_idle(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED) +{ + Efl_Loop_Promise_Simple_Data *d; + Eina_Promise *p; + + d = efl_loop_promise_simple_data_calloc(1); + EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL); + + 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); + // d is dead if p is NULL + EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL); + d->promise = p; + + // NOTE: Eolian should do efl_future_then() to bind future to object. + return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p)); + +idler_error: + efl_loop_promise_simple_data_mp_free(d); + return NULL; +} + +static void +_efl_loop_timeout_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED) +{ + Efl_Loop_Promise_Simple_Data *d = data; + ecore_timer_del(d->timer); + efl_loop_promise_simple_data_mp_free(d); +} + +static Eina_Bool +_efl_loop_timeout_done(void *data) +{ + Efl_Loop_Promise_Simple_Data *d = data; + eina_promise_resolve(d->promise, EINA_VALUE_EMPTY); + efl_loop_promise_simple_data_mp_free(d); + return EINA_FALSE; +} + +static Eina_Future * +_efl_loop_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, double time) +{ + Efl_Loop_Promise_Simple_Data *d; + Eina_Promise *p; + + d = efl_loop_promise_simple_data_calloc(1); + EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL); + + d->timer = ecore_timer_add(time, _efl_loop_timeout_done, 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); + // d is dead if p is NULL + EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL); + d->promise = p; + + // NOTE: Eolian should do efl_future_then() to bind future to object. + return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p)); + +timer_error: + efl_loop_promise_simple_data_mp_free(d); + return NULL; +} + +static Eina_Bool +_efl_loop_register(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, const Efl_Class *klass, const Efl_Object *provider) +{ + // The passed object does not provide that said class. + if (!efl_isa(provider, klass)) return EINA_FALSE; + + // Note: I would prefer to use efl_xref here, but I can't figure a nice way to + // call efl_xunref on hash destruction. + return eina_hash_add(pd->providers, &klass, efl_ref(provider)); +} + +static Eina_Bool +_efl_loop_unregister(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, const Efl_Class *klass, const Efl_Object *provider) +{ + return eina_hash_del(pd->providers, &klass, provider); +} + +void +_efl_loop_messages_filter(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, void *handler_pd) +{ + Message *msg; + + pd->message_walking++; + EINA_INLIST_FOREACH(pd->message_queue, msg) + { + if ((msg->handler) && (msg->message) && (!msg->delete_me)) + { + if (!_ecore_event_do_filter(handler_pd, + msg->handler, msg->message)) + { + efl_del(msg->message); + msg->handler = NULL; + msg->message = NULL; + msg->delete_me = EINA_TRUE; + } + } + } + pd->message_walking--; +} + +void +_efl_loop_messages_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, void *func, void *data) +{ + Message *msg; + + pd->message_walking++; + EINA_INLIST_FOREACH(pd->message_queue, msg) + { + if ((msg->handler) && (msg->message) && (!msg->delete_me)) + { + Eina_Bool (*fn) (void *data, void *handler, void *msg); + + fn = func; + if (!fn(data, msg->handler, msg->message)) + { + efl_del(msg->message); + msg->handler = NULL; + msg->message = NULL; + msg->delete_me = EINA_TRUE; + } + } + } + pd->message_walking--; +} + +EOLIAN static Eina_Bool +_efl_loop_message_process(Eo *obj, Efl_Loop_Data *pd) +{ + if (!pd->message_queue) return EINA_FALSE; + pd->message_walking++; + _ecore_event_filters_call(obj, pd); + while (pd->message_queue) + { + Message *msg = (Message *)pd->message_queue; + if (!msg->delete_me) + efl_loop_message_handler_message_call(msg->handler, msg->message); + else + { + if (msg->message) efl_del(msg->message); + pd->message_queue = + eina_inlist_remove(pd->message_queue, + pd->message_queue); + free(msg); + } + } + pd->message_walking--; + if (pd->message_walking == 0) + { + Message *msg; + + EINA_INLIST_FREE(pd->message_queue, msg) + { + if (msg->message) + { + if (!msg->delete_me) + ERR("Found unprocessed event msg=%p handler=%p on queue", + msg->message, msg->handler); + efl_del(msg->message); + } + else free(msg); + } + } + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_efl_loop_message_exists(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd) +{ + if (pd->message_queue) return EINA_TRUE; + return EINA_FALSE; +} + +EWAPI void +efl_build_version_set(int vmaj, int vmin, int vmic, int revision, + const char *flavor, const char *build_id) +{ + // note: EFL has not been initialized yet at this point (ie. no eina call) + _app_efl_version.major = vmaj; + _app_efl_version.minor = vmin; + _app_efl_version.micro = vmic; + _app_efl_version.revision = revision; + free((char *)_app_efl_version.flavor); + free((char *)_app_efl_version.build_id); + _app_efl_version.flavor = flavor ? strdup(flavor) : NULL; + _app_efl_version.build_id = build_id ? strdup(build_id) : NULL; +} + +EOLIAN static const Efl_Version * +_efl_loop_app_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) +{ + return &_app_efl_version; +} + +EOLIAN static const Efl_Version * +_efl_loop_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) +{ + /* vanilla EFL: flavor = NULL */ + static const Efl_Version version = { + .major = VMAJ, + .minor = VMIN, + .micro = VMIC, + .revision = VREV, + .build_id = EFL_BUILD_ID, + .flavor = NULL + }; + return &version; +} + +EAPI Eina_Future_Scheduler * +efl_loop_future_scheduler_get(Eo *obj) +{ + if (!obj) return NULL; + + if (efl_isa(obj, EFL_LOOP_CLASS)) + return _ecore_event_future_scheduler_get(); + + return efl_loop_future_scheduler_get(efl_loop_get(obj)); +} + +#include "efl_loop.eo.c" diff --git a/src/lib/ecore/efl_loop.eo b/src/lib/ecore/efl_loop.eo index b806de0bb5..2162039113 100644 --- a/src/lib/ecore/efl_loop.eo +++ b/src/lib/ecore/efl_loop.eo @@ -77,7 +77,24 @@ class Efl.Loop (Efl.Object) This has higher priority, for low priority use @.idle ]] - return: ptr(Eina.Future) @owned /* TODO: future */; [[The future handle.]] + return: ptr(Eina.Future) @owned /* TODO: future */; [[The future handle.]] + } + @property throttle { + [[Slow down the loop execution by forcing a sleep for a small + period of time every time the loop iterates/loops.]] + set {} + get {} + values { + amount : double; [[Time to sleep for each "loop iteration"]] + } + } + @property time { + [[The time point when the loop was logically woken up.]] + set {} + get {} + values { + timepoint: double; [[Time in seconds since process specfic start point]] + } } idle { [[A future promise that will be resolved from a clean main @@ -85,7 +102,7 @@ class Efl.Loop (Efl.Object) This is a low priority version of @.job ]] - return: ptr(Eina.Future) @owned /* TODO: future */; [[The future handle.]] + return: ptr(Eina.Future) @owned /* TODO: future */; [[The future handle.]] } timeout { [[A future promise that will be resolved from a clean main @@ -111,6 +128,22 @@ class Efl.Loop (Efl.Object) } return: bool; [[$true if successfully unregistered, $false otherwise.]] } + message_handler_get @class { + [[ ]] + params { + @in loop: Efl.Loop; [[ ]] + @in klass: const(Efl.Class); [[ ]] + } + return: Efl.Loop.Message.Handler; [[ ]] + } + message_process { + [[ ]] + return: bool; [[ ]] + } + message_exists { + [[ ]] + return: bool; [[ ]] + } } events { idle,enter @restart; [[Event occurs once the main loop enters the idle state.]] diff --git a/src/lib/ecore/efl_loop_handler.c b/src/lib/ecore/efl_loop_handler.c new file mode 100644 index 0000000000..417e12d974 --- /dev/null +++ b/src/lib/ecore/efl_loop_handler.c @@ -0,0 +1,341 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "ecore_private.h" + +#define MY_CLASS EFL_LOOP_HANDLER_CLASS + +////////////////////////////////////////////////////////////////////////// + +typedef struct _Efl_Loop_Handler_Data Efl_Loop_Handler_Data; + +struct _Efl_Loop_Handler_Data +{ + Eo *loop; + Efl_Loop_Data *loop_data; + Ecore_Fd_Handler *handler_fd; + Ecore_Win32_Handler *handler_win32; + + void *win32; + int fd; + + struct { + unsigned short read; + unsigned short write; + unsigned short error; + unsigned short buffer; + unsigned short prepare; + } references; + + Efl_Loop_Handler_Flags flags : 8; + Eina_Bool file : 1; + + Eina_Bool constructed : 1; + Eina_Bool finalized : 1; +}; + +////////////////////////////////////////////////////////////////////////// + +static Eina_Bool _cb_handler_fd(void *data, Ecore_Fd_Handler *fd_handler); +static Eina_Bool _cb_handler_buffer(void *data, Ecore_Fd_Handler *fd_handler); +static Eina_Bool _cb_handler_win32(void *data, Ecore_Win32_Handler *win32_handler); +static void _cb_handler_prepare(void *data, Ecore_Fd_Handler *fd_handler); + +////////////////////////////////////////////////////////////////////////// + +static void +_handler_clear(Efl_Loop_Handler_Data *pd) +{ + Eo *obj = pd->loop; + Efl_Loop_Data *loop = pd->loop_data; + + if (pd->handler_fd) + _ecore_main_fd_handler_del(obj, loop, pd->handler_fd); + else if (pd->handler_win32) + _ecore_main_win32_handler_del(obj, loop, pd->handler_win32); + pd->handler_fd = NULL; + pd->handler_win32 = NULL; +} + +static Ecore_Fd_Handler_Flags +_handler_flags_get(Efl_Loop_Handler_Data *pd) +{ + return ((pd->references.read > 0) ? ECORE_FD_READ : 0) | + ((pd->references.write > 0) ? ECORE_FD_WRITE : 0) | + ((pd->references.error > 0) ? ECORE_FD_ERROR : 0); +} + +static void +_handler_active_update(Eo *obj, Efl_Loop_Handler_Data *pd) +{ + Ecore_Fd_Handler_Flags flags = _handler_flags_get(pd); + + ecore_main_fd_handler_active_set(pd->handler_fd, flags); + if (pd->references.prepare) + ecore_main_fd_handler_prepare_callback_set + (pd->handler_fd, _cb_handler_prepare, obj); + else + ecore_main_fd_handler_prepare_callback_set + (pd->handler_fd, NULL, NULL); +} + +static void +_handler_reset(Eo *obj, Efl_Loop_Handler_Data *pd) +{ + if ((pd->fd < 0) && (!pd->win32)) + { + _handler_clear(pd); + return; + } + + if ((!pd->constructed) || (!pd->finalized)) return; + + if (pd->fd >= 0) + { + Ecore_Fd_Cb buffer_func = NULL; + void *buffer_data = NULL; + + if (pd->references.buffer > 0) + { + buffer_func = _cb_handler_buffer; + buffer_data = obj; + } + + if (pd->handler_fd) + _handler_active_update(obj, pd); + else + { + Ecore_Fd_Handler_Flags flags = _handler_flags_get(pd); + + if (pd->file) + pd->handler_fd = _ecore_main_fd_handler_add + (pd->loop, pd->loop_data, obj, pd->fd, flags, + _cb_handler_fd, obj, buffer_func, buffer_data, + EINA_TRUE); + else + pd->handler_fd = _ecore_main_fd_handler_add + (pd->loop, pd->loop_data, obj, pd->fd, flags, + _cb_handler_fd, obj, buffer_func, buffer_data, + EINA_FALSE); + if (pd->handler_fd) _handler_active_update(obj, pd); + } + } + else if (pd->win32) + { + pd->handler_win32 = _ecore_main_win32_handler_add + (pd->loop, pd->loop_data, obj, pd->win32, _cb_handler_win32, obj); + } +} + +static Eina_Bool +_event_references_update(Efl_Loop_Handler_Data *pd, const Efl_Event *event, int increment) +{ + const Efl_Callback_Array_Item *array = event->info; + int i; + Eina_Bool need_reset = EINA_FALSE; + + for (i = 0; array[i].desc != NULL; i++) + { +#define REFERENCES_MAP(_desc, _refs) \ + if (array[i].desc == _desc) { \ + pd->references._refs += increment; \ + need_reset = EINA_TRUE; \ + continue; \ + } + REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_READ, read); + REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_WRITE, write); + REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_ERROR, error); + REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_BUFFER, buffer); + REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_PREPARE, prepare); + } + return need_reset; +} + +////////////////////////////////////////////////////////////////////////// + +static Eina_Bool +_cb_handler_fd(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED) +{ + Eo *obj = data; + + if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) + efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_READ, NULL); + if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE)) + efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_WRITE, NULL); + if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) + efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_ERROR, NULL); + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_cb_handler_buffer(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED) +{ + Eo *obj = data; + + efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_BUFFER, NULL); + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_cb_handler_win32(void *data, Ecore_Win32_Handler *win32_handler EINA_UNUSED) +{ + Eo *obj = data; + + efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_READ, NULL); + return ECORE_CALLBACK_RENEW; +} + +static void +_cb_handler_prepare(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED) +{ + Eo *obj = data; + + efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_PREPARE, NULL); +} + +static void +_cb_event_callback_add(void *data, const Efl_Event *event) +{ + Efl_Loop_Handler_Data *pd = data; + if (_event_references_update(pd, event, 1)) + _handler_reset(event->object, pd); +} + +static void +_cb_event_callback_del(void *data, const Efl_Event *event) +{ + Efl_Loop_Handler_Data *pd = data; + if (_event_references_update(pd, event, -1)) + _handler_reset(event->object, pd); +} + +////////////////////////////////////////////////////////////////////////// + +EFL_CALLBACKS_ARRAY_DEFINE(_event_callback_watch, + { EFL_EVENT_CALLBACK_ADD, _cb_event_callback_add }, + { EFL_EVENT_CALLBACK_DEL, _cb_event_callback_del }); + +static void +_efl_loop_handler_active_set(Eo *obj, Efl_Loop_Handler_Data *pd, Efl_Loop_Handler_Flags flags) +{ + pd->flags = flags; + _handler_reset(obj, pd); +} + +static Efl_Loop_Handler_Flags +_efl_loop_handler_active_get(Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd) +{ + return pd->flags; +} + +static void +_efl_loop_handler_fd_set(Eo *obj, Efl_Loop_Handler_Data *pd, int fd) +{ + pd->fd = fd; + pd->file = EINA_FALSE; + pd->win32 = NULL; + _handler_reset(obj, pd); +} + +static int +_efl_loop_handler_fd_get(Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd) +{ + if (pd->win32) return -1; + return pd->file ? -1 : pd->fd; +} + +static void +_efl_loop_handler_fd_file_set(Eo *obj, Efl_Loop_Handler_Data *pd, int fd) +{ + pd->fd = fd; + pd->file = EINA_TRUE; + pd->win32 = NULL; + _handler_reset(obj, pd); +} + +static int +_efl_loop_handler_fd_file_get(Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd) +{ + if (pd->win32) return -1; + return pd->file ? pd->fd : -1; +} + +static void +_efl_loop_handler_win32_set(Eo *obj, Efl_Loop_Handler_Data *pd, void *handle) +{ + pd->fd = -1; + pd->file = EINA_FALSE; + pd->win32 = handle; + _handler_reset(obj, pd); +} + +static void * +_efl_loop_handler_win32_get(Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd) +{ + return pd->win32; +} + +static void +_efl_loop_handler_efl_object_parent_set(Eo *obj, Efl_Loop_Handler_Data *pd, Efl_Object *parent) +{ + efl_parent_set(efl_super(obj, MY_CLASS), parent); + + if ((!pd->constructed) || (!pd->finalized)) return; + + _handler_clear(pd); + + if (pd->loop) + { + pd->loop_data->fd_handlers_obj = eina_list_remove + (pd->loop_data->fd_handlers_obj, obj); + pd->loop = NULL; + pd->loop_data = NULL; + } + + if (parent == NULL) return; + + pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS); + pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS); + if (pd->loop_data) + pd->loop_data->fd_handlers_obj = + eina_list_append(pd->loop_data->fd_handlers_obj, obj); + _handler_reset(obj, pd); +} + +static Efl_Object * +_efl_loop_handler_efl_object_constructor(Eo *obj, Efl_Loop_Handler_Data *pd) +{ + efl_constructor(efl_super(obj, MY_CLASS)); + efl_event_callback_array_add(obj, _event_callback_watch(), pd); + pd->constructed = EINA_TRUE; + return obj; +} + +static Efl_Object * +_efl_loop_handler_efl_object_finalize(Eo *obj, Efl_Loop_Handler_Data *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_data) + pd->loop_data->fd_handlers_obj = + eina_list_append(pd->loop_data->fd_handlers_obj, obj); + pd->finalized = EINA_TRUE; + _handler_reset(obj, pd); + return efl_finalize(efl_super(obj, MY_CLASS)); +} + +static void +_efl_loop_handler_efl_object_destructor(Eo *obj, Efl_Loop_Handler_Data *pd) +{ + efl_destructor(efl_super(obj, MY_CLASS)); + + if (pd->loop_data) + pd->loop_data->fd_handlers_obj = + eina_list_remove(pd->loop_data->fd_handlers_obj, obj); + _handler_clear(pd); +} + +#include "efl_loop_handler.eo.c" diff --git a/src/lib/ecore/efl_loop_handler.eo b/src/lib/ecore/efl_loop_handler.eo new file mode 100644 index 0000000000..02d1109486 --- /dev/null +++ b/src/lib/ecore/efl_loop_handler.eo @@ -0,0 +1,72 @@ +import eina_types; + +enum Efl.Loop.Handler.Flags { + [[ A set of flags that can be OR'd together to indicate which are + desired ]] + none = 0, [[ No I/O is desired (generally useless) ]] + read = 1, [[ Reading is desired ]] + write = 2, [[ Writing is desired ]] + error = 4, [[ Error channel input is desired ]] +} + +class Efl.Loop.Handler (Efl.Object) +{ + [[ An object that describes an low-level source of I/O to listen to + for available data to be read or written, depending on the OS and data + source type. When I/O becomes available various events are produced + and the callbacks attached to them will be called. ]] + methods { + @property active { + [[ This sets what kind of I/O should be listened to only when + using a fd or fd_file for the handler ]] + set { } + get { } + values { + flags: Efl.Loop.Handler.Flags; [[ The flags that indicate what kind of I/O should be listened for like read, write or error channels. ]] + } + } + @property fd { + [[ Controls a file desciptor to listen to for I/O that points + to a data pipe such as a device, socket or pipe etc. ]] + set { } + get { } + values { + fd: int; [[ The file descriptor ]] + } + } + @property fd_file { + [[ Controls a file descriptor to listen to for I/O that + specifically points to a file in storage and not a device, socket or + pipe etc. ]] + set { } + get { } + values { + fd: int; [[ The file descriptor ]] + } + } + @property win32 { + [[ Controls a windows win32 object handle to listen to for I/O. + When it becomes available for any data the read event will be + produced. ]] + set { } + get { } + values { + handle: void_ptr; [[ A win32 object handle ]] + } + } + } + events { + read; [[ Called when a read happened on the descriptor ]] + write; [[ Called when a write happened on the descriptor ]] + error; [[ Called when a error occurred on the descriptor ]] + buffer; [[ Called when buffered data already read from the descriptor should be processed ]] + prepare; [[ Called when preparing a descriptor for listening ]] + } + + implements { + Efl.Object.constructor; + Efl.Object.destructor; + Efl.Object.finalize; + Efl.Object.parent { set; } + } +} diff --git a/src/lib/ecore/efl_loop_message.c b/src/lib/ecore/efl_loop_message.c new file mode 100644 index 0000000000..dc93020e6f --- /dev/null +++ b/src/lib/ecore/efl_loop_message.c @@ -0,0 +1,83 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include "Ecore.h" +#include "ecore_private.h" + +#define MY_CLASS EFL_LOOP_MESSAGE_CLASS + +#include "ecore_main_common.h" + +typedef struct _Efl_Loop_Message_Data Efl_Loop_Message_Data; + +struct _Efl_Loop_Message_Data +{ + Eina_Inlist *send_list_node; + Eo *loop; + Efl_Loop_Data *loop_data; +}; + +///////////////////////////////////////////////////////////////////////////// + +void +_efl_loop_message_send_info_set(Eo *obj, Eina_Inlist *node, Eo *loop, Efl_Loop_Data *loop_data) +{ + Efl_Loop_Message_Data *pd = efl_data_scope_get(obj, MY_CLASS); + if (!pd) return; + pd->send_list_node = node; + pd->loop = loop; + pd->loop_data = loop_data; +} + +void +_efl_loop_message_unsend(Eo *obj) +{ + Efl_Loop_Message_Data *pd = efl_data_scope_get(obj, MY_CLASS); + if (!pd) return; + if ((!pd->send_list_node) || (!pd->loop)) return; + + Message *msg = (Message *)pd->send_list_node; + msg->delete_me = EINA_TRUE; +} + +///////////////////////////////////////////////////////////////////////////// + +EOLIAN static Efl_Object * +_efl_loop_message_efl_object_constructor(Eo *obj, Efl_Loop_Message_Data *pd EINA_UNUSED) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + return obj; +} + +EOLIAN static void +_efl_loop_message_efl_object_destructor(Eo *obj, Efl_Loop_Message_Data *pd) +{ + if ((pd->send_list_node) && (pd->loop_data)) + { + Message *msg = (Message *)pd->send_list_node; + + msg->delete_me = EINA_TRUE; + msg->message = NULL; + msg->handler = NULL; + if (pd->loop_data->message_walking == 0) + { + pd->loop_data->message_queue = + eina_inlist_remove(pd->loop_data->message_queue, + pd->send_list_node); + } + pd->send_list_node = NULL; + pd->loop = NULL; + pd->loop_data = NULL; + free(pd->send_list_node); + } + efl_destructor(efl_super(obj, MY_CLASS)); +} + +#include "efl_loop_message.eo.c" diff --git a/src/lib/ecore/efl_loop_message.eo b/src/lib/ecore/efl_loop_message.eo new file mode 100644 index 0000000000..7368c28802 --- /dev/null +++ b/src/lib/ecore/efl_loop_message.eo @@ -0,0 +1,13 @@ +import efl_types; +import eina_types; + +class Efl.Loop.Message (Efl.Object) +{ + [[ ]] + methods { + } + implements { + Efl.Object.constructor; + Efl.Object.destructor; + } +} diff --git a/src/lib/ecore/efl_loop_message_handler.c b/src/lib/ecore/efl_loop_message_handler.c new file mode 100644 index 0000000000..04862da756 --- /dev/null +++ b/src/lib/ecore/efl_loop_message_handler.c @@ -0,0 +1,145 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include "Ecore.h" +#include "ecore_private.h" + +#define MY_CLASS EFL_LOOP_MESSAGE_HANDLER_CLASS + +#include "ecore_main_common.h" + +typedef struct _Efl_Loop_Message_Handler_Data Efl_Loop_Message_Handler_Data; + +struct _Efl_Loop_Message_Handler_Data +{ + Eo *loop; + Efl_Loop_Data *loop_data; +}; + +EOLIAN static Efl_Loop_Message * +_efl_loop_message_handler_message_add(Eo *obj, Efl_Loop_Message_Handler_Data *pd EINA_UNUSED) +{ + // XXX: implement message object cache + Efl_Loop_Message *message = efl_add(EFL_LOOP_MESSAGE_CLASS, obj); + if (!message) return NULL; + // XXX: track added messages not sent yet ... + return message; +} + +EOLIAN static void +_efl_loop_message_handler_message_send(Eo *obj, Efl_Loop_Message_Handler_Data *pd, Efl_Loop_Message *message) +{ + Message *msg; + + if (EINA_UNLIKELY(!pd->loop)) + { + pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS); + if (!pd->loop) return; + pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS); + if (!pd->loop_data) + { + pd->loop = NULL; + return; + } + } + msg = calloc(1, sizeof(Message)); + if (msg) + { + msg->handler = obj; + msg->message = message; + pd->loop_data->message_queue = eina_inlist_append + (pd->loop_data->message_queue, EINA_INLIST_GET(msg)); + _efl_loop_message_send_info_set(message, EINA_INLIST_GET(msg), + pd->loop, pd->loop_data); + return; + } + efl_del(message); +} + +EOLIAN static void +_efl_loop_message_handler_message_call(Eo *obj, Efl_Loop_Message_Handler_Data *pd, Efl_Loop_Message *message) +{ + Message *msg; + unsigned int n = 0; + Eina_Bool found = EINA_FALSE; + + if (!pd->loop) return; + EINA_INLIST_FOREACH(pd->loop_data->message_queue, msg) + { + n++; + if (msg->message != message) continue; + found = EINA_TRUE; + msg->message = NULL; + msg->handler = NULL; + _efl_loop_message_send_info_set(message, NULL, NULL, NULL); + if ((pd->loop_data->message_walking == 0) || (n == 1)) + { + pd->loop_data->message_queue = + eina_inlist_remove(pd->loop_data->message_queue, + EINA_INLIST_GET(msg)); + free(msg); + } + else + msg->delete_me = EINA_TRUE; + break; + } + efl_event_callback_call(obj, EFL_LOOP_MESSAGE_HANDLER_EVENT_MESSAGE, + message); + // XXX: implement message object cache... + if (message) efl_del(message); + if (found) return; + ERR("Cannot find message called object %p on message queue", message); +} + +EOLIAN static Eina_Bool +_efl_loop_message_handler_message_clear(Eo *obj, Efl_Loop_Message_Handler_Data *pd) +{ + Eina_Inlist *tmp; + Message *msg; + + if (!pd->loop) return EINA_FALSE; + if (!pd->loop_data->message_queue) return EINA_FALSE; + EINA_INLIST_FOREACH_SAFE(pd->loop_data->message_queue, tmp, msg) + { + if (msg->handler == obj) + { + Eo *message = msg->message; + + msg->delete_me = EINA_TRUE; + msg->handler = NULL; + msg->message = NULL; + _efl_loop_message_send_info_set(message, NULL, NULL, NULL); + if (pd->loop_data->message_walking == 0) + { + pd->loop_data->message_queue = + eina_inlist_remove(pd->loop_data->message_queue, + EINA_INLIST_GET(msg)); + free(msg); + } + if (message) efl_del(message); + } + } + return EINA_FALSE; +} + +EOLIAN static Efl_Object * +_efl_loop_message_handler_efl_object_constructor(Eo *obj, Efl_Loop_Message_Handler_Data *pd EINA_UNUSED) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + return obj; +} + +EOLIAN static void +_efl_loop_message_handler_efl_object_destructor(Eo *obj, Efl_Loop_Message_Handler_Data *pd EINA_UNUSED) +{ + efl_destructor(efl_super(obj, MY_CLASS)); +} + +#include "efl_loop_message_handler.eo.c" diff --git a/src/lib/ecore/efl_loop_message_handler.eo b/src/lib/ecore/efl_loop_message_handler.eo new file mode 100644 index 0000000000..b934364013 --- /dev/null +++ b/src/lib/ecore/efl_loop_message_handler.eo @@ -0,0 +1,38 @@ +import efl_types; +import eina_types; + +class Efl.Loop.Message.Handler (Efl.Object) +{ + [[ ]] + methods { + message_add { + [[ ]] + return: Efl.Loop.Message; [[ ]] + } + message_send { + [[ Plase the message on the queue to be called later ]] + params { + @in message: Efl.Loop.Message; [[ ]] + } + } + message_call { + [[ Overide me (implement) then call super after calling the + right callback type if you specialize the message type + ]] + params { + @in message: Efl.Loop.Message; [[ Generic message event type ]] + } + } + message_clear { + [[ ]] + return: bool; [[ ]] + } + } + events { + message: Efl.Loop.Message; [[ ]] + } + implements { + Efl.Object.constructor; + Efl.Object.destructor; + } +} diff --git a/src/lib/ecore/efl_promise.c b/src/lib/ecore/efl_promise.c index f95e12940e..17e95489c6 100644 --- a/src/lib/ecore/efl_promise.c +++ b/src/lib/ecore/efl_promise.c @@ -21,6 +21,8 @@ struct _Efl_Promise_Msg struct _Efl_Promise_Data { + Eo *loop; + Efl_Loop_Data *loop_data; Efl_Promise *promise; Efl_Promise_Msg *message; Eina_List *futures; @@ -589,7 +591,6 @@ void ecore_loop_promise_fulfill(Eo *obj) { Efl_Promise_Data *pd = efl_data_scope_get(obj, EFL_PROMISE_CLASS); - _efl_promise_propagate(obj, pd); } @@ -675,16 +676,8 @@ _efl_promise_progress_set(Eo *obj, Efl_Promise_Data *pd, const void *p) } } -static Efl_Object * -_efl_promise_efl_object_constructor(Eo *obj, Efl_Promise_Data *pd) -{ - pd->promise = obj; - - return efl_constructor(efl_super(obj, EFL_PROMISE_CLASS)); -} - static void -_efl_promise_efl_object_destructor(Eo *obj, Efl_Promise_Data *pd) +_efl_promise_loop_clear(Eo *obj, Efl_Promise_Data *pd) { pd->nodelay = EINA_TRUE; @@ -698,7 +691,7 @@ _efl_promise_efl_object_destructor(Eo *obj, Efl_Promise_Data *pd) if (pd->message && !pd->propagated) { - ecore_loop_promise_unregister(efl_provider_find(obj, EFL_LOOP_CLASS), obj); + ecore_loop_promise_unregister(pd->loop, obj); _efl_promise_propagate(obj, pd); } @@ -708,7 +701,28 @@ _efl_promise_efl_object_destructor(Eo *obj, Efl_Promise_Data *pd) _efl_promise_msg_free(pd->message); pd->message = NULL; } +} +static void +_efl_promise_efl_object_parent_set(Eo *obj, Efl_Promise_Data *pd, Efl_Object *parent) +{ + if (!parent) _efl_promise_loop_clear(obj, pd); + efl_parent_set(efl_super(obj, EFL_PROMISE_CLASS), parent); + pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS); + pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS); +} + +static Efl_Object * +_efl_promise_efl_object_constructor(Eo *obj, Efl_Promise_Data *pd) +{ + pd->promise = obj; + return efl_constructor(efl_super(obj, EFL_PROMISE_CLASS)); +} + +static void +_efl_promise_efl_object_destructor(Eo *obj, Efl_Promise_Data *pd) +{ + _efl_promise_loop_clear(obj, pd); efl_destructor(efl_super(obj, EFL_PROMISE_CLASS)); } diff --git a/src/lib/ecore/efl_promise.eo b/src/lib/ecore/efl_promise.eo index 40a164b343..be1a7dcd3c 100644 --- a/src/lib/ecore/efl_promise.eo +++ b/src/lib/ecore/efl_promise.eo @@ -73,5 +73,6 @@ class Efl.Promise (Efl.Loop.Consumer) implements { Efl.Object.destructor; Efl.Object.constructor; + Efl.Object.parent { set; } } }