From cd77853222d1c11d71da4ca9066abe35390dcd5e Mon Sep 17 00:00:00 2001 From: Cedric Bail Date: Wed, 11 Sep 2013 16:08:06 +0900 Subject: [PATCH] eo: add eo_childrens_iterator_new(). The goal would be to replace the smart children list and friends. The problem is that they differ in content. Smart children and Eo children are the same, but Elm children and them differ. If I put this function as a virtual, it would be possible to override the list of children and if we start using it in Evas render loop, that could result in "weird" behavior. I have added the use of a simplified Eina_Trash mempool kind of feature to have some fast path for allocation if we start using it in Evas render loop. --- src/lib/eo/Eo.h | 9 ++++ src/lib/eo/eo.c | 113 ++++++++++++++++++++++++++++++++++++---- src/lib/eo/eo_private.h | 26 +++++---- 3 files changed, 130 insertions(+), 18 deletions(-) diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index 049dcaa070..4921f6d01c 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -796,6 +796,15 @@ EAPI Eo *eo_add_internal(const char *file, int line, const Eo_Class *klass, Eo * */ 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_childrens_iterator_new(Eo *obj_id); + /** * @brief Set the parent of an object * @param obj the object to get the parent of. diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index 835eb86178..1985a571a3 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -687,7 +687,7 @@ eo_class_funcs_set(Eo_Class *klass_id, const Eo_Op_Func_Description *func_descs) static void eo_class_free(_Eo_Class *klass) { - void *object; + void *data; if (klass->constructed) { @@ -697,10 +697,14 @@ eo_class_free(_Eo_Class *klass) _dich_func_clean_all(klass); } - EINA_TRASH_CLEAN(&klass->trash, object) - free(object); + EINA_TRASH_CLEAN(&klass->objects.trash, data) + free(data); - eina_lock_free(&klass->trash_lock); + EINA_TRASH_CLEAN(&klass->iterators.trash, data) + free(data); + + eina_lock_free(&klass->objects.trash_lock); + eina_lock_free(&klass->iterators.trash_lock); free(klass); } @@ -893,7 +897,8 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...) klass = calloc(1, _eo_class_sz + extn_sz + mro_sz + mixins_sz); EINA_MAGIC_SET(klass, EO_CLASS_EINA_MAGIC); - eina_lock_new(&klass->trash_lock); + eina_lock_new(&klass->objects.trash_lock); + eina_lock_new(&klass->iterators.trash_lock); klass->parent = parent; klass->desc = desc; klass->extensions = (const _Eo_Class **) ((char *) klass + _eo_class_sz); @@ -1077,6 +1082,96 @@ eo_parent_set(Eo *obj_id, const Eo *parent_id) 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; +} + +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); +} + +EAPI Eina_Iterator * +eo_childrens_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; +} + EAPI Eo * eo_add_internal(const char *file, int line, const Eo_Class *klass_id, Eo *parent_id, ...) { @@ -1096,18 +1191,18 @@ eo_add_internal(const char *file, int line, const Eo_Class *klass_id, Eo *parent return NULL; } - eina_lock_take(&klass->trash_lock); - obj = eina_trash_pop(&klass->trash); + eina_lock_take(&klass->objects.trash_lock); + obj = eina_trash_pop(&klass->objects.trash); if (obj) { memset(obj, 0, klass->obj_size); - klass->trash_count--; + klass->objects.trash_count--; } else { obj = calloc(1, klass->obj_size); } - eina_lock_release(&klass->trash_lock); + eina_lock_release(&klass->objects.trash_lock); obj->refcount++; obj->klass = klass; diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h index 591251771a..0553c7b2a2 100644 --- a/src/lib/eo/eo_private.h +++ b/src/lib/eo/eo_private.h @@ -140,9 +140,18 @@ struct _Eo_Class const _Eo_Class **mro; /* cached object for faster allocation */ - Eina_Trash *trash; - Eina_Lock trash_lock; - unsigned int trash_count; + struct { + Eina_Trash *trash; + Eina_Lock trash_lock; + unsigned int trash_count; + } objects; + + /* cached iterator for faster allocation cycle */ + struct { + Eina_Trash *trash; + Eina_Lock trash_lock; + unsigned int trash_count; + } iterators; unsigned int obj_size; /**< size of an object of this class */ unsigned int chain_size; @@ -219,18 +228,17 @@ _eo_free(_Eo *obj) #endif _eo_id_release(obj->obj_id); - eina_lock_take(&klass->trash_lock); - if (klass->trash_count <= 8) + eina_lock_take(&klass->objects.trash_lock); + if (klass->objects.trash_count <= 8) { - eina_trash_push(&klass->trash, obj); - klass->trash_count++; - eina_lock_release(&klass->trash_lock); + eina_trash_push(&klass->objects.trash, obj); + klass->objects.trash_count++; } else { - eina_lock_release(&klass->trash_lock); free(obj); } + eina_lock_release(&klass->objects.trash_lock); } static inline _Eo *