summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2018-01-11 17:47:45 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2018-02-05 18:48:58 +0900
commit61575f06f84176be4f2806667754c1c78775fe97 (patch)
tree59bb66233d7ba4de138f07e2ae8cecf92267661d
parentb2713c9287c83e7a3437e2bbdebf143665fd542b (diff)
eo: Introduce efl_invalidate
This begins the destruction of an object. Namely, this emits the event "invalidate" and calls a new method "invalidator" (not overridden yet in this patch). Refer to the doc for more information. Next steps: - implement override in efl.canvas.object - introduce efl_new() to create objects without a parent - force efl_add() to be called with a non-null parent - remove parent_sunk and always add a ref on new parenting - break the world @feature
-rw-r--r--src/lib/eo/Eo.h17
-rw-r--r--src/lib/eo/efl_object.eo71
-rw-r--r--src/lib/eo/eo.c16
-rw-r--r--src/lib/eo/eo_base_class.c41
-rw-r--r--src/lib/eo/eo_private.h178
-rw-r--r--src/lib/evas/canvas/efl_input_focus.c6
-rw-r--r--src/lib/evas/canvas/efl_input_key.c6
-rw-r--r--src/lib/evas/canvas/efl_input_pointer.c6
8 files changed, 260 insertions, 81 deletions
diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index 441b3789fc..5654eb37ba 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -1589,6 +1589,23 @@ EAPI Eo *efl_ref(const Eo *obj);
1589EAPI void efl_unref(const Eo *obj); 1589EAPI void efl_unref(const Eo *obj);
1590 1590
1591/** 1591/**
1592 * @brief Invalidate an object.
1593 *
1594 * @param obj The object to invalidate
1595 *
1596 * This does not change the reference count of this object, but if this
1597 * @p obj's parent is the sole reference owner, @p obj will be deleted
1598 * immediately. Otherwise the object will be deleted as soon as its reference
1599 * count reaches zero (by unparenting it).
1600 *
1601 * This calls the invalidator method.
1602 *
1603 * @see efl_ref()
1604 * @see efl_ref_count()
1605 */
1606EAPI void efl_invalidate(const Eo *obj);
1607
1608/**
1592 * @brief Return the ref count of the object passed. 1609 * @brief Return the ref count of the object passed.
1593 * @param obj the object to work on. 1610 * @param obj the object to work on.
1594 * @return the ref count of the object. 1611 * @return the ref count of the object.
diff --git a/src/lib/eo/efl_object.eo b/src/lib/eo/efl_object.eo
index f41b6ee3eb..d069d4e591 100644
--- a/src/lib/eo/efl_object.eo
+++ b/src/lib/eo/efl_object.eo
@@ -123,13 +123,25 @@ abstract Efl.Object ()
123 } 123 }
124 } 124 }
125 @property finalized { 125 @property finalized {
126 [[True if the object is already finalized, otherwise false.]] 126 [[Whether the object is already finalized
127 get { 127
128 } 128 This is $true after @.finalize.
129 ]]
130 get {}
129 values { 131 values {
130 finalized: bool; [[$true if the object is finalized, $false otherwise]] 132 finalized: bool; [[$true if the object is finalized, $false otherwise]]
131 } 133 }
132 } 134 }
135 @property invalidated {
136 [[Whether the object is already invalidated.
137
138 This is $true after @.invalidator.
139 ]]
140 get {}
141 values {
142 invalid: bool; [[$true if the object is invalidated, $false otherwise]]
143 }
144 }
133 provider_find @const { 145 provider_find @const {
134 [[Searches upwards in the object tree for a provider which knows the given class/interface. 146 [[Searches upwards in the object tree for a provider which knows the given class/interface.
135 147
@@ -146,22 +158,51 @@ abstract Efl.Object ()
146 return : Efl.Object; [[Object from the provider list]] 158 return : Efl.Object; [[Object from the provider list]]
147 } 159 }
148 constructor { 160 constructor {
149 [[Call the object's constructor. 161 [[Called when an object begins its creation.
150 162
151 Should not be used with #eo_do. Only use it with #eo_do_super. 163 This is called at the beginning of $efl_add, before @.finalize.
164
165 Should not be called directly. Only use it with $efl_super. All
166 implementations must call $efl_super recursively.
152 ]] 167 ]]
153 return: Efl.Object; [[The new object created, can be NULL if aborting]] 168 return: Efl.Object; [[The new object created, can be NULL if aborting]]
154 } 169 }
155 destructor { 170 finalize {
156 [[Call the object's destructor. 171 [[Called at the end of the creation of an object.
157 172
158 Should not be used with #eo_do. Only use it with #eo_do_super. 173 This is called at the end of $efl_add, after @.constructor and after
174 all initialization calls passed inside $efl_add. Implement this to
175 perform final initialization based on the setup calls made inside
176 $efl_add.
177
178 Should not be called directly. Only use it with $efl_super. All
179 implementations must call $efl_super recursively.
159 ]] 180 ]]
160 }
161 finalize {
162 [[Called at the end of efl_add. Should not be called, just overridden.]]
163 return: Efl.Object; [[The new object created, can be NULL if aborting]] 181 return: Efl.Object; [[The new object created, can be NULL if aborting]]
164 } 182 }
183 invalidator {
184 [[Called when an object is invalidated, about to be destroyed.
185
186 This happens before @.destructor and should be implemented to clean
187 up an object, in particular remove all the references it holds.
188 The @.parent should still be valid.
189
190 Should not be called directly. Only use it with $efl_super. All
191 implementations must call $efl_super recursively.
192 ]]
193 }
194 destructor {
195 [[Called when an object is finally being destroyed.
196
197 This happens after @.invalidator. At this point the object has no
198 remaining reference left, and the destructor should be implemented
199 to free up any remaining resources (
200 The @.parent should not be valid anymore.
201
202 Should not be called directly. Only use it with $efl_super. All
203 implementations must call $efl_super recursively.
204 ]]
205 }
165 name_find @const { 206 name_find @const {
166 [[Find a child object with the given name and return it. 207 [[Find a child object with the given name and return it.
167 208
@@ -287,7 +328,13 @@ abstract Efl.Object ()
287 events { 328 events {
288 callback,add @hot; [[A callback was added.]] 329 callback,add @hot; [[A callback was added.]]
289 callback,del @hot; [[A callback was deleted.]] 330 callback,del @hot; [[A callback was deleted.]]
290 del @hot; [[Object is being deleted.]] 331 invalidate @hot;
332 [[The object is being invalidated. Some object may listen to this
333 event on their children and unreference them at this point.
334 This is emitted before calls to @.invalidator begin.]]
335 del @hot;
336 [[Object is being deleted. This is emitted before calls to
337 @.destructor begin.]]
291 destruct @hot; [[Object has been fully destroyed. It can not be used 338 destruct @hot; [[Object has been fully destroyed. It can not be used
292 beyond this point. This event should only serve to clean up any 339 beyond this point. This event should only serve to clean up any
293 dangling pointer.]] 340 dangling pointer.]]
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index 49e02ba846..57adcb1a84 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -1022,6 +1022,7 @@ efl_reuse(const Eo *eo_id)
1022 efl_object_override(obj, NULL); 1022 efl_object_override(obj, NULL);
1023 if (!efl_parent_get(obj)) 1023 if (!efl_parent_get(obj))
1024 _efl_object_parent_sink_set(obj, EINA_FALSE); 1024 _efl_object_parent_sink_set(obj, EINA_FALSE);
1025 _obj->invalidated = EINA_FALSE;
1025 1026
1026#ifdef EO_DEBUG 1027#ifdef EO_DEBUG
1027 _eo_log_obj_ref_op(_obj, EO_REF_OP_REUSE); 1028 _eo_log_obj_ref_op(_obj, EO_REF_OP_REUSE);
@@ -1902,6 +1903,21 @@ efl_ref_count(const Eo *obj_id)
1902 return ref; 1903 return ref;
1903} 1904}
1904 1905
1906EAPI void
1907efl_invalidate(const Eo *obj_id)
1908{
1909 EO_OBJ_POINTER_RETURN(obj_id, obj);
1910 if (obj->invalidated) goto err;
1911 _efl_invalidate(obj);
1912 EO_OBJ_DONE(obj_id);
1913 return;
1914
1915err:
1916 ERR("Obj:%s@%p. Object is already invalid, can not be destructed further.",
1917 obj->klass->desc->name, obj_id);
1918 EO_OBJ_DONE(obj_id);
1919}
1920
1905EAPI int 1921EAPI int
1906___efl_ref2_count(const Eo *obj_id) 1922___efl_ref2_count(const Eo *obj_id)
1907{ 1923{
diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c
index 9ef4b4fe15..234afbcd82 100644
--- a/src/lib/eo/eo_base_class.c
+++ b/src/lib/eo/eo_base_class.c
@@ -54,12 +54,13 @@ typedef struct
54 unsigned short event_cb_efl_event_callback_add_count; 54 unsigned short event_cb_efl_event_callback_add_count;
55 unsigned short event_cb_efl_event_callback_del_count; 55 unsigned short event_cb_efl_event_callback_del_count;
56 unsigned short event_cb_efl_event_del_count; 56 unsigned short event_cb_efl_event_del_count;
57 unsigned short event_cb_efl_event_invalidate_count;
57#endif 58#endif
58 Eina_Bool callback_stopped : 1; 59 Eina_Bool callback_stopped : 1;
59 Eina_Bool need_cleaning : 1; 60 Eina_Bool need_cleaning : 1;
60 Eina_Bool parent_sunk : 1; // If parent ref has already been settled (parent has been set, or we are in add_ref mode 61 Eina_Bool parent_sunk : 1; // If parent ref has already been settled (parent has been set, or we are in add_ref mode
61 Eina_Bool allow_parent_unref : 1; // Allows unref to zero even with a parent 62 Eina_Bool allow_parent_unref : 1; // Allows unref to zero even with a parent
62 Eina_Bool has_destroyed_event_cb : 1; // No proper count: minor optimization triggered at destruction only 63 Eina_Bool has_destruct_event_cb : 1; // No proper count: minor optimization triggered at destruction only
63} Efl_Object_Data; 64} Efl_Object_Data;
64 65
65typedef enum 66typedef enum
@@ -595,6 +596,7 @@ _efl_object_debug_name_override(Eo *obj_id EINA_UNUSED, Efl_Object_Data *pd EINA
595EOLIAN static void 596EOLIAN static void
596_efl_object_del(const Eo *obj, Efl_Object_Data *pd EINA_UNUSED) 597_efl_object_del(const Eo *obj, Efl_Object_Data *pd EINA_UNUSED)
597{ 598{
599 efl_invalidate(obj);
598 if (efl_parent_get((Eo *) obj)) 600 if (efl_parent_get((Eo *) obj))
599 { 601 {
600 efl_parent_set((Eo *) obj, NULL); 602 efl_parent_set((Eo *) obj, NULL);
@@ -694,6 +696,16 @@ _efl_object_finalized_get(Eo *obj_id, Efl_Object_Data *pd EINA_UNUSED)
694 return finalized; 696 return finalized;
695} 697}
696 698
699EOLIAN static Eina_Bool
700_efl_object_invalidated_get(Eo *obj_id, Efl_Object_Data *pd EINA_UNUSED)
701{
702 Eina_Bool invalidated;
703 EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE);
704 invalidated = obj->invalidated;
705 EO_OBJ_DONE(obj_id);
706 return invalidated;
707}
708
697EOLIAN static Efl_Object * 709EOLIAN static Efl_Object *
698_efl_object_provider_find(const Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const Efl_Object *klass) 710_efl_object_provider_find(const Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const Efl_Object *klass)
699{ 711{
@@ -1069,10 +1081,12 @@ _special_event_count_inc(Efl_Object_Data *pd, const Efl_Callback_Array_Item *it)
1069 CB_COUNT_INC(pd->event_cb_efl_event_callback_add_count); 1081 CB_COUNT_INC(pd->event_cb_efl_event_callback_add_count);
1070 else if (it->desc == EFL_EVENT_CALLBACK_DEL) 1082 else if (it->desc == EFL_EVENT_CALLBACK_DEL)
1071 CB_COUNT_INC(pd->event_cb_efl_event_callback_del_count); 1083 CB_COUNT_INC(pd->event_cb_efl_event_callback_del_count);
1084 else if (it->desc == EFL_EVENT_INVALIDATE)
1085 CB_COUNT_INC(pd->event_cb_efl_event_invalidate_count);
1072 else if (it->desc == EFL_EVENT_DEL) 1086 else if (it->desc == EFL_EVENT_DEL)
1073 CB_COUNT_INC(pd->event_cb_efl_event_del_count); 1087 CB_COUNT_INC(pd->event_cb_efl_event_del_count);
1074 else if (it->desc == EFL_EVENT_DESTRUCT) 1088 else if (it->desc == EFL_EVENT_DESTRUCT)
1075 pd->has_destroyed_event_cb = EINA_TRUE; 1089 pd->has_destruct_event_cb = EINA_TRUE;
1076} 1090}
1077 1091
1078static inline void 1092static inline void
@@ -1082,6 +1096,8 @@ _special_event_count_dec(Efl_Object_Data *pd, const Efl_Callback_Array_Item *it)
1082 CB_COUNT_DEC(pd->event_cb_efl_event_callback_add_count); 1096 CB_COUNT_DEC(pd->event_cb_efl_event_callback_add_count);
1083 else if (it->desc == EFL_EVENT_CALLBACK_DEL) 1097 else if (it->desc == EFL_EVENT_CALLBACK_DEL)
1084 CB_COUNT_DEC(pd->event_cb_efl_event_callback_del_count); 1098 CB_COUNT_DEC(pd->event_cb_efl_event_callback_del_count);
1099 else if (it->desc == EFL_EVENT_INVALIDATE)
1100 CB_COUNT_INC(pd->event_cb_efl_event_invalidate_count);
1085 else if (it->desc == EFL_EVENT_DEL) 1101 else if (it->desc == EFL_EVENT_DEL)
1086 CB_COUNT_DEC(pd->event_cb_efl_event_del_count); 1102 CB_COUNT_DEC(pd->event_cb_efl_event_del_count);
1087} 1103}
@@ -1131,10 +1147,11 @@ _eo_callback_remove_all(Efl_Object_Data *pd)
1131 eina_freeq_ptr_main_add(pd->callbacks, free, 0); 1147 eina_freeq_ptr_main_add(pd->callbacks, free, 0);
1132 pd->callbacks = NULL; 1148 pd->callbacks = NULL;
1133 pd->callbacks_count = 0; 1149 pd->callbacks_count = 0;
1134 pd->has_destroyed_event_cb = EINA_FALSE; 1150 pd->has_destruct_event_cb = EINA_FALSE;
1135#ifdef EFL_EVENT_SPECIAL_SKIP 1151#ifdef EFL_EVENT_SPECIAL_SKIP
1136 pd->event_cb_efl_event_callback_add_count = 0; 1152 pd->event_cb_efl_event_callback_add_count = 0;
1137 pd->event_cb_efl_event_callback_del_count = 0; 1153 pd->event_cb_efl_event_callback_del_count = 0;
1154 pd->event_cb_efl_event_invalidate_count = 0;
1138 pd->event_cb_efl_event_del_count = 0; 1155 pd->event_cb_efl_event_del_count = 0;
1139#endif 1156#endif
1140} 1157}
@@ -1291,7 +1308,7 @@ _efl_object_event_callback_priority_add(Eo *obj, Efl_Object_Data *pd,
1291 _special_event_count_inc(pd, &(cb->items.item)); 1308 _special_event_count_inc(pd, &(cb->items.item));
1292#endif 1309#endif
1293 if (EINA_UNLIKELY(desc == EFL_EVENT_DESTRUCT)) 1310 if (EINA_UNLIKELY(desc == EFL_EVENT_DESTRUCT))
1294 pd->has_destroyed_event_cb = EINA_TRUE; 1311 pd->has_destruct_event_cb = EINA_TRUE;
1295 1312
1296 efl_event_callback_call(obj, EFL_EVENT_CALLBACK_ADD, (void *)arr); 1313 efl_event_callback_call(obj, EFL_EVENT_CALLBACK_ADD, (void *)arr);
1297 1314
@@ -1398,12 +1415,12 @@ _efl_object_event_callback_array_priority_add(Eo *obj, Efl_Object_Data *pd,
1398 for (it = cb->items.item_array; it->func; it++) 1415 for (it = cb->items.item_array; it->func; it++)
1399 _special_event_count_inc(pd, it); 1416 _special_event_count_inc(pd, it);
1400#else 1417#else
1401 if (!pd->has_destroyed_event_cb) 1418 if (!pd->has_destruct_event_cb)
1402 { 1419 {
1403 for (it = cb->items.item_array; it->func; it++) 1420 for (it = cb->items.item_array; it->func; it++)
1404 if (it->desc == EFL_EVENT_DESTRUCT) 1421 if (it->desc == EFL_EVENT_DESTRUCT)
1405 { 1422 {
1406 pd->has_destroyed_event_cb = EINA_TRUE; 1423 pd->has_destruct_event_cb = EINA_TRUE;
1407 break; 1424 break;
1408 } 1425 }
1409 } 1426 }
@@ -1482,6 +1499,8 @@ _event_callback_call(Eo *obj_id, Efl_Object_Data *pd,
1482 (pd->event_cb_efl_event_callback_add_count == 0)) return EINA_FALSE; 1499 (pd->event_cb_efl_event_callback_add_count == 0)) return EINA_FALSE;
1483 else if ((desc == EFL_EVENT_CALLBACK_DEL) && 1500 else if ((desc == EFL_EVENT_CALLBACK_DEL) &&
1484 (pd->event_cb_efl_event_callback_del_count == 0)) return EINA_FALSE; 1501 (pd->event_cb_efl_event_callback_del_count == 0)) return EINA_FALSE;
1502 else if ((desc == EFL_EVENT_INVALIDATE) &&
1503 (pd->event_cb_efl_event_invalidate_count == 0)) return EINA_FALSE;
1485 else if ((desc == EFL_EVENT_DEL) && 1504 else if ((desc == EFL_EVENT_DEL) &&
1486 (pd->event_cb_efl_event_del_count == 0)) return EINA_FALSE; 1505 (pd->event_cb_efl_event_del_count == 0)) return EINA_FALSE;
1487#endif 1506#endif
@@ -2025,6 +2044,14 @@ _efl_object_constructor(Eo *obj, Efl_Object_Data *pd EINA_UNUSED)
2025} 2044}
2026 2045
2027EOLIAN static void 2046EOLIAN static void
2047_efl_object_invalidator(Eo *obj, Efl_Object_Data *pd EINA_UNUSED)
2048{
2049 DBG("%p - %s.", obj, efl_class_name_get(obj));
2050
2051 _eo_condtor_done(obj);
2052}
2053
2054EOLIAN static void
2028_efl_object_destructor(Eo *obj, Efl_Object_Data *pd) 2055_efl_object_destructor(Eo *obj, Efl_Object_Data *pd)
2029{ 2056{
2030 Eo *child; 2057 Eo *child;
@@ -2073,7 +2100,7 @@ _efl_object_destructor(Eo *obj, Efl_Object_Data *pd)
2073 // this isn't 100% correct, as the object is still "slightly" alive at this 2100 // this isn't 100% correct, as the object is still "slightly" alive at this
2074 // point (so efl_destructed_is() returns false), but triggering the 2101 // point (so efl_destructed_is() returns false), but triggering the
2075 // "destruct" event here is the simplest, safest solution. 2102 // "destruct" event here is the simplest, safest solution.
2076 if (EINA_UNLIKELY(pd->has_destroyed_event_cb)) 2103 if (EINA_UNLIKELY(pd->has_destruct_event_cb))
2077 _event_callback_call(obj, pd, EFL_EVENT_DESTRUCT, NULL, EINA_FALSE); 2104 _event_callback_call(obj, pd, EFL_EVENT_DESTRUCT, NULL, EINA_FALSE);
2078 2105
2079 // remove generic data after this final event, in case they are used in a cb 2106 // remove generic data after this final event, in case they are used in a cb
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index 38f8c9eb03..74e19f2ca8 100644
--- a/src/lib/eo/eo_private.h
+++ b/src/lib/eo/eo_private.h
@@ -116,6 +116,8 @@ struct _Eo_Object
116 Eina_Bool finalized:1; 116 Eina_Bool finalized:1;
117 Eina_Bool super:1; 117 Eina_Bool super:1;
118 118
119 Eina_Bool invalidate_triggered:1;
120 Eina_Bool invalidated:1;
119 Eina_Bool del_triggered:1; 121 Eina_Bool del_triggered:1;
120 Eina_Bool destructed:1; 122 Eina_Bool destructed:1;
121 Eina_Bool manual_free:1; 123 Eina_Bool manual_free:1;
@@ -296,84 +298,142 @@ _efl_ref(_Eo_Object *obj)
296} 298}
297 299
298#define _efl_unref(obj) _efl_unref_internal(obj, __FUNCTION__, __FILE__, __LINE__) 300#define _efl_unref(obj) _efl_unref_internal(obj, __FUNCTION__, __FILE__, __LINE__)
301#define _efl_invalidate(obj) _efl_invalidate_internal(obj, __FUNCTION__, __FILE__, __LINE__)
302
303// returns true if del was intercepted
304static inline void
305_efl_invalidate_internal(_Eo_Object *obj, const char *func_name, const char *file, int line)
306{
307 Eo *obj_id = _eo_obj_id_get(obj);
308
309 if (EINA_UNLIKELY(obj->invalidated))
310 {
311 ERR("in %s:%d: func '%s' Object %p already invalidated.",
312 file, line, func_name, obj_id);
313 _eo_log_obj_report((Eo_Id) obj_id, EINA_LOG_LEVEL_ERR,
314 __FUNCTION__, __FILE__, __LINE__);
315 return;
316 }
317
318 if (EINA_UNLIKELY(obj->invalidate_triggered))
319 {
320 ERR("in %s:%d: func '%s' Object %p invalidate already triggered. "
321 "You wrongly call efl_invalidate() within an invalidator.",
322 file, line, func_name, obj_id);
323 _eo_log_obj_report((Eo_Id) obj_id, EINA_LOG_LEVEL_ERR,
324 __FUNCTION__, __FILE__, __LINE__);
325 return;
326 }
327
328 obj->refcount++;
329 obj->invalidate_triggered = EINA_TRUE;
330 obj->condtor_done = EINA_FALSE;
331 efl_event_callback_call(obj_id, EFL_EVENT_INVALIDATE, NULL);
332 efl_invalidator(obj_id);
333 obj->refcount--;
334
335 if (EINA_UNLIKELY(!obj->condtor_done))
336 {
337 ERR("in %s:%d: func '%s' Object %p of class '%s' - Not all of the "
338 "object invalidators have been executed.",
339 file, line, func_name, obj_id, obj->klass->desc->name);
340 obj->condtor_done = EINA_FALSE;
341 }
342
343 obj->invalidated = EINA_TRUE;
344 obj->invalidate_triggered = EINA_FALSE;
345}
346
299static inline void 347static inline void
300_efl_unref_internal(_Eo_Object *obj, const char *func_name, const char *file, int line) 348_efl_unref_internal(_Eo_Object *obj, const char *func_name, const char *file, int line)
301{ 349{
350 Eo *obj_id;
351
302 --(obj->refcount); 352 --(obj->refcount);
303 if (EINA_UNLIKELY(obj->refcount <= 0)) 353
354 if (EINA_LIKELY(obj->refcount > 0))
355 return;
356
357 obj_id = _eo_obj_id_get(obj);
358 if (obj->refcount < 0)
304 { 359 {
305 if (obj->refcount < 0) 360 ERR("in %s:%d: func '%s' Obj:%p. Refcount (%d) < 0. Too many unrefs.",
306 { 361 file, line, func_name, obj, obj->refcount);
307 ERR("in %s:%d: func '%s' Obj:%p. Refcount (%d) < 0. Too many unrefs.", file, line, func_name, obj, obj->refcount); 362 _eo_log_obj_report((Eo_Id) obj_id, EINA_LOG_LEVEL_ERR,
308 _eo_log_obj_report((Eo_Id)_eo_obj_id_get(obj), EINA_LOG_LEVEL_ERR, __FUNCTION__, __FILE__, __LINE__); 363 __FUNCTION__, __FILE__, __LINE__);
309 return; 364 return;
310 } 365 }
311 366
312 if (obj->destructed) 367 if (!obj->invalidated)
313 { 368 {
314 ERR("in %s:%d: func '%s' Object %p already destructed.", file, line, func_name, _eo_obj_id_get(obj)); 369 _efl_invalidate_internal(obj, func_name, file, line);
315 _eo_log_obj_report((Eo_Id)_eo_obj_id_get(obj), EINA_LOG_LEVEL_ERR, __FUNCTION__, __FILE__, __LINE__); 370 }
316 return;
317 }
318 371
319 if (obj->del_triggered) 372 if (obj->destructed)
320 { 373 {
321 ERR("in %s:%d: func '%s' Object %p deletion already triggered. You wrongly call efl_unref() within a destructor.", file, line, func_name, _eo_obj_id_get(obj)); 374 ERR("in %s:%d: func '%s' Object %p already destructed.",
322 _eo_log_obj_report((Eo_Id)_eo_obj_id_get(obj), EINA_LOG_LEVEL_ERR, __FUNCTION__, __FILE__, __LINE__); 375 file, line, func_name, obj_id);
323 return; 376 _eo_log_obj_report((Eo_Id) obj_id, EINA_LOG_LEVEL_ERR,
324 } 377 __FUNCTION__, __FILE__, __LINE__);
378 return;
379 }
325 380
326 if (obj->opt->del_intercept) 381 if (obj->del_triggered)
327 { 382 {
328 Eo *obj_id = _eo_obj_id_get(obj); 383 ERR("in %s:%d: func '%s' Object %p deletion already triggered. "
329 efl_ref(obj_id); 384 "You wrongly call efl_unref() within a destructor.",
330 obj->opt->del_intercept(obj_id); 385 file, line, func_name, obj_id);
331 return; 386 _eo_log_obj_report((Eo_Id) obj_id, EINA_LOG_LEVEL_ERR,
332 } 387 __FUNCTION__, __FILE__, __LINE__);
388 return;
389 }
333 390
334 obj->del_triggered = EINA_TRUE; 391 if (obj->opt->del_intercept)
392 {
393 obj->opt->del_intercept(efl_ref(obj_id));
394 return;
395 }
335 396
336 _efl_del_internal(obj, func_name, file, line); 397 obj->del_triggered = EINA_TRUE;
398 _efl_del_internal(obj, func_name, file, line);
337 399
338 if (EINA_LIKELY(!obj->manual_free)) 400 if (EINA_LIKELY(!obj->manual_free))
339 { 401 {
340#ifdef EO_DEBUG 402#ifdef EO_DEBUG
341 /* If for some reason it's not empty, clear it. */ 403 /* If for some reason it's not empty, clear it. */
342 Eo *obj_id = _eo_obj_id_get(obj); 404 while (obj->xrefs)
343 while (obj->xrefs) 405 {
406 Eina_Inlist *nitr = obj->xrefs->next;
407 Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
408 ERR("in %s:%d: func '%s' Object %p is still referenced by object %p. Origin: %s:%d",
409 file, line, func_name, obj_id, xref->ref_obj, xref->file, xref->line);
410 eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
411 obj->xrefs = nitr;
412 }
413 while (obj->data_xrefs)
414 {
415 Eina_Inlist *nitr = obj->data_xrefs->next;
416 Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
417 if (obj_id == xref->ref_obj)
344 { 418 {
345 Eina_Inlist *nitr = obj->xrefs->next; 419 WRN("in %s:%d: func '%s' Object %p still has a reference to its own data (subclass: %s). Origin: %s:%d",
346 Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node); 420 file, line, func_name, obj_id, xref->data_klass, xref->file, xref->line);
347 ERR("in %s:%d: func '%s' Object %p is still referenced by object %p. Origin: %s:%d",
348 file, line, func_name, obj_id, xref->ref_obj, xref->file, xref->line);
349 eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
350 obj->xrefs = nitr;
351 } 421 }
352 while (obj->data_xrefs) 422 else
353 { 423 {
354 Eina_Inlist *nitr = obj->data_xrefs->next; 424 ERR("in %s:%d: func '%s' Data of object %p (subclass: %s) is still referenced by object %p. Origin: %s:%d",
355 Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node); 425 file, line, func_name, obj_id, xref->data_klass, xref->ref_obj, xref->file, xref->line);
356 if (obj_id == xref->ref_obj)
357 {
358 WRN("in %s:%d: func '%s' Object %p still has a reference to its own data (subclass: %s). Origin: %s:%d",
359 file, line, func_name, obj_id, xref->data_klass, xref->file, xref->line);
360 }
361 else
362 {
363 ERR("in %s:%d: func '%s' Data of object %p (subclass: %s) is still referenced by object %p. Origin: %s:%d",
364 file, line, func_name, obj_id, xref->data_klass, xref->ref_obj, xref->file, xref->line);
365 }
366
367 eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
368 obj->data_xrefs = nitr;
369 } 426 }
370#endif
371 427
372 _eo_free(obj, EINA_FALSE); 428 eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
429 obj->data_xrefs = nitr;
373 } 430 }
374 else 431#endif
375 _efl_ref(obj); /* If we manual free, we keep a phantom ref. */ 432
433 _eo_free(obj, EINA_FALSE);
376 } 434 }
435 else
436 _efl_ref(obj); /* If we manual free, we keep a phantom ref. */
377} 437}
378 438
379Eina_Bool efl_future_init(void); 439Eina_Bool efl_future_init(void);
diff --git a/src/lib/evas/canvas/efl_input_focus.c b/src/lib/evas/canvas/efl_input_focus.c
index abf1c735ae..fc7e737892 100644
--- a/src/lib/evas/canvas/efl_input_focus.c
+++ b/src/lib/evas/canvas/efl_input_focus.c
@@ -32,7 +32,11 @@ _del_hook(Eo *evt)
32 else 32 else
33 { 33 {
34 efl_del_intercept_set(evt, NULL); 34 efl_del_intercept_set(evt, NULL);
35 efl_del(evt); 35 // FIXME
36 if (efl_parent_get(evt))
37 efl_parent_set(evt, NULL);
38 else
39 efl_unref(evt);
36 } 40 }
37} 41}
38 42
diff --git a/src/lib/evas/canvas/efl_input_key.c b/src/lib/evas/canvas/efl_input_key.c
index c6b8061211..e9bdcfd01c 100644
--- a/src/lib/evas/canvas/efl_input_key.c
+++ b/src/lib/evas/canvas/efl_input_key.c
@@ -31,7 +31,11 @@ _del_hook(Eo *evt)
31 else 31 else
32 { 32 {
33 efl_del_intercept_set(evt, NULL); 33 efl_del_intercept_set(evt, NULL);
34 efl_del(evt); 34 // FIXME
35 if (efl_parent_get(evt))
36 efl_parent_set(evt, NULL);
37 else
38 efl_unref(evt);
35 } 39 }
36} 40}
37 41
diff --git a/src/lib/evas/canvas/efl_input_pointer.c b/src/lib/evas/canvas/efl_input_pointer.c
index 282ffeaf8d..a11739abdb 100644
--- a/src/lib/evas/canvas/efl_input_pointer.c
+++ b/src/lib/evas/canvas/efl_input_pointer.c
@@ -42,7 +42,11 @@ _del_hook(Eo *evt)
42 else 42 else
43 { 43 {
44 efl_del_intercept_set(evt, NULL); 44 efl_del_intercept_set(evt, NULL);
45 efl_del(evt); 45 // FIXME
46 if (efl_parent_get(evt))
47 efl_parent_set(evt, NULL);
48 else
49 efl_unref(evt);
46 } 50 }
47} 51}
48 52