eo: prevent unecessary callback call walk.

This patch introduce a small hash (64 or 32bits) that cache all existing
Efl_Event_Description callback handler registered on an object. It slightly
reduce the time needed to do an unecessary call and cost just a few bytes
per object.

Reviewed-by: Marcel Hollerbach <mail@marcel-hollerbach.de>
Differential Revision: https://phab.enlightenment.org/D10475
This commit is contained in:
Cedric Bail 2019-10-15 17:04:32 -07:00 committed by Marcel Hollerbach
parent 9852e6cabc
commit 7f53d91583
2 changed files with 32 additions and 2 deletions

View File

@ -53,6 +53,11 @@ struct _Efl_Object_Data
Efl_Event_Callback_Frame *event_frame;
Eo_Callback_Description **callbacks;
#ifdef EFL64
uint64_t callbacks_mask;
#else
uint32_t callbacks_mask;
#endif
Eina_Inlist *pending_futures;
unsigned int callbacks_count;
@ -1209,9 +1214,26 @@ _efl_pending_future_new(void)
#define CB_COUNT_INC(cnt) do { if ((cnt) != 0xffff) (cnt)++; } while(0)
#define CB_COUNT_DEC(cnt) do { if ((cnt) != 0xffff) (cnt)--; } while(0)
static inline unsigned char
_pointer_hash(const uintptr_t val)
{
static const unsigned char shift = (unsigned char) log2(1 + sizeof (Efl_Event_Description));
#ifdef EFL64
return (unsigned char)(((val) >> shift) & 0x3F);
#else
return (unsigned char)(((val) >> shift) & 0x1F);
#endif
}
static inline void
_special_event_count_inc(Eo *obj_id, Efl_Object_Data *pd, const Efl_Callback_Array_Item *it)
{
int event_hash;
event_hash = _pointer_hash((uintptr_t) it->desc);
pd->callbacks_mask |= 1 << event_hash;
if (it->desc == EFL_EVENT_CALLBACK_ADD)
CB_COUNT_INC(pd->event_cb_efl_event_callback_add_count);
else if (it->desc == EFL_EVENT_CALLBACK_DEL)
@ -1682,6 +1704,7 @@ _event_callback_call(Eo *obj_id, Efl_Object_Data *pd,
.inserted_before = 0,
.generation = 1,
};
int event_hash;
if (pd->callbacks_count == 0) return EINA_FALSE;
else if ((desc == EFL_EVENT_CALLBACK_ADD) &&
@ -1695,6 +1718,13 @@ _event_callback_call(Eo *obj_id, Efl_Object_Data *pd,
else if ((desc == EFL_EVENT_NOREF) &&
(pd->event_cb_efl_event_noref_count == 0)) return EINA_FALSE;
if (!legacy_compare)
{
event_hash = _pointer_hash((uintptr_t) desc);
if (!(pd->callbacks_mask & (1 << event_hash)))
return EINA_FALSE;
}
if (pd->event_frame)
frame.generation = ((Efl_Event_Callback_Frame*)pd->event_frame)->generation + 1;

View File

@ -1808,9 +1808,9 @@ EFL_START_TEST(efl_object_size)
// Update this number only if you modified the class size on purpose
#ifdef EO_DEBUG
ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 164);
ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 180);
#else
ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 148);
ck_assert_int_le(efl_class_memory_size_get(SIMPLE_CLASS), 164);
#endif
}
EFL_END_TEST