From 2c283ada65d955605c70c0592b154d67eda646b9 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Thu, 24 Nov 2011 11:51:11 +0000 Subject: [PATCH] fix awful event re-propagation between every part and parent and part and.... u get the idea. this made an n^m list of messages... where n was 3 of messages sent and m was # of child parts (42 of them)... this caused a silly 3 of timers to be allocated... don't ask how many. in a simple snapshot i saw 101mb of timers allocated... and i was just starting... anyway - this makes the propagatiopn not propagate down and then back up again... and it only needs 1 timer allocated to handle a re-schedule of processing messages. not N. "leak" that was just a massive memory spike) is now fixed. SVN revision: 65571 --- legacy/edje/src/lib/edje_load.c | 9 ++-- legacy/edje/src/lib/edje_match.c | 21 ++++++--- legacy/edje/src/lib/edje_message_queue.c | 31 +++++++++++--- legacy/edje/src/lib/edje_private.h | 13 ++++-- legacy/edje/src/lib/edje_program.c | 54 ++++++++++++++++++------ 5 files changed, 96 insertions(+), 32 deletions(-) diff --git a/legacy/edje/src/lib/edje_load.c b/legacy/edje/src/lib/edje_load.c index c9b77da5c9..644bb7cd9d 100644 --- a/legacy/edje/src/lib/edje_load.c +++ b/legacy/edje/src/lib/edje_load.c @@ -731,8 +731,9 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g group_path = eina_list_remove(group_path, group_path_entry); eina_stringshare_del(group_path_entry); - edje_object_signal_callback_add(child_obj, "*", "*", - _cb_signal_repeat, obj); + edje_object_propagate_callback_add(child_obj, + _cb_signal_repeat, + obj); if (rp->part->type == EDJE_PART_TYPE_GROUP) { _edje_real_part_swallow(rp, child_obj, EINA_TRUE); @@ -1519,6 +1520,6 @@ _cb_signal_repeat(void *data, Evas_Object *obj, const char *sig, const char *sou emsg.sig = sig; emsg.src = alias ? alias : new_src; emsg.data = NULL; - _edje_message_send(ed_parent, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, - 0, &emsg); + _edje_message_send(ed_parent, EDJE_QUEUE_SCRIPT, + EDJE_MESSAGE_SIGNAL, 0, &emsg); } diff --git a/legacy/edje/src/lib/edje_match.c b/legacy/edje/src/lib/edje_match.c index 5a98cd610b..f113f7b48c 100644 --- a/legacy/edje/src/lib/edje_match.c +++ b/legacy/edje/src/lib/edje_match.c @@ -414,7 +414,8 @@ edje_match_programs_exec_check_finals(const size_t *signal_finals, const Edje_States *source_states, Edje_Program **programs, Eina_Bool (*func)(Edje_Program *pr, void *data), - void *data) + void *data, + Eina_Bool prop __UNUSED__) { size_t i; size_t j; @@ -457,7 +458,9 @@ edje_match_callback_exec_check_finals(const Edje_Patterns *singal_ppat, const char *sig, const char *source, Eina_List *callbacks, - Edje *ed) + Edje *ed, + Eina_Bool prop + ) { size_t i; size_t j; @@ -477,6 +480,7 @@ edje_match_callback_exec_check_finals(const Edje_Patterns *singal_ppat, escb = eina_list_nth(callbacks, signal_states->states[i].idx); if (escb) { + if ((prop) && (escb->propagate)) continue; if ((!escb->just_added) && (!escb->delete_me)) { @@ -574,7 +578,8 @@ edje_match_programs_exec(const Edje_Patterns *ppat_signal, const char *source, Edje_Program **programs, Eina_Bool (*func)(Edje_Program *pr, void *data), - void *data) + void *data, + Eina_Bool prop) { Edje_States *signal_result; Edje_States *source_result; @@ -600,7 +605,8 @@ edje_match_programs_exec(const Edje_Patterns *ppat_signal, source_result, programs, func, - data); + data, + prop); return r; } @@ -610,7 +616,9 @@ edje_match_callback_exec(Edje_Patterns *ppat_signal, const char *sig, const char *source, Eina_List *callbacks, - Edje *ed) + Edje *ed, + Eina_Bool prop + ) { Edje_States *signal_result; Edje_States *source_result; @@ -641,7 +649,8 @@ edje_match_callback_exec(Edje_Patterns *ppat_signal, sig, source, callbacks, - ed); + ed, + prop); ppat_signal->ref--; ppat_source->ref--; if (ppat_signal->ref <= 0) edje_match_patterns_free(ppat_signal); diff --git a/legacy/edje/src/lib/edje_message_queue.c b/legacy/edje/src/lib/edje_message_queue.c index 3ba4fd52c4..1a313a533c 100644 --- a/legacy/edje/src/lib/edje_message_queue.c +++ b/legacy/edje/src/lib/edje_message_queue.c @@ -1,5 +1,7 @@ #include "edje_private.h" +static void _edje_object_message_popornot_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg, Eina_Bool prop); + static int _injob = 0; static Ecore_Job *_job = NULL; static Ecore_Timer *_job_loss_timer = NULL; @@ -13,8 +15,8 @@ static int tmp_msgq_restart = 0; * API * *============================================================================*/ -EAPI void -edje_object_message_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg) +static void +_edje_object_message_popornot_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg, Eina_Bool prop) { Edje *ed; Eina_List *l; @@ -22,13 +24,19 @@ edje_object_message_send(Evas_Object *obj, Edje_Message_Type type, int id, void ed = _edje_fetch(obj); if (!ed) return; - _edje_message_send(ed, EDJE_QUEUE_SCRIPT, type, id, msg); + _edje_message_propornot_send(ed, EDJE_QUEUE_SCRIPT, type, id, msg, prop); EINA_LIST_FOREACH(ed->subobjs, l, o) { - edje_object_message_send(o, type, id, msg); + _edje_object_message_popornot_send(o, type, id, msg, EINA_TRUE); } } +EAPI void +edje_object_message_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg) +{ + _edje_object_message_popornot_send(obj, type, id, msg, EINA_FALSE); +} + EAPI void edje_object_message_handler_set(Evas_Object *obj, Edje_Message_Handler_Cb func, void *data) @@ -339,7 +347,7 @@ _edje_message_free(Edje_Message *em) } void -_edje_message_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg) +_edje_message_propornot_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg, Eina_Bool prop) { /* FIXME: check all malloc & strdup fails and gracefully unroll and exit */ Edje_Message *em; @@ -348,6 +356,7 @@ _edje_message_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, v em = _edje_message_new(ed, queue, type, id); if (!em) return; + em->propagated = prop; if (_job) { ecore_job_del(_job); @@ -355,7 +364,8 @@ _edje_message_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, v } if (_injob > 0) { - _job_loss_timer = ecore_timer_add(0.01, _edje_job_loss_timer, NULL); + if (_job_loss_timer) ecore_timer_del(_job_loss_timer); + _job_loss_timer = ecore_timer_add(0.001, _edje_job_loss_timer, NULL); } else { @@ -512,6 +522,12 @@ _edje_message_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, v msgq = eina_list_append(msgq, em); } +void +_edje_message_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg) +{ + _edje_message_propornot_send(ed, queue, type, id, emsg, EINA_FALSE); +} + void _edje_message_parameters_push(Edje_Message *em) { @@ -640,7 +656,8 @@ _edje_message_process(Edje_Message *em) _edje_emit_handle(em->edje, ((Edje_Message_Signal *)em->msg)->sig, ((Edje_Message_Signal *)em->msg)->src, - ((Edje_Message_Signal *)em->msg)->data); + ((Edje_Message_Signal *)em->msg)->data, + em->propagated); return; } /* if this has been queued up for the app then just call the callback */ diff --git a/legacy/edje/src/lib/edje_private.h b/legacy/edje/src/lib/edje_private.h index e42aa6c99f..8f55912b15 100644 --- a/legacy/edje/src/lib/edje_private.h +++ b/legacy/edje/src/lib/edje_private.h @@ -1291,6 +1291,7 @@ struct _Edje_Signal_Callback void *data; unsigned char just_added : 1; unsigned char delete_me : 1; + unsigned char propagate : 1; }; struct _Edje_Text_Insert_Filter_Callback @@ -1435,6 +1436,7 @@ struct _Edje_Message Edje_Message_Type type; int id; unsigned char *msg; + Eina_Bool propagated : 1; }; typedef enum _Edje_Fill @@ -1482,13 +1484,15 @@ Eina_Bool edje_match_programs_exec(const Edje_Patterns *ppat_signal, const char *source, Edje_Program **programs, Eina_Bool (*func)(Edje_Program *pr, void *data), - void *data); + void *data, + Eina_Bool prop); int edje_match_callback_exec(Edje_Patterns *ppat_signal, Edje_Patterns *ppat_source, const char *signal, const char *source, Eina_List *callbacks, - Edje *ed); + Edje *ed, + Eina_Bool prop); void edje_match_patterns_free(Edje_Patterns *ppat); @@ -1593,7 +1597,7 @@ void _edje_programs_patterns_clean(Edje *ed); void _edje_programs_patterns_init(Edje *ed); void _edje_emit(Edje *ed, const char *sig, const char *src); void _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *)); -void _edje_emit_handle(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data); +void _edje_emit_handle(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop); void _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp); void _edje_callbacks_patterns_clean(Edje *ed); @@ -1723,6 +1727,7 @@ void _edje_message_shutdown (void); void _edje_message_cb_set (Edje *ed, void (*func) (void *data, Evas_Object *obj, Edje_Message_Type type, int id, void *msg), void *data); Edje_Message *_edje_message_new (Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id); void _edje_message_free (Edje_Message *em); +void _edje_message_propornot_send (Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg, Eina_Bool prop); void _edje_message_send (Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg); void _edje_message_parameters_push (Edje_Message *em); void _edje_message_process (Edje_Message *em); @@ -1936,6 +1941,8 @@ edje_program_is_strrncmp(const char *str) return EINA_FALSE; return EINA_TRUE; } +void edje_object_propagate_callback_add(Evas_Object *obj, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data); + /* used by edje_cc - private still */ EAPI void _edje_program_insert(Edje_Part_Collection *ed, Edje_Program *p); diff --git a/legacy/edje/src/lib/edje_program.c b/legacy/edje/src/lib/edje_program.c index bd18234678..2c139e98e5 100644 --- a/legacy/edje/src/lib/edje_program.c +++ b/legacy/edje/src/lib/edje_program.c @@ -1,6 +1,6 @@ #include "edje_private.h" -static void _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data); +static void _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop); static void _edje_param_copy(Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part *dst_part, const char *dst_param); static void _edje_param_set(Edje_Real_Part *part, const char *param, const char *value); @@ -25,6 +25,31 @@ edje_frametime_get(void) return ecore_animator_frametime_get(); } +void +edje_object_propagate_callback_add(Evas_Object *obj, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data) +{ + Edje *ed; + Edje_Signal_Callback *escb; + + ed = _edje_fetch(obj); + if (!ed) return; + if (ed->delete_me) return; + escb = calloc(1, sizeof(Edje_Signal_Callback)); + escb->propagate = EINA_TRUE; + escb->signal = eina_stringshare_add("*"); + escb->source = eina_stringshare_add("*"); + escb->func = func; + escb->data = data; + ed->callbacks = eina_list_append(ed->callbacks, escb); + if (ed->walking_callbacks) + { + escb->just_added = 1; + ed->just_added_callbacks = 1; + } + else + _edje_callbacks_patterns_clean(ed); +} + EAPI void edje_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data) { @@ -1092,7 +1117,7 @@ _edje_callbacks_patterns_init(Edje *ed) /* FIXME: what if we delete the evas object??? */ void _edje_emit_handle(Edje *ed, const char *sig, const char *src, - Edje_Message_Signal_Data *sdata) + Edje_Message_Signal_Data *sdata, Eina_Bool prop) { if (ed->delete_me) return; if (!sig) sig = ""; @@ -1187,7 +1212,8 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src, src, ed->patterns.programs.u.programs.globing, _edje_glob_callback, - &data) == 0) + &data, + prop) == 0) goto break_prog; match = edje_match_signal_source_hash_get(sig, src, @@ -1214,7 +1240,7 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src, } #endif } - _edje_emit_cb(ed, sig, src, sdata); + _edje_emit_cb(ed, sig, src, sdata, prop); if (_edje_block_break(ed)) { goto break_prog; @@ -1237,7 +1263,7 @@ edje_object_signal_callback_extra_data_get(void) /* FIXME: what if we delete the evas object??? */ static void -_edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data) +_edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop) { Eina_List *l; @@ -1266,7 +1292,8 @@ _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Da sig, src, ed->patterns.callbacks.u.callbacks.globing, - ed); + ed, + prop); if (!r) goto break_prog; @@ -1274,12 +1301,15 @@ _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Da match = edje_match_signal_source_hash_get(sig, src, ed->patterns.callbacks.exact_match); EINA_LIST_FOREACH(match, l2, escb) - if ((!escb->just_added) && (!escb->delete_me)) - { - escb->func(escb->data, ed->obj, sig, src); - if (_edje_block_break(ed)) - goto break_prog; - } + { + if ((prop) && (escb->propagate)) continue; + if ((!escb->just_added) && (!escb->delete_me)) + { + escb->func(escb->data, ed->obj, sig, src); + if (_edje_block_break(ed)) + goto break_prog; + } + } } break_prog: