eo: make eo_parent_get/set part of eo_base_class.

This commit is contained in:
Cedric Bail 2013-09-25 13:32:13 +09:00
parent b5472db51d
commit 936a8072f2
4 changed files with 202 additions and 174 deletions

View File

@ -787,39 +787,6 @@ EAPI void eo_error_set_internal(const Eo *obj, const char *file, int line);
*/
EAPI Eo *eo_add_internal(const char *file, int line, const Eo_Class *klass, Eo *parent, ...);
/**
* @brief Get the parent of an object
* @param obj the object to get the parent of.
* @return a pointer to the parent object.
*
* @see eo_parent_set()
*/
EAPI Eo *eo_parent_get(const Eo *obj);
/**
* @brief Get an iterator on all childrens
* @param obj the object to get the childrens from.
* @return a pointer to an Eina_Iterator containing all the childrens.
*
* @see eo_parent_set()
*/
EAPI Eina_Iterator *eo_children_iterator_new(Eo *obj_id);
/**
* @brief Set the parent of an object
* @param obj the object to get the parent of.
* @param parent the new parent.
* @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
*
* Parents keep references to their children so in order to delete objects
* that have parents you need to set parent to NULL or use eo_del() that
* does that for you (and also unrefs the object).
*
* @see eo_del()
* @see eo_parent_get()
*/
EAPI Eina_Bool eo_parent_set(Eo *obj, const Eo *parent);
/**
* @brief Get a pointer to the data of an object for a specific class.
* @param obj the object to work on.
@ -1094,6 +1061,9 @@ extern EAPI Eo_Op EO_BASE_BASE_ID;
enum {
EO_BASE_SUB_ID_CONSTRUCTOR,
EO_BASE_SUB_ID_DESTRUCTOR,
EO_BASE_SUB_ID_PARENT_SET,
EO_BASE_SUB_ID_PARENT_GET,
EO_BASE_SUB_ID_CHILDREN_ITERATOR_NEW,
EO_BASE_SUB_ID_DATA_SET,
EO_BASE_SUB_ID_DATA_GET,
EO_BASE_SUB_ID_DATA_DEL,
@ -1163,6 +1133,36 @@ enum {
*/
#define eo_base_data_del(key) EO_BASE_ID(EO_BASE_SUB_ID_DATA_DEL), EO_TYPECHECK(const char *, key)
/**
* @brief Set the parent of an object
* @param[in] parent the new parent.
*
* Parents keep references to their children so in order to delete objects
* that have parents you need to set parent to NULL or use eo_del() that
* does that for you (and also unrefs the object).
*
* @see eo_del()
* @see eo_parent_get()
*/
#define eo_parent_set(parent) EO_BASE_ID(EO_BASE_SUB_ID_PARENT_SET), EO_TYPECHECK(Eo *, parent)
/**
* @brief Get the parent of an object
* @param[out] a pointer to the parent object.
*
* @see eo_parent_set()
*/
#define eo_parent_get(parent) EO_BASE_ID(EO_BASE_SUB_ID_PARENT_GET), EO_TYPECHECK(Eo **, parent)
/**
* @brief Get an iterator on all childrens
* @param obj the object to get the childrens from.
* @return a pointer to an Eina_Iterator containing all the childrens.
*
* @see eo_parent_set()
*/
#define eo_children_iterator_new(it) EO_BASE_ID(EO_BASE_SUB_ID_CHILDREN_ITERATOR_NEW), EO_TYPECHECK(Eina_Iterator **, it)
/**
* @def eo_wref_add
* @brief Add a new weak reference to obj.

View File

@ -1043,133 +1043,17 @@ eo_isa(const Eo *obj_id, const Eo_Class *klass_id)
return (func && (func->func == _eo_class_isa_func));
}
EAPI Eina_Bool
eo_parent_set(Eo *obj_id, const Eo *parent_id)
{
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE);
if (parent_id)
{
EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, EINA_FALSE);
}
if (obj->parent == parent_id)
return EINA_TRUE;
_eo_ref(obj);
if (eo_composite_is(obj_id))
{
eo_composite_detach(obj_id, obj->parent);
}
if (obj->parent)
{
EO_OBJ_POINTER_RETURN_VAL(obj->parent, obj_parent, EINA_FALSE);
obj_parent->children = eina_list_remove(obj_parent->children, obj_id);
eo_xunref(obj_id, obj->parent);
}
obj->parent = (Eo *) parent_id;
if (obj->parent)
{
EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, EINA_FALSE);
parent->children = eina_list_append(parent->children, obj_id);
eo_xref(obj_id, obj->parent);
}
_eo_unref(obj);
return EINA_TRUE;
}
/* Children accessor */
typedef struct _Eo_Children_Iterator Eo_Children_Iterator;
struct _Eo_Children_Iterator
{
Eina_Iterator iterator;
Eina_List *current;
_Eo *obj;
Eo *obj_id;
};
static Eina_Bool
_eo_children_iterator_next(Eo_Children_Iterator *it, void **data)
{
if (!it->current) return EINA_FALSE;
if (data) *data = eina_list_data_get(it->current);
it->current = eina_list_next(it->current);
return EINA_TRUE;
}
static Eo *
_eo_children_iterator_container(Eo_Children_Iterator *it)
{
return it->obj_id;
}
// A little bit hacky, but does the job
static void
_eo_children_iterator_free(Eo_Children_Iterator *it)
_eo_parent_internal_set(_Eo *obj, ...)
{
_Eo_Class *klass;
_Eo *obj;
va_list p_list;
klass = (_Eo_Class*) it->obj->klass;
obj = it->obj;
eina_lock_take(&klass->iterators.trash_lock);
if (klass->iterators.trash_count < 8)
{
klass->iterators.trash_count++;
eina_trash_push(&klass->iterators.trash, it);
}
else
{
free(it);
}
eina_lock_release(&klass->iterators.trash_lock);
_eo_unref(obj);
}
EAPI Eina_Iterator *
eo_children_iterator_new(Eo *obj_id)
{
Eo_Children_Iterator *it;
_Eo_Class *klass;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
if (!obj->children) return NULL;
klass = (_Eo_Class*) obj->klass;
eina_lock_take(&klass->iterators.trash_lock);
it = eina_trash_pop(&klass->iterators.trash);
if (it)
{
klass->iterators.trash_count--;
memset(it, 0, sizeof (Eo_Children_Iterator));
}
else
{
it = calloc(1, sizeof (Eo_Children_Iterator));
}
eina_lock_release(&klass->iterators.trash_lock);
if (!it) return NULL;
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
it->current = obj->children;
it->obj = _eo_ref(obj);
it->obj_id = obj_id;
it->iterator.next = FUNC_ITERATOR_NEXT(_eo_children_iterator_next);
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eo_children_iterator_container);
it->iterator.free = FUNC_ITERATOR_FREE(_eo_children_iterator_free);
return &it->iterator;
va_start(p_list, obj);
_eo_op_internal("eo.c", 1049, obj, obj->klass,
EO_OP_TYPE_REGULAR, EO_BASE_ID(EO_BASE_SUB_ID_PARENT_SET),
&p_list);
va_end(p_list);
}
EAPI Eo *
@ -1212,12 +1096,13 @@ eo_add_internal(const char *file, int line, const Eo_Class *klass_id, Eo *parent
#endif
Eo_Id obj_id = _eo_id_allocate(obj);
obj->obj_id = obj_id;
eo_parent_set((Eo *)obj_id, parent_id);
_eo_condtor_reset(obj);
_eo_ref(obj);
_eo_parent_internal_set(obj, parent_id);
/* Run the relevant do stuff. */
{
va_list p_list;
@ -1322,7 +1207,7 @@ eo_unref(const Eo *obj_id)
EAPI void
eo_del(const Eo *obj)
{
eo_parent_set((Eo *) obj, NULL);
eo_do((Eo *) obj, eo_parent_set(NULL));
eo_unref(obj);
}
@ -1334,14 +1219,6 @@ eo_ref_get(const Eo *obj_id)
return obj->refcount;
}
EAPI Eo *
eo_parent_get(const Eo *obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
return obj->parent;
}
EAPI void
eo_error_set_internal(const Eo *obj_id, const char *file, int line)
{
@ -1624,7 +1501,8 @@ eo_composite_attach(Eo *comp_obj_id, Eo *parent_id)
comp_obj->composite = EINA_TRUE;
parent->composite_objects = eina_list_prepend(parent->composite_objects, comp_obj_id);
eo_parent_set(comp_obj_id, parent_id);
eo_do(comp_obj_id, eo_parent_set(parent_id));
}
EAPI void
@ -1635,7 +1513,7 @@ eo_composite_detach(Eo *comp_obj_id, Eo *parent_id)
comp_obj->composite = EINA_FALSE;
parent->composite_objects = eina_list_remove(parent->composite_objects, comp_obj_id);
eo_parent_set(comp_obj_id, NULL);
eo_do(comp_obj_id, eo_parent_set(NULL));
}
EAPI Eina_Bool

View File

@ -16,6 +16,9 @@ typedef struct _Eo_Callback_Description Eo_Callback_Description;
typedef struct
{
Eina_List *children;
Eo *parent;
Eina_Inlist *generic_data;
Eo ***wrefs;
@ -108,6 +111,147 @@ _data_get(Eo *obj EINA_UNUSED, void *class_data, va_list *list)
}
}
static void
_parent_set(Eo *obj, void *class_data, va_list *list)
{
Private_Data *pd = (Private_Data *) class_data;
EO_PARAMETER_GET(Eo *, parent_id, list);
if (pd->parent == parent_id)
return ;
if (eo_composite_is(obj))
{
eo_composite_detach(obj, pd->parent);
}
if (pd->parent)
{
Private_Data *old_parent_pd;
old_parent_pd = eo_data_scope_get(pd->parent, EO_BASE_CLASS);
old_parent_pd->children = eina_list_remove(old_parent_pd->children,
obj);
eo_xunref(obj, pd->parent);
}
pd->parent = parent_id;
if (pd->parent)
{
Private_Data *parent_pd = NULL;
parent_pd = eo_data_scope_get(parent_id, EO_BASE_CLASS);
parent_pd->children = eina_list_append(parent_pd->children,
obj);
eo_xref(obj, pd->parent);
}
}
static void
_parent_get(Eo *obj EINA_UNUSED, void *class_data, va_list *list)
{
Private_Data *pd = (Private_Data *) class_data;
EO_PARAMETER_GET(Eo **, parent_id, list);
if (!parent_id) return ;
*parent_id = pd->parent;
}
/* Children accessor */
typedef struct _Eo_Children_Iterator Eo_Children_Iterator;
struct _Eo_Children_Iterator
{
Eina_Iterator iterator;
Eina_List *current;
_Eo *obj;
Eo *obj_id;
};
static Eina_Bool
_eo_children_iterator_next(Eo_Children_Iterator *it, void **data)
{
if (!it->current) return EINA_FALSE;
if (data) *data = eina_list_data_get(it->current);
it->current = eina_list_next(it->current);
return EINA_TRUE;
}
static Eo *
_eo_children_iterator_container(Eo_Children_Iterator *it)
{
return it->obj_id;
}
static void
_eo_children_iterator_free(Eo_Children_Iterator *it)
{
_Eo_Class *klass;
_Eo *obj;
klass = (_Eo_Class*) it->obj->klass;
obj = it->obj;
eina_lock_take(&klass->iterators.trash_lock);
if (klass->iterators.trash_count < 8)
{
klass->iterators.trash_count++;
eina_trash_push(&klass->iterators.trash, it);
}
else
{
free(it);
}
eina_lock_release(&klass->iterators.trash_lock);
_eo_unref(obj);
}
static void
_children_iterator_new(Eo *obj_id, void *class_data, va_list *list)
{
Private_Data *pd = class_data;
_Eo_Class *klass;
EO_PARAMETER_GET(Eo_Children_Iterator **, it, list);
EO_OBJ_POINTER_RETURN(obj_id, obj);
if (!it) return ;
*it = NULL;
if (!pd->children) return ;
klass = (_Eo_Class *) obj->klass;
eina_lock_take(&klass->iterators.trash_lock);
*it = eina_trash_pop(&klass->iterators.trash);
if (*it)
{
klass->iterators.trash_count--;
memset(*it, 0, sizeof (Eo_Children_Iterator));
}
else
{
*it = calloc(1, sizeof (Eo_Children_Iterator));
}
eina_lock_release(&klass->iterators.trash_lock);
if (!*it) return ;
EINA_MAGIC_SET(&(*it)->iterator, EINA_MAGIC_ITERATOR);
(*it)->current = obj->children;
(*it)->obj = _eo_ref(obj);
(*it)->obj_id = obj_id;
(*it)->iterator.next = FUNC_ITERATOR_NEXT(_eo_children_iterator_next);
(*it)->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eo_children_iterator_container);
(*it)->iterator.free = FUNC_ITERATOR_FREE(_eo_children_iterator_free);
}
static void
_dbg_info_get(Eo *obj EINA_UNUSED, void *class_data EINA_UNUSED,
va_list *data EINA_UNUSED)
@ -746,8 +890,13 @@ _constructor(Eo *obj, void *class_data EINA_UNUSED, va_list *list EINA_UNUSED)
static void
_destructor(Eo *obj, void *class_data, va_list *list EINA_UNUSED)
{
Private_Data *pd = class_data;
DBG("%p - %s.", obj, eo_class_name_get(MY_CLASS));
while (pd->children)
eo_do(eina_list_data_get(pd->children), eo_parent_set(NULL));
_eo_generic_data_del_all(class_data);
_wref_destruct(class_data);
_eo_callback_remove_all(class_data);
@ -763,6 +912,9 @@ _class_constructor(Eo_Class *klass)
const Eo_Op_Func_Description func_desc[] = {
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_PARENT_SET), _parent_set),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_PARENT_GET), _parent_get),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CHILDREN_ITERATOR_NEW), _children_iterator_new),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DATA_SET), _data_set),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DATA_GET), _data_get),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DATA_DEL), _data_del),
@ -791,6 +943,9 @@ _class_constructor(Eo_Class *klass)
static const Eo_Op_Description op_desc[] = {
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_CONSTRUCTOR, "Constructor"),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_DESTRUCTOR, "Destructor"),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_PARENT_SET, "Set parent"),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_PARENT_GET, "Get parent"),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_CHILDREN_ITERATOR_NEW, "Children Iterator"),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_DATA_SET, "Set data for key."),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_DATA_GET, "Get data for key."),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_DATA_DEL, "Del key."),

View File

@ -214,11 +214,6 @@ _eo_del_internal(const char *file, int line, _Eo *obj)
}
}
while (obj->children)
{
eo_parent_set(eina_list_data_get(obj->children), NULL); // ZZZ
}
obj->del = EINA_TRUE;
obj->refcount--;
}