summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousa@expertisesolutions.com.br>2019-04-17 18:44:40 -0300
committerVitor Sousa <vitorsousa@expertisesolutions.com.br>2019-04-24 12:13:34 -0300
commit44ae5646bb584d00619df20317afb20f67beb629 (patch)
tree5c15df09ac9fe95b18dfc676af1c1a08737b0a91
parent2e85c6ba344852242290bac55621a9d0e6e0829f (diff)
eo: add events to track the ownership status of an Eo object
Summary: Some user code may want to track an object ownership in regard to whether it is kept by just one owner or shared between many owners. This is specially true for code provided by bindings to other programming languages, where different kinds of resource management may take place. The event `ownership,unique` is triggered whenever the object refcount goes from two to one, as a signal that it has just one owner from now on. The event `ownership,shared` is triggered whenever the object refcount goes from one to two, as a signal that it has multiple owners from now on. It will not trigger when further increasing the refcount to any value beyond two. Reviewers: lauromoura, felipealmeida, cedric, bu5hm4n, segfaultxavi Subscribers: #reviewers, woohyun, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D8678
-rw-r--r--src/lib/eo/efl_object.eo5
-rw-r--r--src/lib/eo/eo.c7
-rw-r--r--src/tests/eo/suite/eo_test_lifecycle.c103
3 files changed, 115 insertions, 0 deletions
diff --git a/src/lib/eo/efl_object.eo b/src/lib/eo/efl_object.eo
index cb0a92e70c..680554c9a8 100644
--- a/src/lib/eo/efl_object.eo
+++ b/src/lib/eo/efl_object.eo
@@ -411,6 +411,11 @@ abstract Efl.Object
411 del @hot: void; [[Object is being deleted. See @.destructor.]] 411 del @hot: void; [[Object is being deleted. See @.destructor.]]
412 invalidate @hot: void; [[Object is being invalidated and losing its parent. See @.invalidate.]] 412 invalidate @hot: void; [[Object is being invalidated and losing its parent. See @.invalidate.]]
413 noref @hot: void; [[Object has lost its last reference, only parent relationship is keeping it alive. Advanced usage.]] 413 noref @hot: void; [[Object has lost its last reference, only parent relationship is keeping it alive. Advanced usage.]]
414 ownership,unique @hot: void; [[Object has lost a reference and only one is left. It has just one owner now.
415 Triggered whenever the refcount goes from two to one.]]
416 ownership,shared @hot: void; [[Object has acquired a second reference. It has multiple owners now.
417 Triggered whenever increasing the refcount from one to two,
418 it will not trigger by further increasing the refcount beyond two.]]
414 destruct @hot: void; [[Object has been fully destroyed. It can not be used 419 destruct @hot: void; [[Object has been fully destroyed. It can not be used
415 beyond this point. This event should only serve to clean up any 420 beyond this point. This event should only serve to clean up any
416 reference you keep to the object.]] 421 reference you keep to the object.]]
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index c16c021ef2..3ce21695de 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -1933,6 +1933,9 @@ efl_ref(const Eo *obj_id)
1933 ++(obj->user_refcount); 1933 ++(obj->user_refcount);
1934 if (EINA_UNLIKELY(obj->user_refcount == 1)) 1934 if (EINA_UNLIKELY(obj->user_refcount == 1))
1935 _efl_ref(obj); 1935 _efl_ref(obj);
1936 else if (!obj->auto_unref && obj->user_refcount == 2)
1937 efl_event_callback_call((Eo *) obj_id, EFL_EVENT_OWNERSHIP_SHARED, NULL);
1938
1936#ifdef EO_DEBUG 1939#ifdef EO_DEBUG
1937 _eo_log_obj_ref_op(obj, EO_REF_OP_REF); 1940 _eo_log_obj_ref_op(obj, EO_REF_OP_REF);
1938#endif 1941#endif
@@ -1991,6 +1994,10 @@ efl_unref(const Eo *obj_id)
1991 } 1994 }
1992 _efl_unref(obj); 1995 _efl_unref(obj);
1993 } 1996 }
1997 else if (obj->user_refcount == 1)
1998 {
1999 efl_event_callback_call((Eo *) obj_id, EFL_EVENT_OWNERSHIP_UNIQUE, NULL);
2000 }
1994 2001
1995 _apply_auto_unref(obj, obj_id); 2002 _apply_auto_unref(obj, obj_id);
1996 2003
diff --git a/src/tests/eo/suite/eo_test_lifecycle.c b/src/tests/eo/suite/eo_test_lifecycle.c
index 224c9c738c..186fa4e5bd 100644
--- a/src/tests/eo/suite/eo_test_lifecycle.c
+++ b/src/tests/eo/suite/eo_test_lifecycle.c
@@ -163,6 +163,107 @@ EFL_START_TEST(eo_test_unref_noref)
163EFL_END_TEST 163EFL_END_TEST
164 164
165typedef struct { 165typedef struct {
166 int shared, unique;
167} OwnershipEventsCounter;
168
169static void
170_ownership_shared_event(void *data, const Efl_Event *ev EINA_UNUSED)
171{
172 OwnershipEventsCounter *counter = data;
173 ++(counter->shared);
174}
175
176static void
177_ownership_unique_event(void *data, const Efl_Event *ev EINA_UNUSED)
178{
179 OwnershipEventsCounter *counter = data;
180 ++(counter->unique);
181}
182
183EFL_START_TEST(eo_test_ownership_events)
184{
185 OwnershipEventsCounter counter = {0,};
186 Eo *obj = efl_add_ref(SIMPLE_CLASS, NULL);
187
188 efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_SHARED, _ownership_shared_event, &counter);
189 efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_UNIQUE, _ownership_unique_event, &counter);
190
191 efl_ref(obj);
192 ck_assert_int_eq(counter.shared, 1);
193 ck_assert_int_eq(counter.unique, 0);
194
195 efl_unref(obj);
196 ck_assert_int_eq(counter.shared, 1);
197 ck_assert_int_eq(counter.unique, 1);
198
199 efl_ref(obj);
200 ck_assert_int_eq(counter.shared, 2);
201 ck_assert_int_eq(counter.unique, 1);
202 efl_ref(obj);
203 ck_assert_int_eq(counter.shared, 2);
204 ck_assert_int_eq(counter.unique, 1);
205 efl_ref(obj);
206 ck_assert_int_eq(counter.shared, 2);
207 ck_assert_int_eq(counter.unique, 1);
208
209 efl_unref(obj);
210 ck_assert_int_eq(counter.shared, 2);
211 ck_assert_int_eq(counter.unique, 1);
212 efl_unref(obj);
213 ck_assert_int_eq(counter.shared, 2);
214 ck_assert_int_eq(counter.unique, 1);
215 efl_unref(obj);
216 ck_assert_int_eq(counter.shared, 2);
217 ck_assert_int_eq(counter.unique, 2);
218
219 efl_unref(obj);
220 ck_assert_int_eq(counter.shared, 2);
221 ck_assert_int_eq(counter.unique, 2);
222}
223EFL_END_TEST
224
225EFL_START_TEST(eo_test_ownership_events_with_parent)
226{
227 OwnershipEventsCounter counter = {0,};
228 Eo *par = efl_add_ref(SIMPLE_CLASS, NULL);
229 Eo *obj = efl_add(SIMPLE_CLASS, par);
230
231 efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_SHARED, _ownership_shared_event, &counter);
232 efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_UNIQUE, _ownership_unique_event, &counter);
233
234 efl_ref(obj);
235 ck_assert_int_eq(counter.shared, 1);
236 ck_assert_int_eq(counter.unique, 0);
237
238 efl_unref(obj);
239 ck_assert_int_eq(counter.shared, 1);
240 ck_assert_int_eq(counter.unique, 1);
241
242 efl_ref(obj);
243 ck_assert_int_eq(counter.shared, 2);
244 ck_assert_int_eq(counter.unique, 1);
245 efl_ref(obj);
246 ck_assert_int_eq(counter.shared, 2);
247 ck_assert_int_eq(counter.unique, 1);
248
249 efl_unref(obj);
250 ck_assert_int_eq(counter.shared, 2);
251 ck_assert_int_eq(counter.unique, 1);
252 efl_unref(obj);
253 ck_assert_int_eq(counter.shared, 2);
254 ck_assert_int_eq(counter.unique, 2);
255
256 efl_del(obj);
257 ck_assert_int_eq(counter.shared, 2);
258 ck_assert_int_eq(counter.unique, 2);
259
260 efl_unref(par);
261 ck_assert_int_eq(counter.shared, 2);
262 ck_assert_int_eq(counter.unique, 2);
263}
264EFL_END_TEST
265
266typedef struct {
166 Eo *par; 267 Eo *par;
167 Eina_Bool called; 268 Eina_Bool called;
168} Invalidating_Test_Helper; 269} Invalidating_Test_Helper;
@@ -216,6 +317,8 @@ void eo_test_lifecycle(TCase *tc)
216 tcase_add_test(tc, eo_test_shutdown_eventting); 317 tcase_add_test(tc, eo_test_shutdown_eventting);
217 tcase_add_test(tc, eo_test_del_in_noref); 318 tcase_add_test(tc, eo_test_del_in_noref);
218 tcase_add_test(tc, eo_test_unref_noref); 319 tcase_add_test(tc, eo_test_unref_noref);
320 tcase_add_test(tc, eo_test_ownership_events);
321 tcase_add_test(tc, eo_test_ownership_events_with_parent);
219 tcase_add_test(tc, eo_test_invalidating_get); 322 tcase_add_test(tc, eo_test_invalidating_get);
220 tcase_add_test(tc, eo_test_alive_get); 323 tcase_add_test(tc, eo_test_alive_get);
221} 324}