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:
Cedric BAIL 2008-11-10 16:37:52 +00:00
parent 5257321d9a
commit 25f4acee01
4 changed files with 222 additions and 25 deletions

View File

@ -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

View File

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

View File

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

View File

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