Eo: Added eo_manual_free* funcs.

Patch by Daniel Zaoui.

SVN revision: 71281
This commit is contained in:
Tom Hacohen 2012-05-21 11:45:32 +00:00
parent 510cada94b
commit bff3911c08
3 changed files with 149 additions and 12 deletions

View File

@ -749,7 +749,35 @@ EAPI void eo_composite_object_detach(Eo *obj, Eo *comp_obj);
* @see eo_composite_object_attach()
* @see eo_composite_object_detach()
*/
EAPI Eina_Bool eo_composite_is(Eo *comp_obj);
EAPI Eina_Bool eo_composite_is(const Eo *comp_obj);
/**
* @brief Enable or disable the manual free feature.
* @param obj the object to work on.
* @param manual_free indicates if the free is manual (EINA_TRUE) or automatic (EINA_FALSE).
*
* The developer is in charge to call the function eo_manual_free to free the memory allocated for this object.
*
* Do not use, unless you really know what you are doing. It's used by Evas
* because evas wants to keep its private data available even after the object
* is deleted. Setting this to true makes Eo destruct the object but not free
* the private data or the object itself.
*
* @see eo_manual_free()
*/
EAPI void eo_manual_free_set(Eo *obj, Eina_Bool manual_free);
/**
* @brief Frees the object.
* @param obj the object to work on.
* This function must be called by the developer if the function
* eo_manual_free_set has been called before with the parameter EINA_TRUE.
* An error will be printed if this function is called when the manual
* free option is not set to EINA_TRUE or the number of refs is not 0.
*
* @see eo_manual_free_set()
*/
EAPI void eo_manual_free(Eo *obj);
/**
* @}

View File

@ -44,6 +44,7 @@ struct _Eo {
Eina_Bool del:1;
Eina_Bool construct_error:1;
Eina_Bool manual_free:1;
};
/* Start of Dich */
@ -1193,6 +1194,13 @@ _eo_del_internal(Eo *obj)
obj->refcount--;
}
static inline void
_eo_free(Eo *obj)
{
EINA_MAGIC_SET(obj, EO_DELETED_EINA_MAGIC);
free(obj);
}
static inline void
_eo_unref(Eo *obj)
{
@ -1201,18 +1209,17 @@ _eo_unref(Eo *obj)
_eo_del_internal(obj);
#ifndef NDEBUG
/* If for some reason it's not empty, clear it. */
while (obj->xrefs)
{
WRN("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.");
Eina_Inlist *nitr = obj->xrefs->next;
free(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node));
obj->xrefs = nitr;
}
/* If for some reason it's not empty, clear it. */
while (obj->xrefs)
{
WRN("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.");
Eina_Inlist *nitr = obj->xrefs->next;
free(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node));
obj->xrefs = nitr;
}
#endif
EINA_MAGIC_SET(obj, EO_DELETED_EINA_MAGIC);
free(obj);
if (!obj->manual_free) _eo_free(obj);
}
}
@ -1466,7 +1473,7 @@ eo_composite_object_detach(Eo *obj, Eo *emb_obj)
}
EAPI Eina_Bool
eo_composite_is(Eo *emb_obj)
eo_composite_is(const Eo *emb_obj)
{
if (!EINA_MAGIC_CHECK(emb_obj, EO_EINA_MAGIC))
{
@ -1490,4 +1497,30 @@ eo_composite_is(Eo *emb_obj)
return EINA_FALSE;
}
EAPI void
eo_manual_free_set(Eo *obj, Eina_Bool manual_free)
{
EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
obj->manual_free = manual_free;
}
EAPI void
eo_manual_free(Eo *obj)
{
EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
if (EINA_FALSE == obj->manual_free)
{
ERR("Tried to free manually the object %p while the option has not been set; see eo_manual_free_set for more information.", obj);
return;
}
if (0 != obj->refcount)
{
ERR("Tried deleting the object %p while still referenced(%d).", obj, eo_ref_get(obj));
return;
}
_eo_free(obj);
}

View File

@ -59,6 +59,76 @@ START_TEST(eo_data_fetch)
}
END_TEST
static void
_man_con(Eo *obj, void *data EINA_UNUSED)
{
eo_manual_free_set(obj, EINA_TRUE);
eo_constructor_super(obj);
}
static void
_man_des(Eo *obj, void *data EINA_UNUSED)
{
eo_destructor_super(obj);
eo_manual_free_set(obj, EINA_FALSE);
}
START_TEST(eo_man_free)
{
eo_init();
/* Usually should be const, not const only for the test... */
static Eo_Class_Description class_desc = {
"Simple2",
EO_CLASS_TYPE_REGULAR,
EO_CLASS_DESCRIPTION_OPS(NULL, NULL, 0),
NULL,
10,
_man_con,
_man_des,
NULL,
NULL
};
const Eo_Class *klass = eo_class_new(&class_desc, EO_BASE_CLASS, NULL);
fail_if(!klass);
Eo *obj = eo_add(klass, NULL);
fail_if(!obj);
eo_unref(obj);
obj = eo_add(klass, NULL);
fail_if(!obj);
eo_manual_free(obj);
eo_unref(obj);
class_desc.destructor = NULL;
klass = eo_class_new(&class_desc, EO_BASE_CLASS, NULL);
fail_if(!klass);
obj = eo_add(klass, NULL);
fail_if(!obj);
eo_manual_free(obj);
eo_unref(obj);
obj = eo_add(klass, NULL);
fail_if(!obj);
eo_unref(obj);
eo_manual_free(obj);
class_desc.constructor = NULL;
klass = eo_class_new(&class_desc, EO_BASE_CLASS, NULL);
fail_if(!klass);
obj = eo_add(klass, NULL);
fail_if(!obj);
eo_manual_free(obj);
eo_unref(obj);
eo_shutdown();
}
END_TEST
START_TEST(eo_refs)
{
eo_init();
@ -371,6 +441,11 @@ START_TEST(eo_magic_checks)
eo_do(obj, eo_event_callback_forwarder_add(NULL, (Eo *) buf));
eo_do(obj, eo_event_callback_forwarder_del(NULL, (Eo *) buf));
eo_manual_free_set((Eo *) buf, EINA_TRUE);
eo_manual_free((Eo *) buf);
eo_manual_free_set(NULL, EINA_TRUE);
eo_manual_free(NULL);
eo_unref(obj);
eo_shutdown();
@ -386,4 +461,5 @@ void eo_test_general(TCase *tc)
tcase_add_test(tc, eo_refs);
tcase_add_test(tc, eo_magic_checks);
tcase_add_test(tc, eo_data_fetch);
tcase_add_test(tc, eo_man_free);
}