WWW-www.enlightenment.org pushed a commit to branch master.

http://git.enlightenment.org/website/www-content.git/commit/?id=5f68f4fff9e42f3be019f1abcfa72315b5eee3c0

commit 5f68f4fff9e42f3be019f1abcfa72315b5eee3c0
Author: Xavi Artigas <[email protected]>
Date:   Wed Nov 8 06:34:20 2017 -0800

    Wiki page eo-intro.md changed with summary [created] by Xavi Artigas
---
 pages/develop/tutorial/c/eo-intro.md.txt | 289 +++++++++++++++++++++++++++++++
 1 file changed, 289 insertions(+)

diff --git a/pages/develop/tutorial/c/eo-intro.md.txt 
b/pages/develop/tutorial/c/eo-intro.md.txt
new file mode 100644
index 00000000..072ad6ab
--- /dev/null
+++ b/pages/develop/tutorial/c/eo-intro.md.txt
@@ -0,0 +1,289 @@
+---
+~~Title: Introduction to Eo~~
+---
+ 
+# Introduction to Eo: Creating and destroying objects #
+ 
+The Eo generic object system was designed to provide **Object-Oriented 
capabilities** to the EFL. Eo objects are at the core of almost every EFL 
entity (like Windows, Buttons or Timers), providing lifecycle management and 
inheritance abilities, for example.
+
+This tutorial will show you the basics of creating and destroying Eo objects, 
along with **Reference Counting**, the technique at the heart of the Eo object 
lifecycle management.
+
+Due to its fundamental nature, this tutorial is more theoretic than the 
average. The concepts being explained are crucial, though, so its reading is 
highly encouraged. If you are familiar with Reference Counting, it should be a 
breeze.
+ 
+## Prerequisites ##
+ 
+* Read the [Setting up the Development Environment](/develop/setup/c/) guide 
so you are able to build and run EFL applications.
+* Read the [Hello World tutorial](hello-word.md) so you know the basics of 
building an EFL application.
+ 
+## Step One: Object Creation and Destruction ##
+
+Start with the basic EFL application skeleton from the [Hello World 
tutorial](hello-word.md) and add some placeholder methods that will be filled 
later on:
+
+```c
+#define EFL_EO_API_SUPPORT 1
+#define EFL_BETA_API_SUPPORT 1
+
+#include <Eina.h>
+#include <Efl.h>
+#include <Elementary.h>
+
+// Create our test hierarchy
+static void
+_obj_create()
+{
+}
+
+// Destroy the test hierarchy
+static void
+_obj_destroy()
+{
+}
+
+EAPI_MAIN void
+efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
+{
+   // Create all objects
+   _obj_create();
+
+   // Destroy all objects
+   _obj_destroy();
+
+   // Exit
+   efl_exit(0);
+}
+EFL_MAIN()
+```
+
+Sensibly enough, the objects will be created in ``_obj_create()``, and will be 
destroyed in ``_obj_destroy()``.
+
+Also define some global pointers to keep track of the created objects. In a 
real application you won't be using global variables, but they help keep these 
first tutorials as simple as possible. Put this line after the includes:
+
+```c
+Eo *_root;
+```
+
+This tutorial will use generic ``Eo *`` pointers to store the objects; your 
programs can use them too, or use more specific types like ``Efl_Ui_Win *`` or 
``Efl_Ui_Button *``. EFL methods will accept both types (generic and specific) 
and perform runtime checks to ensure that you provide objects of the type a 
method is expecting.
+
+Now, fill-in the object creation method:
+
+```c
+static void
+_obj_create()
+{
+   // First create a root element
+   _root = efl_add(EFL_MODEL_ITEM_CLASS, NULL,
+                   efl_name_set(efl_added, "Root"));
+}
+```
+
+``efl_add()`` is one of the most commonly-used methods in EFL so it requires 
careful inspection. It mainly does **three** separate things:
+
+* Creates a new object of the type (**class**) specified in the first 
parameter.
+* Sets the new object as a child of the already existing object specified in 
the second parameter.
+* Calls a list of methods to further initialize or configure the new object.
+
+In the code snippet above, an object of type ``EFL_MODEL_ITEM_CLASS`` is being 
created, set as a child of no one (the ``NULL`` parameter) and 
``efl_name_set()`` is used to configure the object (as explained below).
+
+The particular kind of object being created in this tutorial 
(``EFL_MODEL_ITEM_CLASS``) is irrelevant. It was chosen because it does not 
need configuration and is therefore easier to use.
+
+You can use as many configuration calls inside ``efl_add()`` as you need, 
since it accepts an infinite number of parameters. Also, configuration calls 
can use the special symbol ``efl_added`` which refers to the object being 
created. Together, these two powerful features make object creation code 
smaller and more compact: You could create an object, configure it and add it 
to a scene without even requiring a variable to store it!
+
+In this example, ``efl_name_set()`` is used to name the new object "Root" 
(note the ``efl_added`` parameter being used).
+
+Finally, the return value of ``efl_add()`` is the new object, with type ``Eo 
*`` which you can safely assign to a pointer of the specific type you 
requested, or keep the generic ``Eo *``, as you prefer. In this case, the 
pointer is stored in the ``_root`` variable for later use.
+
+At this point, you have created your first Eo object. It is time now to talk 
about who will be responsible for destroying it later on. Because, if the 
object is not destroyed, system resources will eventually be exhausted (this is 
known as a *memory leak*).
+
+### Reference Counting ###
+
+In the simplest case, when only one piece of code is interacting with an 
object, you can create the object, use it, and then destroy it. In more complex 
scenarios though, when different parts of the code use the same object, maybe 
from different execution threads, it is not easy to know when an object is not 
in use anymore and can therefore be safely destroyed.
+
+A common approach to this problem is to use the **Reference Counting** 
technique, in which every object keeps track of how many people (pieces of 
code) are using it in an internal *reference counter*:
+
+* When somebody wants to work with a particular object it first needs to *get 
a reference to it* by using a call like ``efl_ref()`` on the object. This 
increases the internal reference counter.
+* When that piece of code is done working with the object, it *returns the 
reference* by calling ``efl_unref()`` on the object. This decreases the 
internal reference counter.
+
+The advantage of this technique is that objects can be automatically destroyed 
when their internal reference counter reaches 0, because it means that nobody 
is using them anymore.
+
+### Reference Counting and ``efl_add()`` ###
+
+Eo objects created through ``efl_add()`` have a starting reference count of 1, 
meaning that there is one piece of code using them. **It is very important to 
understand which one is this piece of code**, because it will be responsible 
for returning the reference. It is easy, though:
+
+* **If you gave the object a parent**: Then that parent is the owner of the 
reference. There is nothing else that you need to do with the object. You 
cannot actually work with the object, because you do not hold any reference to 
it (more about this later).
+* **If you gave no parent to the object**: If you passed ``NULL`` as the 
parent, then **you** are the owner of the reference and you are responsible for 
returning it with ``efl_unref()``. Forgetting to do so is the most common cause 
of memory leaks.
+
+Back to the tutorial code, no parent was given to the object created in 
``_obj_create()``, therefore you need to return that reference at some point. 
It is time to fill-in the ``_obj_destroy()`` method:
+
+```c
+static void
+_obj_destroy()
+{
+   // Destroy the root element
+   printf ("Deleting root...\n");
+   efl_unref(_root);
+}
+```
+
+As you can see, the reference you were holding to the ``_root`` object is 
returned. Since it was the only existing reference to this object, the internal 
reference counter will reach 0 and the object will be destroyed. Right now you 
have no proof of that, but the following tutorial will show you what is 
happening behind the scenes.
+
+With this, the first step of this tutorial is complete. It does not show much 
on screen, but it was necessary to explain the fundamental concept of **Object 
Lifecycle Management**: When are objects created and when are they destroyed.
+
+Here you have the complete listing, which you can build and run:
+
+```c
+#define EFL_EO_API_SUPPORT 1
+#define EFL_BETA_API_SUPPORT 1
+
+#include <Eina.h>
+#include <Efl.h>
+#include <Elementary.h>
+
+#include <stdlib.h>
+
+Eo *_root;
+
+// Create our test hierarchy
+static void
+_obj_create()
+{
+   // First create a root element
+   _root = efl_add(EFL_MODEL_ITEM_CLASS, NULL,
+                   efl_name_set(efl_added, "Root"));
+}
+
+// Destroy the test hierarchy
+static void
+_obj_destroy()
+{
+   // Destroy the root element
+   printf ("Deleting root...\n");
+   efl_unref(_root);
+}
+
+EAPI_MAIN void
+efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
+{
+   // Create all objects
+   _obj_create();
+
+   // Destroy all objects
+   _obj_destroy();
+
+   // Exit
+   efl_exit(0);
+}
+EFL_MAIN()
+```
+
+## Step Two: A more complex hierarchy ##
+
+In this second step more objects will be added forming a hierarchy. This will 
give you more hands-on training with the concepts you acquired in the previous 
step.
+
+Start by adding two more global object pointers to keep track of the new 
objects. Just below the ``#includes``, replace the ``Eo *_root;`` line with:
+
+```c
+Eo *_root, *_child1, *_child2;
+```
+
+And now, in the ``_obj_create()`` method, add a new ``efl_add()`` line below 
the previous one:
+
+```c
+   // Create the first child element
+   _child1 = efl_add(EFL_MODEL_ITEM_CLASS, _root,
+                     efl_name_set(efl_added, "Child1"));
+```
+
+Here you are creating a new object (of type ``EFL_MODEL_ITEM_CLASS``, again) 
and setting its parent to ``_root``. As you saw in the previous step, the one 
reference to the new object belongs to the parent, therefore you need not worry 
about returning it. It also means that you won't be able to work with this 
object later on. In fact, you don't event need to keep the ``_child1`` pointer 
(it's here because you will be using it in the following tutorial).
+
+Add now a second object just below the previous one:
+
+```c
+   // Create the second child element, this time, with an extra reference
+   _child2 = efl_add_ref(EFL_MODEL_ITEM_CLASS, _root,
+                         efl_name_set(efl_added, "Child2"));
+```
+
+This time you didn't use ``efl_add()`` but ``efl_add_ref()``. This method 
creates objects with an initial reference count of 2, one reference for the 
parent and another one for you. This is handy when you want the object to have 
a parent but you also want to work with it. Obviously, you will need to return 
the extra reference later on.
+
+In this simple tutorial you will not be doing anything special with 
``_child2``, it has been created with an extra reference for illustration 
purposes only.
+
+Move now then to the ``_obj_destroy()`` method. You need to return the extra 
reference to ``_child2`` there, right below the previous call to 
``efl_unref()``:
+
+```c
+   // Destroy the child2 element, for which we were keeping an extra reference
+   printf ("Deleting Child2...\n");
+   efl_unref(_child2);
+```
+
+Note how you are **not** returning the reference to ``_child1``. This is 
because that reference belongs to its parent, ``_root``, which takes care of 
it. In this example, when ``_root`` is destroyed it will also return the 
references for all its children. In turn, this destroys ``_child1`` (because 
there was only one reference to it) but **not** ``_child2`` (because there is 
an extra reference to it, which we will manually return with the explicit call 
to ``efl_unref()``).
+
+And with that, this tutorial is complete. If you compile and run the complete 
code below you will only see messages about objects being deleted, but, in the 
process, you have learned about the very important topic of object creation and 
destruction, and how to avoid memory leaks.
+
+```c
+#define EFL_EO_API_SUPPORT 1
+#define EFL_BETA_API_SUPPORT 1
+
+#include <Eina.h>
+#include <Efl.h>
+#include <Elementary.h>
+
+#include <stdlib.h>
+
+Eo *_root, *_child1, *_child2;
+
+// Create our test hierarchy
+static void
+_obj_create()
+{
+   // First create a root element
+   _root = efl_add(EFL_MODEL_ITEM_CLASS, NULL,
+                   efl_name_set(efl_added, "Root"));
+
+   // Create the first child element
+   _child1 = efl_add(EFL_MODEL_ITEM_CLASS, _root,
+                     efl_name_set(efl_added, "Child1"));
+
+   // Create the second child element, this time, with an extra reference
+   _child2 = efl_add_ref(EFL_MODEL_ITEM_CLASS, _root,
+                         efl_name_set(efl_added, "Child2"));
+}
+
+// Destroy the test hierarchy
+static void
+_obj_destroy()
+{
+   // Destroy the root element
+   printf ("Deleting root...\n");
+   efl_unref(_root);
+
+   // Destroy the child2 element, for which we were keeping an extra reference
+   printf ("Deleting Child2...\n");
+   efl_unref(_child2);
+}
+
+EAPI_MAIN void
+efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
+{
+   // Create all objects
+   _obj_create();
+
+   // Destroy all objects
+   _obj_destroy();
+
+   // Exit
+   efl_exit(0);
+}
+EFL_MAIN()
+```
+
+## Summary ##
+
+At the end of this tutorial you have learned:
+
+* Objects are **created** with ``efl_add()``.
+* ``efl_add()`` creates objects with **one reference**, which belongs to their 
parent. You don't have to do anything to destroy the objects.
+* If you do not provide a parent to ``efl_add()`` then the reference belongs 
to **you**, and you have to return it when you are done working with the object 
using ``efl_unref()``.
+
+## Further Reading ##
+
+[The following tutorial](eo-intro-2.md) builds on top of this one, adding 
instrumentation calls to display the actual values of the different reference 
counters.
\ No newline at end of file

-- 


Reply via email to