forked from enlightenment/efl
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:
parent
081d55c51c
commit
c226a11bfe
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue