eo2: add eo2_parent_set(), eo2_parent_get(), eo2_children_iterator_new()

imported from eo_base_class.c as is in
a7f417e 2013-12-24 23:45:30 +0900 <Carsten Haitzler (Rasterman)>
This commit is contained in:
Jérémy Zurcher 2013-12-26 21:11:48 +01:00 committed by Tom Hacohen
parent d4aad6bfc0
commit c9ccc700fd
3 changed files with 178 additions and 2 deletions

View File

@ -1391,6 +1391,8 @@ eo2_base_data_del(const char *key);
* @see eo_parent_get()
*/
#define eo_parent_set(parent) EO_BASE_ID(EO_BASE_SUB_ID_PARENT_SET), EO_TYPECHECK(Eo *, parent)
EAPI void
eo2_parent_set(Eo *parent_id);
/**
* @def eo_parent_get
@ -1400,6 +1402,8 @@ eo2_base_data_del(const char *key);
* @see eo_parent_set()
*/
#define eo_parent_get(parent) EO_BASE_ID(EO_BASE_SUB_ID_PARENT_GET), EO_TYPECHECK(Eo **, parent)
EAPI Eo *
eo2_parent_get();
/**
* @def eo_children_iterator_new
@ -1410,6 +1414,8 @@ eo2_base_data_del(const char *key);
* @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)
EAPI Eina_Iterator *
eo2_children_iterator_new();
/**
* @def eo_wref_add

View File

@ -650,10 +650,11 @@ eo2_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo
#endif
Eo_Id obj_id = _eo_id_allocate(obj);
obj->header.id = obj_id;
eo_parent_set((Eo *)obj_id, parent_id);
_eo_condtor_reset(obj);
eo2_do((Eo *)obj_id, eo2_parent_set(parent_id));
return (Eo *)obj_id;
}
@ -1655,7 +1656,11 @@ eo_unref(const Eo *obj_id)
EAPI void
eo_del(const Eo *obj)
{
eo_do((Eo *) obj, eo_parent_set(NULL));
EO_OBJ_POINTER_RETURN(obj, _obj);
if (_obj->klass->desc->version == EO2_VERSION)
eo2_do((Eo *) obj, eo2_parent_set(NULL));
else
eo_do((Eo *) obj, eo_parent_set(NULL));
eo_unref(obj);
}

View File

@ -14,6 +14,9 @@ typedef struct _Eo_Callback_Description Eo_Callback_Description;
typedef struct
{
Eina_List *children;
Eo *parent;
Eina_Inlist *generic_data;
Eo ***wrefs;
@ -101,6 +104,165 @@ _data_get(Eo *obj EINA_UNUSED, void *class_data, const char *key)
}
EAPI EO2_VOID_FUNC_BODYV(eo2_base_data_get, EO2_FUNC_CALL(key), const char *key);
static void
_parent_set(Eo *obj, void *class_data, Eo *parent_id)
{
Private_Data *pd = (Private_Data *) class_data;
if (pd->parent == parent_id)
return;
if (eo_composite_is(obj) && pd->parent)
{
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);
if (old_parent_pd)
{
old_parent_pd->children = eina_list_remove(old_parent_pd->children,
obj);
}
else
{
ERR("CONTACT DEVS!!! SHOULD NEVER HAPPEN!!! Old parent %p for object %p is not a valid Eo object.",
pd->parent, obj);
}
eo_xunref(obj, pd->parent);
}
/* Set new parent */
if (parent_id)
{
Private_Data *parent_pd = NULL;
parent_pd = eo_data_scope_get(parent_id, EO_BASE_CLASS);
if (EINA_LIKELY(parent_pd != NULL))
{
pd->parent = parent_id;
parent_pd->children = eina_list_append(parent_pd->children,
obj);
eo_xref(obj, pd->parent);
}
else
{
pd->parent = NULL;
ERR("New parent %p for object %p is not a valid Eo object.",
parent_id, obj);
}
}
else
{
pd->parent = NULL;
}
}
EAPI EO2_VOID_FUNC_BODYV(eo2_parent_set, EO2_FUNC_CALL(parent_id), Eo *parent_id);
static Eo *
_parent_get(Eo *obj EINA_UNUSED, void *class_data)
{
Private_Data *pd = (Private_Data *) class_data;
return pd->parent;
}
EAPI EO2_FUNC_BODY(eo2_parent_get, Eo *, NULL);
/* Children accessor */
typedef struct _Eo_Children_Iterator Eo_Children_Iterator;
struct _Eo_Children_Iterator
{
Eina_Iterator iterator;
Eina_List *current;
_Eo_Object *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_Object *obj;
klass = (_Eo_Class*) it->obj->klass;
obj = it->obj;
eina_spinlock_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_spinlock_release(&klass->iterators.trash_lock);
_eo_unref(obj);
}
static Eina_Iterator *
_children_iterator_new(Eo *obj_id, void *class_data)
{
Private_Data *pd = class_data;
_Eo_Class *klass;
Eo_Children_Iterator *it;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
if (!pd->children) return NULL;
klass = (_Eo_Class *) obj->klass;
eina_spinlock_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_spinlock_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 (Eina_Iterator *)it;
}
EAPI EO2_FUNC_BODY(eo2_children_iterator_new, Eina_Iterator *, NULL);
static void
_dbg_info_get(Eo *obj EINA_UNUSED, void *class_data EINA_UNUSED, Eo_Dbg_Info *root_node EINA_UNUSED)
{ /* No info required in the meantime */
@ -790,6 +952,9 @@ _class_constructor(Eo_Class *klass EINA_UNUSED)
Eo2_Op_Description op_descs [] = {
EO2_OP_FUNC(_constructor, eo2_constructor, "Constructor."),
EO2_OP_FUNC(_destructor, eo2_destructor, "Destructor."),
EO2_OP_FUNC(_parent_set, eo2_parent_set, "Set parent."),
EO2_OP_FUNC(_parent_get, eo2_parent_get, "Get parent."),
EO2_OP_FUNC(_children_iterator_new, eo2_children_iterator_new, "Get Children Iterator."),
EO2_OP_FUNC(_data_set, eo2_base_data_set, "Set data for key."),
EO2_OP_FUNC(_data_get, eo2_base_data_get, "Get data for key."),
EO2_OP_FUNC(_data_del, eo2_base_data_del, "Del key."),