Eo callbacks: Improve memory footprint of callbacks.

We don't really need a double-linked-list with a pointer to the last item.
This saves us 2 pointers per callback, which is a decent improvement.
This commit is contained in:
Tom Hacohen 2013-04-11 15:06:59 +01:00
parent 081d55c51c
commit c226a11bfe
1 changed files with 59 additions and 29 deletions

View File

@ -11,12 +11,14 @@ EAPI Eo_Op EO_BASE_BASE_ID = 0;
static int event_freeze_count = 0; static int event_freeze_count = 0;
typedef struct _Eo_Callback_Description Eo_Callback_Description;
typedef struct typedef struct
{ {
Eina_Inlist *generic_data; Eina_Inlist *generic_data;
Eo ***wrefs; Eo ***wrefs;
Eina_Inlist *callbacks; Eo_Callback_Description *callbacks;
int walking_list; int walking_list;
int event_freeze_count; int event_freeze_count;
Eina_Bool deletions_waiting : 1; Eina_Bool deletions_waiting : 1;
@ -242,41 +244,58 @@ _wref_destruct(Private_Data *pd)
/* Callbacks */ /* Callbacks */
typedef struct struct _Eo_Callback_Description
{ {
EINA_INLIST; Eo_Callback_Description *next;
const Eo_Event_Description *event; const Eo_Event_Description *event;
Eo_Event_Cb func; Eo_Event_Cb func;
void *func_data; void *func_data;
Eo_Callback_Priority priority; Eo_Callback_Priority priority;
Eina_Bool delete_me : 1; Eina_Bool delete_me : 1;
} Eo_Callback_Description; };
/* Actually remove, doesn't care about walking list, or delete_me */ /* Actually remove, doesn't care about walking list, or delete_me */
static void static void
_eo_callback_remove(Private_Data *pd, Eo_Callback_Description *cb) _eo_callback_remove(Private_Data *pd, Eo_Callback_Description *cb)
{ {
pd->callbacks = eina_inlist_remove(pd->callbacks, Eo_Callback_Description *itr, *pitr;
EINA_INLIST_GET(cb));
free(cb); itr = pitr = pd->callbacks;
if (pd->callbacks == cb)
pd->callbacks = cb->next;
for ( ; itr ; )
{
Eo_Callback_Description *titr = itr;
itr = itr->next;
if (titr == cb)
{
if (pitr)
{
pitr->next = titr->next;
}
free(titr);
}
pitr = titr;
}
} }
/* Actually remove, doesn't care about walking list, or delete_me */ /* Actually remove, doesn't care about walking list, or delete_me */
static void static void
_eo_callback_remove_all(Private_Data *pd) _eo_callback_remove_all(Private_Data *pd)
{ {
Eina_Inlist *initr; while (pd->callbacks)
Eo_Callback_Description *cb = NULL;
EINA_INLIST_FOREACH_SAFE(pd->callbacks, initr, cb)
{ {
_eo_callback_remove(pd, cb); Eo_Callback_Description *next = pd->callbacks->next;
free(pd->callbacks);
pd->callbacks = next;
} }
} }
static void static void
_eo_callbacks_clear(Private_Data *pd) _eo_callbacks_clear(Private_Data *pd)
{ {
Eina_Inlist *itn;
Eo_Callback_Description *cb = NULL; Eo_Callback_Description *cb = NULL;
/* Abort if we are currently walking the list. */ /* Abort if we are currently walking the list. */
@ -289,25 +308,38 @@ _eo_callbacks_clear(Private_Data *pd)
pd->deletions_waiting = EINA_FALSE; pd->deletions_waiting = EINA_FALSE;
EINA_INLIST_FOREACH_SAFE(pd->callbacks, itn, cb) for (cb = pd->callbacks ; cb ; )
{ {
if (cb->delete_me) Eo_Callback_Description *titr = cb;
cb = cb->next;
if (titr->delete_me)
{ {
_eo_callback_remove(pd, cb); _eo_callback_remove(pd, titr);
} }
} }
} }
static int static void
_callback_priority_cmp(const void *_a, const void *_b) _eo_callbacks_sorted_insert(Private_Data *pd, Eo_Callback_Description *cb)
{ {
const Eo_Callback_Description *a, *b; Eo_Callback_Description *itr, *itrp = NULL;
a = (const Eo_Callback_Description *) _a; for (itr = pd->callbacks ; itr && (itr->priority < cb->priority) ;
b = (const Eo_Callback_Description *) _b; itr = itr->next)
if (a->priority < b->priority) {
return -1; itrp = itr;
}
if (itrp)
{
cb->next = itrp->next;
itrp->next = cb;
}
else else
return 1; {
cb->next = pd->callbacks;
pd->callbacks = cb;
}
} }
static void static void
@ -324,8 +356,7 @@ _ev_cb_priority_add(Eo *obj, void *class_data, va_list *list)
cb->func = func; cb->func = func;
cb->func_data = (void *) data; cb->func_data = (void *) data;
cb->priority = priority; cb->priority = priority;
pd->callbacks = eina_inlist_sorted_insert(pd->callbacks, _eo_callbacks_sorted_insert(pd, cb);
EINA_INLIST_GET(cb), _callback_priority_cmp);
eo_do(obj, eo_event_callback_call(EO_EV_CALLBACK_ADD, desc, NULL)); eo_do(obj, eo_event_callback_call(EO_EV_CALLBACK_ADD, desc, NULL));
} }
@ -339,7 +370,7 @@ _ev_cb_del(Eo *obj, void *class_data, va_list *list)
void *user_data = va_arg(*list, void *); void *user_data = va_arg(*list, void *);
Eo_Callback_Description *cb; Eo_Callback_Description *cb;
EINA_INLIST_FOREACH(pd->callbacks, cb) for (cb = pd->callbacks ; cb ; cb = cb->next)
{ {
if ((cb->event == desc) && (cb->func == func) && if ((cb->event == desc) && (cb->func == func) &&
(cb->func_data == user_data)) (cb->func_data == user_data))
@ -363,8 +394,6 @@ _ev_cb_call(Eo *obj, void *class_data, va_list *list)
void *event_info = va_arg(*list, void *); void *event_info = va_arg(*list, void *);
Eina_Bool *ret = va_arg(*list, Eina_Bool *); Eina_Bool *ret = va_arg(*list, Eina_Bool *);
Eo_Callback_Description *cb;
if (ret) *ret = EINA_TRUE; if (ret) *ret = EINA_TRUE;
if (event_freeze_count || pd->event_freeze_count) if (event_freeze_count || pd->event_freeze_count)
@ -374,7 +403,8 @@ _ev_cb_call(Eo *obj, void *class_data, va_list *list)
eo_ref(obj); eo_ref(obj);
pd->walking_list++; pd->walking_list++;
EINA_INLIST_FOREACH(pd->callbacks, cb) Eo_Callback_Description *cb;
for (cb = pd->callbacks ; cb ; cb = cb->next)
{ {
if (!cb->delete_me && (cb->event == desc)) if (!cb->delete_me && (cb->event == desc))
{ {