diff options
-rw-r--r-- | src/benchmarks/eo/eo_bench_eo_add.c | 34 | ||||
-rw-r--r-- | src/lib/eo/efl_object.eo | 5 | ||||
-rw-r--r-- | src/lib/eo/eo.c | 7 | ||||
-rw-r--r-- | src/lib/eo/eo_base_class.c | 6 | ||||
-rw-r--r-- | src/lib/eo/eo_private.h | 1 | ||||
-rw-r--r-- | src/tests/eo/suite/eo_test_lifecycle.c | 238 |
6 files changed, 291 insertions, 0 deletions
diff --git a/src/benchmarks/eo/eo_bench_eo_add.c b/src/benchmarks/eo/eo_bench_eo_add.c index 963cd3a..77f2ead 100644 --- a/src/benchmarks/eo/eo_bench_eo_add.c +++ b/src/benchmarks/eo/eo_bench_eo_add.c | |||
@@ -38,10 +38,44 @@ bench_efl_add_jump_by_2(int request) | |||
38 | free(objs); | 38 | free(objs); |
39 | } | 39 | } |
40 | 40 | ||
41 | static void | ||
42 | bench_efl_add_shared_ownership(int request) | ||
43 | { | ||
44 | int i; | ||
45 | Eo **objs = calloc(request, sizeof(Eo *)); | ||
46 | Eo *p = efl_add_ref(SIMPLE_CLASS, NULL); | ||
47 | for (i = 0; i < request; i++) | ||
48 | objs[i] = efl_add_ref(SIMPLE_CLASS, p); | ||
49 | efl_unref(p); | ||
50 | for (i = 0; i < request; i++) | ||
51 | efl_unref(objs[i]); | ||
52 | free(objs); | ||
53 | } | ||
54 | |||
55 | static void | ||
56 | bench_efl_add_shared_ownership_alternative(int request) | ||
57 | { | ||
58 | int i; | ||
59 | Eo **objs = calloc(request, sizeof(Eo *)); | ||
60 | Eo *p = efl_add_ref(SIMPLE_CLASS, NULL); | ||
61 | for (i = 0; i < request; i++) | ||
62 | objs[i] = efl_add(SIMPLE_CLASS, p); | ||
63 | for (i = 0; i < request; i++) | ||
64 | efl_ref(objs[i]); | ||
65 | for (i = 0; i < request; i++) | ||
66 | efl_unref(objs[i]); | ||
67 | efl_unref(p); | ||
68 | free(objs); | ||
69 | } | ||
70 | |||
41 | void eo_bench_efl_add(Eina_Benchmark *bench) | 71 | void eo_bench_efl_add(Eina_Benchmark *bench) |
42 | { | 72 | { |
43 | eina_benchmark_register(bench, "efl_add_linear", | 73 | eina_benchmark_register(bench, "efl_add_linear", |
44 | EINA_BENCHMARK(bench_efl_add_linear), _EO_BENCH_TIMES(1000, 10, 50000)); | 74 | EINA_BENCHMARK(bench_efl_add_linear), _EO_BENCH_TIMES(1000, 10, 50000)); |
45 | eina_benchmark_register(bench, "efl_add_jump_by_2", | 75 | eina_benchmark_register(bench, "efl_add_jump_by_2", |
46 | EINA_BENCHMARK(bench_efl_add_jump_by_2), _EO_BENCH_TIMES(1000, 10, 50000)); | 76 | EINA_BENCHMARK(bench_efl_add_jump_by_2), _EO_BENCH_TIMES(1000, 10, 50000)); |
77 | eina_benchmark_register(bench, "efl_add_shared_ownership", | ||
78 | EINA_BENCHMARK(bench_efl_add_shared_ownership), _EO_BENCH_TIMES(1000, 10, 50000)); | ||
79 | eina_benchmark_register(bench, "efl_add_shared_ownership_alternative", | ||
80 | EINA_BENCHMARK(bench_efl_add_shared_ownership_alternative), _EO_BENCH_TIMES(1000, 10, 50000)); | ||
47 | } | 81 | } |
diff --git a/src/lib/eo/efl_object.eo b/src/lib/eo/efl_object.eo index 1ced422..bea9a0e 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 0113434..db96b24 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 (EINA_UNLIKELY(obj->ownership_track && 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 (EINA_UNLIKELY(obj->ownership_track && 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/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c index 2dc5efc..62a1caf 100644 --- a/src/lib/eo/eo_base_class.c +++ b/src/lib/eo/eo_base_class.c | |||
@@ -1179,6 +1179,12 @@ _special_event_count_inc(Eo *obj_id, Efl_Object_Data *pd, const Efl_Callback_Arr | |||
1179 | } | 1179 | } |
1180 | else if (it->desc == EFL_EVENT_DESTRUCT) | 1180 | else if (it->desc == EFL_EVENT_DESTRUCT) |
1181 | pd->has_destroyed_event_cb = EINA_TRUE; | 1181 | pd->has_destroyed_event_cb = EINA_TRUE; |
1182 | else if (it->desc == EFL_EVENT_OWNERSHIP_SHARED || it->desc == EFL_EVENT_OWNERSHIP_UNIQUE) | ||
1183 | { | ||
1184 | EO_OBJ_POINTER_RETURN(obj_id, obj); | ||
1185 | obj->ownership_track = EINA_TRUE; | ||
1186 | EO_OBJ_DONE(obj_id); | ||
1187 | } | ||
1182 | } | 1188 | } |
1183 | 1189 | ||
1184 | static inline void | 1190 | static inline void |
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h index 3b046bb..c64dee5 100644 --- a/src/lib/eo/eo_private.h +++ b/src/lib/eo/eo_private.h | |||
@@ -126,6 +126,7 @@ struct _Eo_Object | |||
126 | Eina_Bool destructed:1; | 126 | Eina_Bool destructed:1; |
127 | Eina_Bool manual_free:1; | 127 | Eina_Bool manual_free:1; |
128 | unsigned char auto_unref : 1; // unref after 1 call - hack for parts | 128 | unsigned char auto_unref : 1; // unref after 1 call - hack for parts |
129 | Eina_Bool ownership_track:1; | ||
129 | }; | 130 | }; |
130 | 131 | ||
131 | /* How we search and store the implementations in classes. */ | 132 | /* How we search and store the implementations in classes. */ |
diff --git a/src/tests/eo/suite/eo_test_lifecycle.c b/src/tests/eo/suite/eo_test_lifecycle.c index 224c9c7..381f153 100644 --- a/src/tests/eo/suite/eo_test_lifecycle.c +++ b/src/tests/eo/suite/eo_test_lifecycle.c | |||
@@ -163,6 +163,238 @@ EFL_START_TEST(eo_test_unref_noref) | |||
163 | EFL_END_TEST | 163 | EFL_END_TEST |
164 | 164 | ||
165 | typedef struct { | 165 | typedef struct { |
166 | int shared, unique, invalidate; | ||
167 | } OwnershipEventsCounter; | ||
168 | |||
169 | static void | ||
170 | _ownership_shared_event(void *data, const Efl_Event *ev EINA_UNUSED) | ||
171 | { | ||
172 | OwnershipEventsCounter *counter = data; | ||
173 | ++(counter->shared); | ||
174 | } | ||
175 | |||
176 | static void | ||
177 | _ownership_unique_event(void *data, const Efl_Event *ev EINA_UNUSED) | ||
178 | { | ||
179 | OwnershipEventsCounter *counter = data; | ||
180 | ++(counter->unique); | ||
181 | } | ||
182 | |||
183 | static void | ||
184 | _invalidate_ownership_event(void *data, const Efl_Event *ev EINA_UNUSED) | ||
185 | { | ||
186 | OwnershipEventsCounter *counter = data; | ||
187 | ++(counter->invalidate); | ||
188 | } | ||
189 | |||
190 | |||
191 | EFL_START_TEST(eo_test_ownership_events) | ||
192 | { | ||
193 | OwnershipEventsCounter counter = {0,}; | ||
194 | Eo *obj = efl_add_ref(SIMPLE_CLASS, NULL); | ||
195 | |||
196 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_SHARED, _ownership_shared_event, &counter); | ||
197 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_UNIQUE, _ownership_unique_event, &counter); | ||
198 | efl_event_callback_add(obj, EFL_EVENT_INVALIDATE, _invalidate_ownership_event, &counter); | ||
199 | |||
200 | efl_ref(obj); | ||
201 | ck_assert_int_eq(counter.shared, 1); | ||
202 | ck_assert_int_eq(counter.unique, 0); | ||
203 | |||
204 | efl_unref(obj); | ||
205 | ck_assert_int_eq(counter.shared, 1); | ||
206 | ck_assert_int_eq(counter.unique, 1); | ||
207 | |||
208 | efl_ref(obj); | ||
209 | ck_assert_int_eq(counter.shared, 2); | ||
210 | ck_assert_int_eq(counter.unique, 1); | ||
211 | efl_ref(obj); | ||
212 | ck_assert_int_eq(counter.shared, 2); | ||
213 | ck_assert_int_eq(counter.unique, 1); | ||
214 | efl_ref(obj); | ||
215 | ck_assert_int_eq(counter.shared, 2); | ||
216 | ck_assert_int_eq(counter.unique, 1); | ||
217 | |||
218 | efl_unref(obj); | ||
219 | ck_assert_int_eq(counter.shared, 2); | ||
220 | ck_assert_int_eq(counter.unique, 1); | ||
221 | efl_unref(obj); | ||
222 | ck_assert_int_eq(counter.shared, 2); | ||
223 | ck_assert_int_eq(counter.unique, 1); | ||
224 | efl_unref(obj); | ||
225 | ck_assert_int_eq(counter.shared, 2); | ||
226 | ck_assert_int_eq(counter.unique, 2); | ||
227 | ck_assert_int_eq(counter.invalidate, 0); | ||
228 | |||
229 | efl_unref(obj); | ||
230 | ck_assert_int_eq(counter.shared, 2); | ||
231 | ck_assert_int_eq(counter.unique, 2); | ||
232 | ck_assert_int_eq(counter.invalidate, 1); | ||
233 | } | ||
234 | EFL_END_TEST | ||
235 | |||
236 | EFL_START_TEST(eo_test_ownership_events_with_parent) | ||
237 | { | ||
238 | OwnershipEventsCounter counter = {0,}; | ||
239 | Eo *par = efl_add_ref(SIMPLE_CLASS, NULL); | ||
240 | Eo *obj = efl_add(SIMPLE_CLASS, par); | ||
241 | |||
242 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_SHARED, _ownership_shared_event, &counter); | ||
243 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_UNIQUE, _ownership_unique_event, &counter); | ||
244 | efl_event_callback_add(obj, EFL_EVENT_INVALIDATE, _invalidate_ownership_event, &counter); | ||
245 | |||
246 | efl_ref(obj); | ||
247 | ck_assert_int_eq(counter.shared, 1); | ||
248 | ck_assert_int_eq(counter.unique, 0); | ||
249 | |||
250 | efl_unref(obj); | ||
251 | ck_assert_int_eq(counter.shared, 1); | ||
252 | ck_assert_int_eq(counter.unique, 1); | ||
253 | |||
254 | efl_ref(obj); | ||
255 | ck_assert_int_eq(counter.shared, 2); | ||
256 | ck_assert_int_eq(counter.unique, 1); | ||
257 | efl_ref(obj); | ||
258 | ck_assert_int_eq(counter.shared, 2); | ||
259 | ck_assert_int_eq(counter.unique, 1); | ||
260 | |||
261 | efl_unref(obj); | ||
262 | ck_assert_int_eq(counter.shared, 2); | ||
263 | ck_assert_int_eq(counter.unique, 1); | ||
264 | efl_unref(obj); | ||
265 | ck_assert_int_eq(counter.shared, 2); | ||
266 | ck_assert_int_eq(counter.unique, 2); | ||
267 | ck_assert_int_eq(counter.invalidate, 0); | ||
268 | |||
269 | efl_del(obj); | ||
270 | ck_assert_int_eq(counter.shared, 2); | ||
271 | ck_assert_int_eq(counter.unique, 2); | ||
272 | ck_assert_int_eq(counter.invalidate, 1); | ||
273 | |||
274 | efl_unref(par); | ||
275 | ck_assert_int_eq(counter.shared, 2); | ||
276 | ck_assert_int_eq(counter.unique, 2); | ||
277 | } | ||
278 | EFL_END_TEST | ||
279 | |||
280 | EFL_START_TEST(eo_test_ownership_events_with_parent_invalidate) | ||
281 | { | ||
282 | OwnershipEventsCounter counter = {0,}; | ||
283 | Eo *par = efl_add_ref(SIMPLE_CLASS, NULL); | ||
284 | Eo *obj = efl_add(SIMPLE_CLASS, par); | ||
285 | |||
286 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_SHARED, _ownership_shared_event, &counter); | ||
287 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_UNIQUE, _ownership_unique_event, &counter); | ||
288 | efl_event_callback_add(obj, EFL_EVENT_INVALIDATE, _invalidate_ownership_event, &counter); | ||
289 | |||
290 | /* Kill parent */ | ||
291 | efl_unref(par); | ||
292 | ck_assert_int_eq(counter.shared, 0); | ||
293 | ck_assert_int_eq(counter.unique, 0); | ||
294 | ck_assert_int_eq(counter.invalidate, 1); | ||
295 | } | ||
296 | EFL_END_TEST | ||
297 | |||
298 | EFL_START_TEST(eo_test_ownership_events_with_parent_invalidate2) | ||
299 | { | ||
300 | OwnershipEventsCounter counter = {0,}; | ||
301 | Eo *par = efl_add_ref(SIMPLE_CLASS, NULL); | ||
302 | Eo *obj = efl_add(SIMPLE_CLASS, par); | ||
303 | |||
304 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_SHARED, _ownership_shared_event, &counter); | ||
305 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_UNIQUE, _ownership_unique_event, &counter); | ||
306 | efl_event_callback_add(obj, EFL_EVENT_INVALIDATE, _invalidate_ownership_event, &counter); | ||
307 | |||
308 | efl_ref(obj); | ||
309 | ck_assert_int_eq(counter.shared, 1); | ||
310 | ck_assert_int_eq(counter.unique, 0); | ||
311 | ck_assert_int_eq(counter.invalidate, 0); | ||
312 | |||
313 | /* Kill parent */ | ||
314 | efl_unref(par); | ||
315 | ck_assert_int_eq(counter.shared, 1); | ||
316 | ck_assert_int_eq(counter.unique, 1); | ||
317 | ck_assert_int_eq(counter.invalidate, 1); | ||
318 | |||
319 | efl_unref(obj); | ||
320 | ck_assert_int_eq(counter.shared, 1); | ||
321 | ck_assert_int_eq(counter.unique, 1); | ||
322 | ck_assert_int_eq(counter.invalidate, 1); | ||
323 | } | ||
324 | EFL_END_TEST | ||
325 | |||
326 | EFL_START_TEST(eo_test_ownership_events_with_parent_invalidate3) | ||
327 | { | ||
328 | OwnershipEventsCounter counter = {0,}; | ||
329 | Eo *par = efl_add_ref(SIMPLE_CLASS, NULL); | ||
330 | Eo *obj = efl_add(SIMPLE_CLASS, par); | ||
331 | |||
332 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_SHARED, _ownership_shared_event, &counter); | ||
333 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_UNIQUE, _ownership_unique_event, &counter); | ||
334 | efl_event_callback_add(obj, EFL_EVENT_INVALIDATE, _invalidate_ownership_event, &counter); | ||
335 | |||
336 | efl_ref(obj); | ||
337 | ck_assert_int_eq(counter.shared, 1); | ||
338 | ck_assert_int_eq(counter.unique, 0); | ||
339 | |||
340 | efl_unref(obj); | ||
341 | ck_assert_int_eq(counter.shared, 1); | ||
342 | ck_assert_int_eq(counter.unique, 1); | ||
343 | |||
344 | efl_ref(obj); | ||
345 | ck_assert_int_eq(counter.shared, 2); | ||
346 | ck_assert_int_eq(counter.unique, 1); | ||
347 | efl_ref(obj); | ||
348 | ck_assert_int_eq(counter.shared, 2); | ||
349 | ck_assert_int_eq(counter.unique, 1); | ||
350 | ck_assert_int_eq(counter.invalidate, 0); | ||
351 | |||
352 | /* Kill parent */ | ||
353 | efl_unref(par); | ||
354 | ck_assert_int_eq(counter.shared, 2); | ||
355 | ck_assert_int_eq(counter.unique, 1); | ||
356 | ck_assert_int_eq(counter.invalidate, 1); | ||
357 | } | ||
358 | EFL_END_TEST | ||
359 | |||
360 | EFL_START_TEST(eo_test_ownership_events_self_invalidate) | ||
361 | { | ||
362 | OwnershipEventsCounter counter = {0,}; | ||
363 | Eo *par = efl_add_ref(SIMPLE_CLASS, NULL); | ||
364 | Eo *obj = efl_add(SIMPLE_CLASS, par); | ||
365 | |||
366 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_SHARED, _ownership_shared_event, &counter); | ||
367 | efl_event_callback_add(obj, EFL_EVENT_OWNERSHIP_UNIQUE, _ownership_unique_event, &counter); | ||
368 | efl_event_callback_add(obj, EFL_EVENT_INVALIDATE, _invalidate_ownership_event, &counter); | ||
369 | |||
370 | ck_assert_int_eq(counter.shared, 0); | ||
371 | ck_assert_int_eq(counter.unique, 0); | ||
372 | ck_assert_int_eq(counter.invalidate, 0); | ||
373 | |||
374 | efl_ref(obj); | ||
375 | ck_assert_int_eq(counter.shared, 1); | ||
376 | ck_assert_int_eq(counter.unique, 0); | ||
377 | ck_assert_int_eq(counter.invalidate, 0); | ||
378 | |||
379 | efl_del(obj); | ||
380 | ck_assert_int_eq(counter.shared, 1); | ||
381 | ck_assert_int_eq(counter.unique, 1); | ||
382 | ck_assert_int_eq(counter.invalidate, 1); | ||
383 | |||
384 | /* Kill parent */ | ||
385 | efl_unref(par); | ||
386 | ck_assert_int_eq(counter.shared, 1); | ||
387 | ck_assert_int_eq(counter.unique, 1); | ||
388 | ck_assert_int_eq(counter.invalidate, 1); | ||
389 | |||
390 | efl_unref(obj); | ||
391 | ck_assert_int_eq(counter.shared, 1); | ||
392 | ck_assert_int_eq(counter.unique, 1); | ||
393 | ck_assert_int_eq(counter.invalidate, 1); | ||
394 | } | ||
395 | EFL_END_TEST | ||
396 | |||
397 | typedef struct { | ||
166 | Eo *par; | 398 | Eo *par; |
167 | Eina_Bool called; | 399 | Eina_Bool called; |
168 | } Invalidating_Test_Helper; | 400 | } Invalidating_Test_Helper; |
@@ -216,6 +448,12 @@ void eo_test_lifecycle(TCase *tc) | |||
216 | tcase_add_test(tc, eo_test_shutdown_eventting); | 448 | tcase_add_test(tc, eo_test_shutdown_eventting); |
217 | tcase_add_test(tc, eo_test_del_in_noref); | 449 | tcase_add_test(tc, eo_test_del_in_noref); |
218 | tcase_add_test(tc, eo_test_unref_noref); | 450 | tcase_add_test(tc, eo_test_unref_noref); |
451 | tcase_add_test(tc, eo_test_ownership_events); | ||
452 | tcase_add_test(tc, eo_test_ownership_events_with_parent); | ||
453 | tcase_add_test(tc, eo_test_ownership_events_with_parent_invalidate); | ||
454 | tcase_add_test(tc, eo_test_ownership_events_with_parent_invalidate2); | ||
455 | tcase_add_test(tc, eo_test_ownership_events_with_parent_invalidate3); | ||
456 | tcase_add_test(tc, eo_test_ownership_events_self_invalidate); | ||
219 | tcase_add_test(tc, eo_test_invalidating_get); | 457 | tcase_add_test(tc, eo_test_invalidating_get); |
220 | tcase_add_test(tc, eo_test_alive_get); | 458 | tcase_add_test(tc, eo_test_alive_get); |
221 | } | 459 | } |