This is a quick fix for edje match memory consuption. It is not the best
solution, but the fastest to implement without breaking edje file format. So now, when a callback or a program don't use globbing charactere (*, ?, [] and \), the match are put in a little rbtree instead of the big automate matrix. This patch could potentially break edje user, if you experience anything strange with your edje file, please report. SVN revision: 37577
This commit is contained in:
parent
5257321d9a
commit
25f4acee01
|
@ -214,19 +214,28 @@ static void
|
|||
_edje_programs_patterns_clean(Edje *ed)
|
||||
{
|
||||
_edje_signals_sources_patterns_clean(&ed->patterns.programs);
|
||||
|
||||
eina_rbtree_delete(ed->patterns.programs.exact_match,
|
||||
EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
|
||||
NULL);
|
||||
ed->patterns.programs.exact_match = NULL;
|
||||
|
||||
ed->patterns.programs.globing = eina_list_free(ed->patterns.programs.globing);
|
||||
}
|
||||
|
||||
static void
|
||||
_edje_programs_patterns_init(Edje *ed)
|
||||
{
|
||||
Edje_Signals_Sources_Patterns *ssp = &ed->patterns.programs;
|
||||
Eina_List *programs = ed->collection->programs;
|
||||
|
||||
if (ssp->signals_patterns)
|
||||
return;
|
||||
|
||||
ssp->signals_patterns = edje_match_programs_signal_init(programs);
|
||||
ssp->sources_patterns = edje_match_programs_source_init(programs);
|
||||
ssp->globing = edje_match_program_hash_build(ed->collection->programs,
|
||||
&ssp->exact_match);
|
||||
|
||||
ssp->signals_patterns = edje_match_programs_signal_init(ssp->globing);
|
||||
ssp->sources_patterns = edje_match_programs_source_init(ssp->globing);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -55,7 +55,7 @@ _edje_match_states_alloc(Edje_Patterns *ppat, int n)
|
|||
unsigned char *states;
|
||||
unsigned char *has;
|
||||
|
||||
size_t i;
|
||||
int i;
|
||||
|
||||
states_size = sizeof (*l->states) * array_len;
|
||||
ALIGN(states_size);
|
||||
|
@ -116,9 +116,9 @@ _edje_match_states_insert(Edje_States *list,
|
|||
}
|
||||
|
||||
static void
|
||||
_edje_match_states_clear(Edje_States *list,
|
||||
size_t patterns_size,
|
||||
size_t patterns_max_length)
|
||||
_edje_match_states_clear(Edje_States *list,
|
||||
__UNUSED__ size_t patterns_size,
|
||||
__UNUSED__ size_t patterns_max_length)
|
||||
{
|
||||
list->size = 0;
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ _edje_match_patterns_exec_init_states(Edje_States *states,
|
|||
Type *data; \
|
||||
size_t j; \
|
||||
\
|
||||
data = eina_list_data_get(lst); \
|
||||
data = eina_list_data_get(lst); \
|
||||
if (!data) \
|
||||
{ \
|
||||
free(r); \
|
||||
|
@ -562,3 +562,134 @@ _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp)
|
|||
ssp->signals_patterns = NULL;
|
||||
ssp->sources_patterns = NULL;
|
||||
}
|
||||
|
||||
static Eina_Rbtree_Direction
|
||||
_edje_signal_source_node_cmp(const Edje_Signal_Source_Char *n1,
|
||||
const Edje_Signal_Source_Char *n2,
|
||||
__UNUSED__ void *data)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
cmp = strcmp(n1->signal, n2->signal);
|
||||
if (cmp) return cmp < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
|
||||
|
||||
return strcmp(n1->source, n2->source) < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
|
||||
}
|
||||
|
||||
static int
|
||||
_edje_signal_source_key_cmp(const Edje_Signal_Source_Char *node,
|
||||
const char *signal,
|
||||
__UNUSED__ int length,
|
||||
const char *source)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
cmp = strcmp(node->signal, signal);
|
||||
if (cmp) return cmp;
|
||||
|
||||
return strcmp(node->source, source);
|
||||
}
|
||||
|
||||
|
||||
Eina_List *
|
||||
edje_match_program_hash_build(const Eina_List *callbacks,
|
||||
Eina_Rbtree **tree)
|
||||
{
|
||||
Eina_List *result = NULL;
|
||||
Eina_Rbtree *new = NULL;
|
||||
Edje_Program *program;
|
||||
const Eina_List *l;
|
||||
|
||||
EINA_LIST_FOREACH(callbacks, l, program)
|
||||
{
|
||||
if (program->signal && strpbrk(program->signal, "*?[\\") == NULL
|
||||
&& program->source && strpbrk(program->source, "*?[\\") == NULL)
|
||||
{
|
||||
Edje_Signal_Source_Char *item;
|
||||
|
||||
item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, program->signal, 0,
|
||||
EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), program->source);
|
||||
if (!item)
|
||||
{
|
||||
item = malloc(sizeof (Edje_Signal_Source_Char));
|
||||
if (!item) continue ;
|
||||
|
||||
item->signal = program->signal;
|
||||
item->source = program->source;
|
||||
item->list = NULL;
|
||||
|
||||
new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
|
||||
EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
|
||||
}
|
||||
|
||||
item->list = eina_list_prepend(item->list, program);
|
||||
}
|
||||
else
|
||||
result = eina_list_prepend(result, program);
|
||||
}
|
||||
|
||||
*tree = new;
|
||||
return result;
|
||||
}
|
||||
|
||||
Eina_List *
|
||||
edje_match_callback_hash_build(const Eina_List *callbacks,
|
||||
Eina_Rbtree **tree)
|
||||
{
|
||||
Eina_List *result = NULL;
|
||||
Eina_Rbtree *new = NULL;
|
||||
Edje_Signal_Callback *callback;
|
||||
const Eina_List *l;
|
||||
|
||||
EINA_LIST_FOREACH(callbacks, l, callback)
|
||||
{
|
||||
if (callback->signal && strpbrk(callback->signal, "*?[\\") == NULL
|
||||
&& callback->source && strpbrk(callback->source, "*?[\\") == NULL)
|
||||
{
|
||||
Edje_Signal_Source_Char *item;
|
||||
|
||||
item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, callback->signal, 0,
|
||||
EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callback->source);
|
||||
if (!item)
|
||||
{
|
||||
item = malloc(sizeof (Edje_Signal_Source_Char));
|
||||
if (!item) continue ;
|
||||
|
||||
item->signal = callback->signal;
|
||||
item->source = callback->source;
|
||||
item->list = NULL;
|
||||
|
||||
new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
|
||||
EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
|
||||
}
|
||||
|
||||
item->list = eina_list_prepend(item->list, callback);
|
||||
}
|
||||
else
|
||||
result = eina_list_prepend(result, callback);
|
||||
}
|
||||
|
||||
*tree = new;
|
||||
return result;
|
||||
}
|
||||
|
||||
const Eina_List *
|
||||
edje_match_signal_source_hash_get(const char *signal,
|
||||
const char *source,
|
||||
const Eina_Rbtree *tree)
|
||||
{
|
||||
Edje_Signal_Source_Char *lookup;
|
||||
|
||||
lookup = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(tree, signal, 0,
|
||||
EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), source);
|
||||
|
||||
if (lookup) return lookup->list;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
edje_match_signal_source_free(Edje_Signal_Source_Char *key, __UNUSED__ void *data)
|
||||
{
|
||||
eina_list_free(key->list);
|
||||
free(key);
|
||||
}
|
||||
|
|
|
@ -581,11 +581,25 @@ typedef struct _Edje_Var_Hash Edje_Var_Hash;
|
|||
typedef struct _Edje_Var_Animator Edje_Var_Animator;
|
||||
typedef struct _Edje_Var_Timer Edje_Var_Timer;
|
||||
typedef struct _Edje_Var_Pool Edje_Var_Pool;
|
||||
typedef struct _Edje_Signal_Source_Char Edje_Signal_Source_Char;
|
||||
|
||||
struct _Edje_Signal_Source_Char
|
||||
{
|
||||
EINA_RBTREE;
|
||||
|
||||
const char *signal;
|
||||
const char *source;
|
||||
|
||||
Eina_List *list;
|
||||
};
|
||||
|
||||
struct _Edje_Signals_Sources_Patterns
|
||||
{
|
||||
Edje_Patterns *signals_patterns;
|
||||
Edje_Patterns *sources_patterns;
|
||||
|
||||
Eina_Rbtree *exact_match;
|
||||
Eina_List *globing;
|
||||
};
|
||||
|
||||
typedef struct _Edje_Signals_Sources_Patterns Edje_Signals_Sources_Patterns;
|
||||
|
@ -952,6 +966,15 @@ int edje_match_callback_exec(const Edje_Patterns *ppat_signal,
|
|||
|
||||
void edje_match_patterns_free(Edje_Patterns *ppat);
|
||||
|
||||
Eina_List *edje_match_program_hash_build(const Eina_List *callbacks,
|
||||
Eina_Rbtree **tree);
|
||||
Eina_List *edje_match_callback_hash_build(const Eina_List *callbacks,
|
||||
Eina_Rbtree **tree);
|
||||
const Eina_List *edje_match_signal_source_hash_get(const char *signal,
|
||||
const char *source,
|
||||
const Eina_Rbtree *tree);
|
||||
void edje_match_signal_source_free(Edje_Signal_Source_Char *key, void *data);
|
||||
|
||||
EAPI extern Eet_Data_Descriptor *_edje_edd_edje_file;
|
||||
EAPI extern Eet_Data_Descriptor *_edje_edd_edje_style;
|
||||
EAPI extern Eet_Data_Descriptor *_edje_edd_edje_style_tag;
|
||||
|
|
|
@ -860,6 +860,13 @@ void
|
|||
_edje_callbacks_patterns_clean(Edje *ed)
|
||||
{
|
||||
_edje_signals_sources_patterns_clean(&ed->patterns.callbacks);
|
||||
|
||||
eina_rbtree_delete(ed->patterns.callbacks.exact_match,
|
||||
EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
|
||||
NULL);
|
||||
ed->patterns.callbacks.exact_match = NULL;
|
||||
|
||||
ed->patterns.callbacks.globing = eina_list_free(ed->patterns.callbacks.globing);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -870,8 +877,11 @@ _edje_callbacks_patterns_init(Edje *ed)
|
|||
if (ssp->signals_patterns)
|
||||
return;
|
||||
|
||||
ssp->signals_patterns = edje_match_callback_signal_init(ed->callbacks);
|
||||
ssp->sources_patterns = edje_match_callback_source_init(ed->callbacks);
|
||||
ssp->globing = edje_match_callback_hash_build(ed->callbacks,
|
||||
&ssp->exact_match);
|
||||
|
||||
ssp->signals_patterns = edje_match_callback_signal_init(ssp->globing);
|
||||
ssp->sources_patterns = edje_match_callback_source_init(ssp->globing);
|
||||
}
|
||||
|
||||
/* FIXME: what if we delete the evas object??? */
|
||||
|
@ -942,14 +952,24 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src)
|
|||
#endif
|
||||
if (ed->collection->programs)
|
||||
{
|
||||
if (edje_match_programs_exec(ed->patterns.programs.signals_patterns,
|
||||
ed->patterns.programs.sources_patterns,
|
||||
sig,
|
||||
src,
|
||||
ed->collection->programs,
|
||||
_edje_glob_callback,
|
||||
&data) == 0)
|
||||
goto break_prog;
|
||||
const Eina_List *match;
|
||||
const Eina_List *l;
|
||||
Edje_Program *pr;
|
||||
|
||||
if (ed->patterns.programs.globing)
|
||||
if (edje_match_programs_exec(ed->patterns.programs.signals_patterns,
|
||||
ed->patterns.programs.sources_patterns,
|
||||
sig,
|
||||
src,
|
||||
ed->patterns.programs.globing,
|
||||
_edje_glob_callback,
|
||||
&data) == 0)
|
||||
goto break_prog;
|
||||
|
||||
match = edje_match_signal_source_hash_get(sig, src,
|
||||
ed->patterns.programs.exact_match);
|
||||
EINA_LIST_FOREACH(match, l, pr)
|
||||
_edje_glob_callback(pr, &data);
|
||||
}
|
||||
|
||||
#ifdef EDJE_PROGRAM_CACHE
|
||||
|
@ -994,18 +1014,32 @@ _edje_emit_cb(Edje *ed, const char *sig, const char *src)
|
|||
|
||||
if (ed->callbacks)
|
||||
{
|
||||
int r;
|
||||
Edje_Signal_Callback *escb;
|
||||
const Eina_List *match;
|
||||
const Eina_List *l;
|
||||
int r = 1;
|
||||
|
||||
_edje_callbacks_patterns_init(ed);
|
||||
r = edje_match_callback_exec(ed->patterns.callbacks.signals_patterns,
|
||||
ed->patterns.callbacks.sources_patterns,
|
||||
sig,
|
||||
src,
|
||||
ed->callbacks,
|
||||
ed);
|
||||
if (ed->patterns.callbacks.globing)
|
||||
r = edje_match_callback_exec(ed->patterns.callbacks.signals_patterns,
|
||||
ed->patterns.callbacks.sources_patterns,
|
||||
sig,
|
||||
src,
|
||||
ed->patterns.callbacks.globing,
|
||||
ed);
|
||||
|
||||
if (!r)
|
||||
goto break_prog;
|
||||
|
||||
match = edje_match_signal_source_hash_get(sig, src,
|
||||
ed->patterns.callbacks.exact_match);
|
||||
EINA_LIST_FOREACH(match, l, escb)
|
||||
if ((!escb->just_added) && (!escb->delete_me))
|
||||
{
|
||||
escb->func(escb->data, ed->obj, sig, src);
|
||||
if (_edje_block_break(ed))
|
||||
goto break_prog;
|
||||
}
|
||||
}
|
||||
|
||||
ed->walking_callbacks = 0;
|
||||
|
|
Loading…
Reference in New Issue