eo: Add API to allow deletion by unref

This allows deleting an object by simply calling efl_unref() on it, even
if there is a parent. Normally the parent is in charge, and you can
request deletion by calling efl_del() or efl_parent_set(NULL).

But in some rare cases, you want to give ownership of an object (@owned)
and still give a parent to that object. efl_unref() should be used (and
would be used by bindings when going out of scope or on garbage
collection), which would then print an error message. This API allows
the specific behaviour.

@feature
This commit is contained in:
Jean-Philippe Andre 2017-09-28 16:38:00 +09:00
parent 662a172139
commit d3436af616
2 changed files with 34 additions and 1 deletions

View File

@ -262,6 +262,25 @@ abstract Efl.Object ()
]]
return: bool; [[$true if it is. $false otherwise.]]
}
@property allow_parent_unref {
[[Allow an object to be deleted by unref even if it has a parent.
This simply hides error messages warning that an object being
destructed still has a parent. This property is false by default.
In a normal object use case, when ownership of an object is given
to a caller, said ownership should be released with efl_unref(). But
if the object has a parent, this will print error messages, as
$efl_unref() is stealing the ref from the parent.
Warning: Use this function very carefully, if you are absolutely
sure of what you are doing.
]]
values {
allow: bool(false); [[Whether to allow $efl_unref() to zero
even if @.parent is not $null.]]
}
}
}
implements {
class.constructor;

View File

@ -58,6 +58,7 @@ typedef struct
Eina_Bool callback_stopped : 1;
Eina_Bool need_cleaning : 1;
Eina_Bool parent_sunk : 1; // If parent ref has already been settled (parent has been set, or we are in add_ref mode
Eina_Bool allow_parent_unref : 1; // Allows unref to zero even with a parent
} Efl_Object_Data;
typedef enum
@ -2088,11 +2089,24 @@ composite_obj:
goto composite_obj_back;
err_parent:
ERR("Object '%p' still has a parent at the time of destruction.", obj);
if (EINA_LIKELY(!pd->allow_parent_unref))
ERR("Object '%p' still has a parent at the time of destruction.", obj);
efl_parent_set(obj, NULL);
goto err_parent_back;
}
EOLIAN static void
_efl_object_allow_parent_unref_set(Eo *obj_id EINA_UNUSED, Efl_Object_Data *pd, Eina_Bool allow)
{
pd->allow_parent_unref = !!allow;
}
EOLIAN static Eina_Bool
_efl_object_allow_parent_unref_get(Eo *obj_id EINA_UNUSED, Efl_Object_Data *pd)
{
return pd->allow_parent_unref;
}
EOLIAN static Eo *
_efl_object_finalize(Eo *obj, Efl_Object_Data *pd EINA_UNUSED)
{