Eina_Bool func_array : 1;
};
+static int _eo_callbacks = 0;
+static Eina_Mempool *_eo_callback_mempool = NULL;
+
+static void
+_eo_callback_free(Eo_Callback_Description *cb)
+{
+ if (!cb) return;
+ eina_mempool_free(_eo_callback_mempool, cb);
+ _eo_callbacks--;
+ if (_eo_callbacks == 0)
+ {
+ eina_mempool_del(_eo_callback_mempool);
+ _eo_callback_mempool = NULL;
+ }
+}
+
+static Eo_Callback_Description *
+_eo_callback_new(void)
+{
+ Eo_Callback_Description *cb;
+ if (!_eo_callback_mempool)
+ {
+ _eo_callback_mempool = eina_mempool_add
+ ("chained_mempool",
+ NULL, NULL,
+ sizeof(Eo_Callback_Description), 256);
+ if (!_eo_callback_mempool) return NULL;
+ }
+ cb = eina_mempool_calloc(_eo_callback_mempool,
+ sizeof(Eo_Callback_Description));
+ if (!cb)
+ {
+ if (_eo_callbacks == 0)
+ {
+ eina_mempool_del(_eo_callback_mempool);
+ _eo_callback_mempool = NULL;
+ }
+ return NULL;
+ }
+ _eo_callbacks++;
+ return cb;
+}
+
/* Actually remove, doesn't care about walking list, or delete_me */
static void
_eo_callback_remove(Efl_Object_Data *pd, Eo_Callback_Description *cb)
{
Eo_Callback_Description *itr, *pitr = NULL;
- itr = pd->callbacks;
-
- for ( ; itr; )
+ for (itr = pd->callbacks; itr; )
{
Eo_Callback_Description *titr = itr;
itr = itr->next;
if (titr == cb)
{
- if (pitr)
- {
- pitr->next = titr->next;
- }
- else
- {
- pd->callbacks = titr->next;
- }
- free(titr);
- }
- else
- {
- pitr = titr;
+ if (pitr) pitr->next = titr->next;
+ else pd->callbacks = titr->next;
+ _eo_callback_free(titr);
}
+ else pitr = titr;
}
}
while (pd->callbacks)
{
Eo_Callback_Description *next = pd->callbacks->next;
- free(pd->callbacks);
+ _eo_callback_free(pd->callbacks);
pd->callbacks = next;
}
}
Eo_Callback_Description *cb = NULL;
/* If there are no deletions waiting. */
- if (!pd->deletions_waiting)
- return;
+ if (!pd->deletions_waiting) return;
/* Abort if we are currently walking the list. */
- if (pd->walking_list > 0)
- return;
+ if (pd->walking_list > 0) return;
pd->deletions_waiting = EINA_FALSE;
Eo_Callback_Description *titr = cb;
cb = cb->next;
- if (titr->delete_me)
- {
- _eo_callback_remove(pd, titr);
- }
+ if (titr->delete_me) _eo_callback_remove(pd, titr);
}
}
_eo_callbacks_sorted_insert(Efl_Object_Data *pd, Eo_Callback_Description *cb)
{
Eo_Callback_Description *itr, *itrp = NULL;
+
for (itr = pd->callbacks; itr && (itr->priority < cb->priority);
itr = itr->next)
- {
- itrp = itr;
- }
+ itrp = itr;
if (itrp)
{
const void *user_data)
{
const Efl_Callback_Array_Item arr[] = { {desc, func}, {NULL, NULL}};
- Eo_Callback_Description *cb;
+ Eo_Callback_Description *cb = _eo_callback_new();
- cb = calloc(1, sizeof(*cb));
if (!cb || !desc || !func)
{
ERR("Tried adding callback with invalid values: cb: %p desc: %p func: %p\n", cb, desc, func);
- free(cb);
+ _eo_callback_free(cb);
return EINA_FALSE;
}
cb->items.item.desc = desc;
Efl_Event_Cb func,
const void *user_data)
{
- Eo_Callback_Description *cb;
+ Eo_Callback_Description *cb, *pcb;
- for (cb = pd->callbacks; cb; cb = cb->next)
+ for (pcb = NULL, cb = pd->callbacks; cb; pcb = cb, cb = cb->next)
{
if (!cb->delete_me && (cb->items.item.desc == desc) &&
(cb->items.item.func == func) && (cb->func_data == user_data))
const Efl_Callback_Array_Item arr[] = { {desc, func}, {NULL, NULL}};
cb->delete_me = EINA_TRUE;
- pd->deletions_waiting = EINA_TRUE;
- _eo_callbacks_clear(pd);
+ if (pd->walking_list > 0)
+ pd->deletions_waiting = EINA_FALSE;
+ else
+ {
+ if (pcb) pcb->next = cb->next;
+ else pd->callbacks = cb->next;
+ _eo_callback_free(cb);
+ }
efl_event_callback_call(obj, EFL_EVENT_CALLBACK_DEL, (void *)arr);
return EINA_TRUE;
}
Efl_Callback_Priority priority,
const void *user_data)
{
- Eo_Callback_Description *cb;
+ Eo_Callback_Description *cb = _eo_callback_new();
- cb = calloc(1, sizeof(*cb));
if (!cb || !array)
{
ERR("Tried adding array of callbacks with invalid values: cb: %p array: %p\n", cb, array);
- free(cb);
+ _eo_callback_free(cb);
return EINA_FALSE;
}
cb->func_data = (void *) user_data;
const Efl_Callback_Array_Item *array,
const void *user_data)
{
- Eo_Callback_Description *cb;
+ Eo_Callback_Description *cb, *pcb;
- for (cb = pd->callbacks; cb; cb = cb->next)
+ for (pcb = NULL, cb = pd->callbacks; cb; pcb = cb, cb = cb->next)
{
if (!cb->delete_me &&
(cb->items.item_array == array) && (cb->func_data == user_data))
{
cb->delete_me = EINA_TRUE;
- pd->deletions_waiting = EINA_TRUE;
- _eo_callbacks_clear(pd);
-
+ if (pd->walking_list > 0)
+ pd->deletions_waiting = EINA_FALSE;
+ else
+ {
+ if (pcb) pcb->next = cb->next;
+ else pd->callbacks = cb->next;
+ _eo_callback_free(cb);
+ }
efl_event_callback_call(obj, EFL_EVENT_CALLBACK_DEL, (void *)array);
return EINA_TRUE;
}