struct _Efl_Event_Callback_Frame
{
+ const Efl_Event_Description *desc;
Efl_Event_Callback_Frame *next;
unsigned int idx;
unsigned int inserted_before;
Efl_Object_Extension *ext;
- Eina_Inlist *current;
-
Efl_Event_Callback_Frame *event_frame;
Eo_Callback_Description **callbacks;
#ifdef EFL64
Eina_Bool legacy_compare)
{
Eo_Callback_Description **cb;
- Eo_Current_Callback_Description *lookup, saved;
+ Efl_Event_Callback_Frame *restart_lookup = NULL; //a pointer to a frame, which is high up the stack, which we use to restore
Efl_Event ev;
unsigned int idx;
Eina_Bool callback_already_stopped, ret;
Efl_Event_Callback_Frame frame = {
+ .desc = desc,
.next = NULL,
.idx = 0,
.inserted_before = 0,
EVENT_STACK_PUSH(pd, &frame);
- lookup = NULL;
callback_already_stopped = pd->callback_stopped;
pd->callback_stopped = EINA_FALSE;
ret = EINA_TRUE;
(event_freeze_count || pd->event_freeze_count))
continue;
- // Handle nested restart of walking list
- if (lookup) lookup->current = idx - 1;
-
it->func((void *) (*cb)->func_data, &ev);
/* Abort callback calling if the func says so. */
if (pd->callback_stopped)
ret = EINA_FALSE;
goto end;
}
- // We have actually walked this list during a nested call
- if (lookup &&
- lookup->current == 0)
- goto end;
}
}
else
(event_freeze_count || pd->event_freeze_count))
continue;
- // Handle nested restart of walking list
- if (lookup) lookup->current = idx - 1;
-
(*cb)->items.item.func((void *) (*cb)->func_data, &ev);
/* Abort callback calling if the func says so. */
if (pd->callback_stopped)
ret = EINA_FALSE;
goto end;
}
- // We have actually walked this list during a nested call
- if (lookup &&
- lookup->current == 0)
- goto end;
}
}
- idx += frame.inserted_before;
+ /*
+ * copy back the idx that might have changed due to restarts, (theoretically only needed with restarts, condition made everything slower)
+ * additionally adjust to event subscriptions that have been added in a event callback
+ */
+ idx = frame.idx + frame.inserted_before;
frame.inserted_before = 0;
}
end:
// Handling restarting list walking complete exit.
- if (lookup) lookup->current = 0;
- if (lookup == &saved)
- {
- pd->current = eina_inlist_remove(pd->current, EINA_INLIST_GET(lookup));
- }
+ if (restart_lookup) restart_lookup->idx = 0;
EVENT_STACK_POP(pd);
return ret;
restart:
- EINA_INLIST_FOREACH(pd->current, lookup)
+ // Search for the next frame that has the same event description
+ for (restart_lookup = frame.next; restart_lookup; restart_lookup = restart_lookup->next)
{
- if (lookup->desc == desc) break;
+ if (restart_lookup->desc == desc) break;
}
- // This is the first event to trigger it, so register it here
- if (!lookup)
- {
- // This following trick get us a zero allocation list
- saved.desc = desc;
- saved.current = 0;
- lookup = &saved;
- // Ideally there will most of the time be only one item in this list
- // But just to speed up things, prepend so we find it fast at the end
- // of this function
- pd->current = eina_inlist_prepend(pd->current, EINA_INLIST_GET(lookup));
- }
+ // Ensure that the idx is the next from the previous run, minimum number 0
+ if (restart_lookup) {
+ idx = restart_lookup->idx - 1;
+ } else {
+ idx = 0;
+ }
+ // If this is 0, then we are restarting
+ if (!idx)
+ idx = pd->callbacks_count;
- if (!lookup->current) lookup->current = pd->callbacks_count;
- idx = lookup->current;
goto restart_back;
}