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; } } }