jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=d3436af616319f1fdbbd4a0aa71a7835a14699ac

commit d3436af616319f1fdbbd4a0aa71a7835a14699ac
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Thu Sep 28 16:38:00 2017 +0900

    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
---
 src/lib/eo/efl_object.eo   | 19 +++++++++++++++++++
 src/lib/eo/eo_base_class.c | 16 +++++++++++++++-
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/src/lib/eo/efl_object.eo b/src/lib/eo/efl_object.eo
index 68d0d19770..db634ea7e6 100644
--- a/src/lib/eo/efl_object.eo
+++ b/src/lib/eo/efl_object.eo
@@ -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;
diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c
index 60ceaf6c67..72171fbf4b 100644
--- a/src/lib/eo/eo_base_class.c
+++ b/src/lib/eo/eo_base_class.c
@@ -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)
 {

-- 


Reply via email to