summaryrefslogtreecommitdiff
path: root/pages/develop/tutorials
diff options
context:
space:
mode:
authorXavi Artigas <xavierartigas@yahoo.es>2018-05-25 10:23:59 -0700
committerapache <apache@e5-web1.enlightenment.org>2018-05-25 10:23:59 -0700
commit67539c96933e81d298e25ecdc4bc60c83a39ed16 (patch)
tree986c82b4af3bddd25e7ad3f0aa4e317b524e5089 /pages/develop/tutorials
parenta8f182fe2e4fe09cbce0331f0e03b761578ed65b (diff)
Wiki page eo-intro.md changed with summary [Updated to efl_new] by Xavi Artigas
Diffstat (limited to 'pages/develop/tutorials')
-rw-r--r--pages/develop/tutorials/c/eo-intro.md.txt76
1 files changed, 42 insertions, 34 deletions
diff --git a/pages/develop/tutorials/c/eo-intro.md.txt b/pages/develop/tutorials/c/eo-intro.md.txt
index 0d3767676..9df289b75 100644
--- a/pages/develop/tutorials/c/eo-intro.md.txt
+++ b/pages/develop/tutorials/c/eo-intro.md.txt
@@ -4,11 +4,12 @@
4 4
5# Introduction to Eo: Creating and Destroying Objects # 5# Introduction to Eo: Creating and Destroying Objects #
6 6
7The Eo generic object system was designed to provide *Object-Oriented capabilities* to EFL. Eo objects are at the core of almost every EFL entity (like Windows, Buttons or Timers) providing lifecycle management and inheritance abilities amongst other features. 7EFL is written in C and therefore lacks language support for [Object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming).
8The Eo generic object system was designed to provide such capabilities to EFL. Eo objects are at the core of almost every EFL entity (like Windows, Buttons or Timers) providing lifecycle management and inheritance abilities amongst other features.
8 9
9This tutorial shows you the basics of creating and destroying Eo objects as well as *Reference Counting*, the technique at the heart of the Eo object lifecycle management. 10This tutorial shows you the basics of creating and destroying Eo objects as well as *Reference Counting*, the technique at the heart of the Eo object lifecycle management.
10 11
11This tutorial is more theoretical than practical however the concepts being explained are crucial, so it's highly advisable to go through it. If you're familiar with Reference Counting, you should have no trouble. 12This tutorial is more theoretical than practical however the concepts being explained are crucial, so it's highly advisable to go through it. If you're familiar with Reference Counting, you should have no trouble at all.
12 13
13## Prerequisites ## 14## Prerequisites ##
14 15
@@ -70,26 +71,26 @@ static void
70_obj_create() 71_obj_create()
71{ 72{
72 // First create a root element 73 // First create a root element
73 _root = efl_add(EFL_MODEL_ITEM_CLASS, NULL, 74 _root = efl_new(EFL_MODEL_ITEM_CLASS,
74 efl_name_set(efl_added, "Root")); 75 efl_name_set(efl_added, "Root"));
75} 76}
76``` 77```
77 78
78``efl_add()`` is one of the most commonly-used methods in EFL so it requires careful inspection. It mainly does **three** separate things: 79``efl_new()`` is the most basic of the object creation methods. It does three things:
79 80
80* Creates a new object of the type (**class**) specified in the first parameter. 81* Creates a new object of the type (**class**) specified in the first parameter and returns a pointer to it.
81* Sets the new object as a child of the already existing object specified in the second parameter. 82* Calls any constructor method defined for the object's class.
82* Calls a list of methods to further initialize or configure the new object. 83* Calls a list of methods to further initialize or configure the new object.
83 84
84In the code snippet above an object of type ``EFL_MODEL_ITEM_CLASS`` is created, as a child of nothing (the ``NULL`` parameter) and ``efl_name_set()`` is then used to configure the object (as explained below). 85In the code snippet above an object of type ``EFL_MODEL_ITEM_CLASS`` is created, and ``efl_name_set()`` is then used to configure the object (as explained below).
85 86
86Note that the specific type of object being created in this tutorial (``EFL_MODEL_ITEM_CLASS``) is not important. It was chosen because it does not need configuration and is therefore easier to use. 87Note that the specific type of object being created in this tutorial (``EFL_MODEL_ITEM_CLASS``) is not important. It was chosen because it does not need configuration and is therefore easier to use.
87 88
88You 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 much more compact. You can create an object, configure it and add it to a scene without even requiring a variable to store it. 89You can use as many configuration calls inside ``efl_new()`` 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 much more compact.
89 90
90In this example, ``efl_name_set()`` is used to name the new object "Root" (note the ``efl_added`` parameter being used). 91In this example, ``efl_name_set()`` is used to name the new object "Root" (note the ``efl_added`` parameter being used).
91 92
92The 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 as the generic ``Eo *``. In this case the pointer is stored in the ``_root`` variable for later use. 93The return value of ``efl_new()`` is the new object with type ``Eo *``, which you can safely assign to a pointer of the specific type you requested or keep it as the generic ``Eo *``. In this case the pointer is stored in the ``_root`` variable for later use.
93 94
94At this point you have created your first Eo object. It is now time to decide who will be responsible for destroying it later. If the object is not destroyed system resources will eventually be exhausted. This is known as a *memory leak*. 95At this point you have created your first Eo object. It is now time to decide who will be responsible for destroying it later. If the object is not destroyed system resources will eventually be exhausted. This is known as a *memory leak*.
95 96
@@ -97,24 +98,15 @@ At this point you have created your first Eo object. It is now time to decide wh
97 98
98In 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 where different parts of code use the same object, it's not easy to know when an object isn't in use anymore and can therefore be safely destroyed. 99In 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 where different parts of code use the same object, it's not easy to know when an object isn't in use anymore and can therefore be safely destroyed.
99 100
100A common approach to this problem is to use the **Reference Counting** technique whereby every object keeps track of how many people (pieces of code) are using it, using an internal *reference counter*: 101A common approach to this problem is to use the **Reference Counting** technique whereby every object keeps track of how many people (pieces of code) are using it, using an internal *reference counter* (*refcount* for short):
101 102
102* When somebody wants to work with a particular object it first needs to *obtain a reference* by using a call like ``efl_ref()`` on the object. This increments the internal reference counter. 103* ``efl_new()`` returns a new object with a reference counter of 1, meaning that the object is currently in use by one person: you, the caller of ``efl_new()``.
104* If somebody else wants to work with that object it first needs to *obtain a reference* by using a call like ``efl_ref()`` on the object. This increments the internal reference counter.
103* When that piece of code is done working with the object it *returns the reference* by calling ``efl_unref()`` on the object in question. This decrements the internal reference counter. 105* When that piece of code is done working with the object it *returns the reference* by calling ``efl_unref()`` on the object in question. This decrements the internal reference counter.
104 106
105The advantage of this technique is that objects can automatically be destroyed when their internal reference counter reaches 0 as no one else is using them. 107The advantage of this technique is that objects can automatically be destroyed when their internal reference counter reaches 0 as no one else is using them.
106 108
107### Reference Counting and efl_add() ### 109Back to the tutorial code, you obtained an object using ``efl_new()`` with a refcount of 1, therefore you need to return that reference at some point. It is time to fill-in the ``_obj_destroy()`` method:
108
109Eo objects created through ``efl_add()`` have a starting reference count of 1, meaning that only one piece of code is using them. **You must know which code this is** as it will be responsible for returning the reference. This is very easy to do.
110
111* **If you assigned the object a parent** then said parent is the owner of the reference. There's 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).
112* **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.
113
114> **NOTE:**
115> Parenthood does need to be permanent in EFL: you can always remove a child object from its parent using ``efl_unparent()``. Be careful, though, because this returns to you the reference the parent was holding. **You are now responsible for returning this reference**, and failing to do so will leak the object. If you want to remove the object from its parent **and** return the reference at the same time, you can use the convenience method ``efl_del()``.
116
117Back 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:
118 110
119```c 111```c
120static void 112static void
@@ -128,7 +120,7 @@ _obj_destroy()
128 120
129The reference you were holding to the ``_root`` object has now returned. Since it was the only existing reference to this object, the internal reference counter will reach 0 and the object will be destroyed. This isn't immediately obvious but you will explore this process further in the next tutorial. 121The reference you were holding to the ``_root`` object has now returned. Since it was the only existing reference to this object, the internal reference counter will reach 0 and the object will be destroyed. This isn't immediately obvious but you will explore this process further in the next tutorial.
130 122
131The first step of the tutorial is now complete. You may not have seen much on screen but now understand the fundamental concept of **Object Lifecycle Management**: when objects are created and destroyed. 123The first step of the tutorial is now complete. You may not have seen much on screen but you now understand the fundamental concept of **Object Lifecycle Management**: when objects are created and destroyed.
132 124
133See below the complete listing, which you can build and run yourself: 125See below the complete listing, which you can build and run yourself:
134 126
@@ -148,7 +140,7 @@ static void
148_obj_create() 140_obj_create()
149{ 141{
150 // First create a root element 142 // First create a root element
151 _root = efl_add(EFL_MODEL_ITEM_CLASS, NULL, 143 _root = efl_new(EFL_MODEL_ITEM_CLASS,
152 efl_name_set(efl_added, "Root")); 144 efl_name_set(efl_added, "Root"));
153} 145}
154 146
@@ -178,7 +170,7 @@ EFL_MAIN()
178 170
179## Step Two: A More Complex Hierarchy ## 171## Step Two: A More Complex Hierarchy ##
180 172
181In this second section more objects will be added, forming a hierarchy. This will give you more hands-on training with the concepts you acquired in the previous stection. 173In this second section more objects will be created as children of other objects, forming a hierarchy. This will give you more hands-on training with the concepts you acquired in the previous section.
182 174
183Start by adding two more global object pointers to keep track of the new objects. Just below the ``#includes``, replace the ``Eo *_root;`` line with: 175Start by adding two more global object pointers to keep track of the new objects. Just below the ``#includes``, replace the ``Eo *_root;`` line with:
184 176
@@ -186,7 +178,7 @@ Start by adding two more global object pointers to keep track of the new objects
186Eo *_root, *_child1, *_child2; 178Eo *_root, *_child1, *_child2;
187``` 179```
188 180
189Next, in the ``_obj_create()`` method add a new ``efl_add()`` line below the previous one: 181Next, in the ``_obj_create()`` method add these lines below the call to ``efl_new()``:
190 182
191```c 183```c
192 // Create the first child element 184 // Create the first child element
@@ -194,7 +186,17 @@ Next, in the ``_obj_create()`` method add a new ``efl_add()`` line below the pre
194 efl_name_set(efl_added, "Child1")); 186 efl_name_set(efl_added, "Child1"));
195``` 187```
196 188
197Here you are creating a new object (of type ``EFL_MODEL_ITEM_CLASS``, again) and setting its parent to ``_root``. As you learned in the previous section, since you are assigning the object a parent, its only reference now belongs to said parent. This means you don't need to 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 exists because you will be using it in the following tutorial. 189``efl_add()`` is one of the most commonly-used methods in EFL so it requires careful inspection. It works the same way ``efl_new()`` does (it creates and initializes a new object), and it then gives the new object a **parent**. This means that the only reference to the new object **belongs to the parent**, so you don't need to worry about returning it. It also means that you won't be able to work with this object later on unless you obtain an extra reference. In fact, you don't event need to keep the ``_child1`` pointer. It exists because you will be using it in the following tutorial.
190
191As you can see, ``efl_add()`` is very convenient since it allows you to create an object, configure it and add it to a hierarchy without even requiring a variable to store it.
192
193> **NOTE:**
194>
195> Parenthood does not need to be permanent in EFL: you can always remove a child object from its parent using ``efl_parent_set(obj, NULL)``. Be careful, though, because this returns to you the reference the parent was holding. **You are now responsible for returning this reference**, and failing to do so will leak the object. If you want to remove the object from its parent **and** return the reference at the same time, you can use the convenience method ``efl_del()``.
196>
197> Likewise, you can assign an object to a parent using ``efl_parent_set(obj, parent)``. This steals the reference from you and gives it to the new parent.
198
199In the above code snippet, you are creating a new object (of type ``EFL_MODEL_ITEM_CLASS``, again) and setting its parent to ``_root``, so from this point onwards you can forget about this object: its parent will take care of it.
198 200
199Now add a second object immediately below the previous one: 201Now add a second object immediately below the previous one:
200 202
@@ -204,7 +206,13 @@ Now add a second object immediately below the previous one:
204 efl_name_set(efl_added, "Child2")); 206 efl_name_set(efl_added, "Child2"));
205``` 207```
206 208
207This 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 one for you. This is handy when you want the object to have a parent but also want to work with it. Obviously, you will need to return the extra reference later on. 209This 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 one for you. This is handy when you want the object to have a parent but also want to work with it. You will need to return your extra reference later on, and the parent will return its own reference.
210
211> **NOTE:**
212>
213> ``efl_add_ref()`` accepts ``NULL`` as parent. In this case, it behaves exactly like ``efl_new()`` and returns an object with a single reference.
214>
215> ``efl_add()`` does **not** accept ``NULL`` as parent and will show an error message at runtime if you try.
208 216
209In this simple tutorial you will not be doing anything special with ``_child2``: It has been created with an extra reference for example purposes only. 217In this simple tutorial you will not be doing anything special with ``_child2``: It has been created with an extra reference for example purposes only.
210 218
@@ -216,7 +224,7 @@ Next, move on to the ``_obj_destroy()`` method. You need to return the extra ref
216 efl_unref(_child2); 224 efl_unref(_child2);
217``` 225```
218 226
219Note how you are **not** returning the reference to ``_child1``. This is because that reference belongs to its parent, ``_root``, which handles it. In this example when ``_root`` is destroyed it will also return the references for all its children. This in turn destroys ``_child1`` because there was only one reference to it but **not** ``_child2`` because there is an extra reference to it. You will manually return this with an explicit call to ``efl_unref()``). 227Note how you are **not** returning the reference to ``_child1``. This is because that reference belongs to its parent, ``_root``, which handles it. In this example when ``_root`` is destroyed it will also return the references for all its children. This in turn destroys ``_child1`` because there was only one reference to it but **not** ``_child2`` because there is an extra reference to it. You will manually return this with an explicit call to ``efl_unref()``.
220 228
221If you compile and run the complete code below you will only see messages about objects being deleted but in so doing you've learned about the very important topic of object creation and destruction, as well as how to avoid memory leaks. 229If you compile and run the complete code below you will only see messages about objects being deleted but in so doing you've learned about the very important topic of object creation and destruction, as well as how to avoid memory leaks.
222 230
@@ -236,7 +244,7 @@ static void
236_obj_create() 244_obj_create()
237{ 245{
238 // First create a root element 246 // First create a root element
239 _root = efl_add(EFL_MODEL_ITEM_CLASS, NULL, 247 _root = efl_new(EFL_MODEL_ITEM_CLASS,
240 efl_name_set(efl_added, "Root")); 248 efl_name_set(efl_added, "Root"));
241 249
242 // Create the first child element 250 // Create the first child element
@@ -280,10 +288,10 @@ EFL_MAIN()
280 288
281At the end of this tutorial you have learned: 289At the end of this tutorial you have learned:
282 290
283* Objects are **created** with ``efl_add()``. 291* **Standalone** (parent-less) objects are created with ``efl_new()``. You must manually destroy these objects using ``efl_unref()``.
284* ``efl_add()`` creates objects with **one reference**, which belongs to their parent. You don't have to do anything to destroy the objects. 292* ``efl_add()`` creates objects which **belong to their parent**. You don't have to do anything to destroy the objects.
285* 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()``. 293* Objects can be created with an **extra reference** with ``efl_add_ref()``, which is useful if you want to give the object a parent and also start working with it right away. You must return the extra reference using ``efl_unref()``.
286* Objects can be created with an **extra reference** with ``efl_add_ref()``, which is useful if you want to give the object a parent and also start working with it right away. 294* The parent of an object can be **changed** at any time using ``efl_parent_set()``. Be careful with object ownership if you do so.
287 295
288The following tutorial builds on top of this one, adding instrumentation calls to display the actual values of the different reference counters. 296The following tutorial builds on top of this one, adding instrumentation calls to display the actual values of the different reference counters.
289 297