docs: Update efl_object lifecycle docs
authorXavi Artigas <xavierartigas@yahoo.es>
Mon, 11 Feb 2019 13:00:04 +0000 (14:00 +0100)
committerWonki Kim <wonki_.kim@samsung.com>
Fri, 8 Mar 2019 11:49:33 +0000 (20:49 +0900)
Summary:
Explained the different phases, added method refs and removed outdated links.
Ref T7557

Reviewers: zmike, bu5hm4n

Reviewed By: bu5hm4n

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Maniphest Tasks: T7557

Differential Revision: https://phab.enlightenment.org/D7903

src/lib/eo/efl_object.eo

index 5aa1c84..a9ac302 100644 (file)
@@ -29,25 +29,54 @@ const Efl.Callback_Priority_After : Efl.Callback_Priority = 100;
 
 abstract Efl.Object
 {
-   [[Abstract Efl object class]]
+   [[Abstract EFL object class.
+   
+     All EFL objects inherit from this class, which provides basic functionality
+     like naming, debugging, hierarchy traversal, event emission and life cycle
+     management.
+   
+     Life Cycle
+     Objects are created with efl_add() and mostly disposed of with efl_del().
+     As an optimization, efl_add() accepts a list of initialization functions
+     which the programmer can use to further customize the object before it is
+     fully constructed.
+     Also, objects can have a parent which will keep them alive as long as the
+     parent is alive, so the programmer does not need to keep track of references.
+     (See the @.parent property for details).
+     Due to the above characteristics, EFL objects undergo the following phases
+     during their Life Cycle:
+     - Construction: The @.constructor method is called. Afterwards, any
+       user-supplied initialization methods are called.
+     - Finalization: The @.finalize method is called and @.finalized is set to
+       $true when it returns. Object is usable at this point.
+     - Invalidation: The object has lost its parent. The @.invalidate method is
+       called so all the object's relationships can be terminated. @.invalidated
+       is set to $true.
+     - Destruction: The object has no parent and it can be destroyed. The
+       @.destructor method is called, use it to return any resources the object
+       might have gathered during its life.
+     ]]
    eo_prefix: efl;
 
    methods {
       @property parent {
          [[The parent of an object.
 
-           Parents keep references to their children. In order to
-           delete objects which have parents you need to set parent to
-           NULL or use efl_del(). This will both delete & unref
-           the object).
+           Parents keep references to their children and will release these
+           references when destroyed. In this way, objects can be assigned to
+           a parent upon creation, tying their life cycle so the programmer
+           does not need to worry about destroying the child object.
+           In order to destroy an object before its parent, set the parent to
+           $NULL and use efl_unref(), or use efl_del() directly.
 
            The Eo parent is conceptually user set. That means that a parent
            should not be changed behind the scenes in an unexpected way.
 
            For example:
-           If you have a widget that has a box internally and
-           when you 'swallow' a widget and the swallowed object ends up in
-           the box, the parent should be the widget, not the box.
+           If you have a widget which can swallow objects into an internal
+           box, the parent of the swallowed objects should be the widget, not
+           the internal box. The user is not even aware of the existence of
+           the internal box.
          ]]
 
          set {
@@ -55,32 +84,31 @@ abstract Efl.Object
          get {
          }
          values {
-            parent: Efl.Object @nullable; [[The new parent]]
+            parent: Efl.Object @nullable; [[The new parent.]]
          }
       }
       @property name {
-         [[ The name of the object.
-
-           Every object can have a string name. Names may not contain
-           the following characters:
-             / ? * [ ] ! \ :
-           Using any of these in a name will result in undefined
-           behavior later on. An empty string is considered the same as a
-           NULL string or no string for the name.
+         [[The name of the object.
+
+           Every EFL object can have a name. Names may not contain the
+           following characters: / ? * [ ] ! \ :
+           Using any of these in a name will result in undefined behavior
+           later on. An empty string is considered the same as a $NULL string
+           or no string for the name.
          ]]
          set {
          }
          get {
          }
          values {
-           name: string @nullable; [[The name]]
+           name: string @nullable; [[The name.]]
          }
       }
       @property comment {
-         [[ A human readable comment for the object
+         [[A human readable comment for the object.
 
-           Every object can have a string comment. This is intended for developers
-           and debugging. An empty string is considered the same as a NULL
+           Every EFL object can have a comment. This is intended for developers
+           and debugging. An empty string is considered the same as a $NULL
            string or no string for the comment.
          ]]
          set {
@@ -88,11 +116,11 @@ abstract Efl.Object
          get {
          }
          values {
-           comment: string @nullable; [[The comment]]
+           comment: string @nullable; [[The comment.]]
          }
       }
       debug_name_override {
-         [[ Build a read-only name for this object used for debugging.
+         [[Build a read-only name for this object used for debugging.
 
             Multiple calls using efl_super() can be chained in order to build
             the entire debug name, from parent to child classes. In C the usual
@@ -121,7 +149,7 @@ abstract Efl.Object
             ]]
          }
          values {
-            fcount: int; [[The global event freeze count]]
+            fcount: int; [[The global event freeze count.]]
          }
       }
       @property event_freeze_count {
@@ -135,34 +163,36 @@ abstract Efl.Object
             ]]
          }
          values {
-            fcount: int; [[The event freeze count of this object]]
+            fcount: int; [[The event freeze count of this object.]]
          }
       }
       @property finalized {
-         [[True if the object is already finalized, otherwise false.]]
+         [[$true if the object has been finalized, i.e. construction has finished.
+           See the Life Cycle section in this class' description.]]
          get {
          }
          values {
-            finalized: bool; [[$true if the object is finalized, $false otherwise]]
+            finalized: bool; [[$true if the object is finalized, $false otherwise.]]
          }
       }
       @property invalidated {
-         [[True if the object is already invalidated, otherwise false.]]
+         [[$true if the object has been invalidated, i.e. it has no parent.
+           See the Life Cycle section in this class' description.]]
          get {
          }
          values {
-            finalized: bool; [[$true if the object is invalidated, $false otherwise]]
+            finalized: bool; [[$true if the object is invalidated, $false otherwise.]]
          }
       }
       @property invalidating {
-         [[True if the object is about to be invalidated, and the invalidation of the children is already happening.
-
-           Note this is true before the invalidate call on the object.
-         ]]
+         [[$true if the object has started the invalidation phase, but has not
+           finished it yet.
+           Note: This might become $true before @.invalidate is called.
+           See the Life Cycle section in this class' description.]]
          get {
          }
          values {
-            invalidating: bool; [[$true if the object is invalidating, $false otherwise]]
+            invalidating: bool; [[$true if the object is invalidating, $false otherwise.]]
          }
       }
       provider_find @const {
@@ -176,30 +206,53 @@ abstract Efl.Object
           If this is not done the class cannot be found up in the object tree.
         ]]
         params {
-          klass : const(Efl.Class); [[The class identifier to search for]]
+          klass : const(Efl.Class); [[The class identifier to search for.]]
         }
-        return : Efl.Object; [[Object from the provider list]]
+        return : Efl.Object; [[Object from the provider list.]]
       }
       constructor {
-         [[Call the object's constructor.
+         [[Implement this method to provide optional initialization code for your object.
 
-           Should not be used with #eo_do. Only use it with #eo_do_super.
-         ]]
-         return: Efl.Object; [[The new object created, can be NULL if aborting]]
+           See the Life Cycle section in this class' description.]]
+         return: Efl.Object; [[The new object, can be $NULL if aborted.]]
       }
       destructor {
-         [[Call the object's destructor.
+         [[Implement this method to provide deinitialization code for your object if you need it.
 
-           Should not be used with #efl_do. Only use it with #efl_do_super.
-          Will be triggered once #invalidate and #noref have been triggered.
-         ]]
+           Will be called once @.invalidate has returned.
+           See the Life Cycle section in this class' description.]]
       }
       finalize {
-         [[Called at the end of efl_add. Should not be called, just overridden.]]
-         return: Efl.Object; [[The new object created, can be NULL if aborting]]
+         [[Implement this method to finish the initialization of your object
+           after all (if any) user-provided configuration methods have been
+           executed.
+
+           Use this method to delay expensive operations until user configuration
+           has finished, to avoid building the object in a "default" state in the
+           constructor, just to have to throw it all away because a user
+           configuration (a property being set, for example) requires a diferent
+           state.
+           This is the last call inside efl_add() and will set @.finalized to $true
+           once it returns.
+           This is an optimization and implementing this method is optional if you
+           already perform all your initialization in the @.constructor method.
+           See the Life Cycle section in this class' description.]]
+         return: Efl.Object; [[The new object. Return $NULL to abort object creation.]]
       }
       invalidate {
-         [[Called when parent reference is lost/set to $NULL and switch the state of the object to invalidate.]]
+         [[Implement this method to perform special actions when your object loses
+           its parent, if you need to.
+
+           It is called when the parent reference is lost or set to $NULL. After this
+           call returns, @.invalidated is set to $true.
+           This allows a simpler tear down of complex hierarchies, by performing
+           object destruction in two steps, first all object relationships are
+           broken and then the isolated objects are destroyed. Performing everything
+           in the @.destructor can sometimes lead to deadlocks, but implementing
+           this method is optional if this is not your case.
+           When an object with a parent is destroyed, it first receives a call to
+           @.invalidate and then to @.destructor.
+           See the Life Cycle section in this class' description.]]
       }
       name_find @const {
          [[Find a child object with the given name and return it.
@@ -211,9 +264,9 @@ abstract Efl.Object
            the search will match any object of that class.
          ]]
          params {
-            @in search: string; [[The name search string]]
+            @in search: string; [[The name search string.]]
          }
-         return: Efl.Object; [[The first object found]]
+         return: Efl.Object; [[The first object found.]]
       }
       event_thaw {
          [[Thaw events of object.
@@ -334,13 +387,13 @@ abstract Efl.Object
            In a normal object use case, when ownership of an object is given
            to a caller, said ownership should be released with efl_unref().
            If the object has a parent, this will print error messages, as
-           $efl_unref() is stealing the ref from the parent.
+           efl_unref() is stealing the ref from the parent.
 
            Warning: Use this function very carefully, unless you're absolutely
            sure of what you are doing.
          ]]
          values {
-            allow: bool(false); [[Whether to allow $efl_unref() to zero
+            allow: bool(false); [[Whether to allow efl_unref() to zero
                even if @.parent is not $null.]]
          }
       }
@@ -350,12 +403,12 @@ abstract Efl.Object
         class.destructor;
    }
    events {
-      del @hot: void; [[Object is being deleted.]]
-      invalidate @hot: void; [[Object is being invalidated and loosing its parent.]]
-      noref @hot: void; [[Object has lost its last reference, only parent relationship is keeping it alive.]]
+      del @hot: void; [[Object is being deleted. See @.destructor.]]
+      invalidate @hot: void; [[Object is being invalidated and losing its parent. See @.invalidate.]]
+      noref @hot: void; [[Object has lost its last reference, only parent relationship is keeping it alive. Advanced usage.]]
       destruct @hot: void; [[Object has been fully destroyed. It can not be used
          beyond this point. This event should only serve to clean up any
-         dangling pointer.]]
+         reference you keep to the object.]]
    }
 }