eo: trigger invalidate and noref event before any modification is commited on the object tree.

This commit is contained in:
Cedric Bail 2018-04-02 17:18:46 -07:00
parent 1ca196fbcd
commit 224049fa18
2 changed files with 48 additions and 31 deletions

View File

@ -1882,6 +1882,14 @@ efl_unref(const Eo *obj_id)
{
EO_OBJ_POINTER_RETURN(obj_id, obj);
if (EINA_UNLIKELY(obj->user_refcount == 1))
{
// The noref event should happen before any object in the
// tree get affected by the change in refcount.
efl_event_callback_call((Eo *) obj_id, EFL_EVENT_NOREF, NULL);
efl_noref((Eo *) obj_id);
}
--(obj->user_refcount);
#ifdef EO_DEBUG
_eo_log_obj_ref_op(obj, EO_REF_OP_UNREF);
@ -1896,7 +1904,6 @@ efl_unref(const Eo *obj_id)
EO_OBJ_DONE(obj_id);
return;
}
efl_noref((Eo *) obj_id);
_efl_unref(obj);
}
EO_OBJ_DONE(obj_id);

View File

@ -110,6 +110,43 @@ typedef struct
static int _eo_nostep_alloc = -1;
static void
_efl_pending_futures_clear(Efl_Object_Data *pd)
{
while (pd->pending_futures)
{
Efl_Future_Pending *pending = EINA_INLIST_CONTAINER_GET(pd->pending_futures, Efl_Future_Pending);
Eina_Future *future = *pending->desc.storage;
assert(future);
eina_future_cancel(future);
}
}
// Generate the invalidate event in all case and make sure it happens
// before any user code can change the children invalidate state. This
// make sure that the entire tree of object is valid at the time of
// the invalidate event.
static void
_efl_invalidate(Eo *obj)
{
efl_event_callback_call(obj, EFL_EVENT_INVALIDATE, NULL);
efl_invalidate(obj);
}
static void
_efl_object_invalidate(Eo *obj, Efl_Object_Data *pd)
{
_efl_pending_futures_clear(pd);
efl_parent_set(obj, NULL);
pd->invalidate = EINA_TRUE;
}
static void
_efl_object_noref(Eo *obj EINA_UNUSED, Efl_Object_Data *pd EINA_UNUSED)
{
}
static inline void
_efl_object_extension_free(Efl_Object_Extension *ext)
{
@ -676,7 +713,7 @@ _efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo *parent_id)
else
{
pd->parent = NULL;
if (prev_parent) efl_invalidate(obj);
if (prev_parent) _efl_invalidate(obj);
if (prev_parent && !eo_obj->del_triggered) efl_unref(obj);
}
@ -1934,18 +1971,6 @@ EAPI const Eina_Value_Type *EFL_DBG_INFO_TYPE = &_EFL_DBG_INFO_TYPE;
/* EFL_OBJECT_CLASS stuff */
#define MY_CLASS EFL_OBJECT_CLASS
static void
_efl_pending_futures_clear(Efl_Object_Data *pd)
{
while (pd->pending_futures)
{
Efl_Future_Pending *pending = EINA_INLIST_CONTAINER_GET(pd->pending_futures, Efl_Future_Pending);
Eina_Future *future = *pending->desc.storage;
assert(future);
eina_future_cancel(future);
}
}
static Eina_Value
_efl_future_cb(void *data, const Eina_Value value, const Eina_Future *dead_future)
{
@ -2056,7 +2081,8 @@ _efl_object_destructor(Eo *obj, Efl_Object_Data *pd)
// This can happen when the object has no parent and get
// deleted by efl_unref.
if (!pd->invalidate)
efl_invalidate(obj);
_efl_invalidate(obj);
// special removal - remove from children list by hand after getting
// child handle in case unparent method is overridden and does
@ -2170,22 +2196,6 @@ _efl_object_finalize(Eo *obj, Efl_Object_Data *pd EINA_UNUSED)
return obj;
}
static void
_efl_object_invalidate(Eo *obj, Efl_Object_Data *pd)
{
efl_event_callback_call(obj, EFL_EVENT_INVALIDATE, NULL);
_efl_pending_futures_clear(pd);
efl_parent_set(obj, NULL);
pd->invalidate = EINA_TRUE;
}
static void
_efl_object_noref(Eo *obj, Efl_Object_Data *pd EINA_UNUSED)
{
efl_event_callback_call(obj, EFL_EVENT_NOREF, NULL);
}
EOLIAN static void
_efl_object_class_constructor(Efl_Class *klass EINA_UNUSED)
{