summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric Bail <cedric.bail@samsung.com>2013-09-11 16:08:06 +0900
committerCedric Bail <cedric.bail@samsung.com>2013-09-11 16:08:06 +0900
commitcd77853222d1c11d71da4ca9066abe35390dcd5e (patch)
tree974d7924b4a01cdd294fcba95c14f46a75e3b291
parent766d1d178884c8f33c14170ff0c14cefbb2ae31d (diff)
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.
-rw-r--r--src/lib/eo/Eo.h9
-rw-r--r--src/lib/eo/eo.c113
-rw-r--r--src/lib/eo/eo_private.h26
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
@@ -797,6 +797,15 @@ EAPI Eo *eo_add_internal(const char *file, int line, const Eo_Class *klass, Eo *
797EAPI Eo *eo_parent_get(const Eo *obj); 797EAPI Eo *eo_parent_get(const Eo *obj);
798 798
799/** 799/**
800 * @brief Get an iterator on all childrens
801 * @param obj the object to get the childrens from.
802 * @return a pointer to an Eina_Iterator containing all the childrens.
803 *
804 * @see eo_parent_set()
805 */
806EAPI Eina_Iterator *eo_childrens_iterator_new(Eo *obj_id);
807
808/**
800 * @brief Set the parent of an object 809 * @brief Set the parent of an object
801 * @param obj the object to get the parent of. 810 * @param obj the object to get the parent of.
802 * @param parent the new parent. 811 * @param parent the new parent.
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)
687static void 687static void
688eo_class_free(_Eo_Class *klass) 688eo_class_free(_Eo_Class *klass)
689{ 689{
690 void *object; 690 void *data;
691 691
692 if (klass->constructed) 692 if (klass->constructed)
693 { 693 {
@@ -697,10 +697,14 @@ eo_class_free(_Eo_Class *klass)
697 _dich_func_clean_all(klass); 697 _dich_func_clean_all(klass);
698 } 698 }
699 699
700 EINA_TRASH_CLEAN(&klass->trash, object) 700 EINA_TRASH_CLEAN(&klass->objects.trash, data)
701 free(object); 701 free(data);
702 702
703 eina_lock_free(&klass->trash_lock); 703 EINA_TRASH_CLEAN(&klass->iterators.trash, data)
704 free(data);
705
706 eina_lock_free(&klass->objects.trash_lock);
707 eina_lock_free(&klass->iterators.trash_lock);
704 708
705 free(klass); 709 free(klass);
706} 710}
@@ -893,7 +897,8 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...)
893 897
894 klass = calloc(1, _eo_class_sz + extn_sz + mro_sz + mixins_sz); 898 klass = calloc(1, _eo_class_sz + extn_sz + mro_sz + mixins_sz);
895 EINA_MAGIC_SET(klass, EO_CLASS_EINA_MAGIC); 899 EINA_MAGIC_SET(klass, EO_CLASS_EINA_MAGIC);
896 eina_lock_new(&klass->trash_lock); 900 eina_lock_new(&klass->objects.trash_lock);
901 eina_lock_new(&klass->iterators.trash_lock);
897 klass->parent = parent; 902 klass->parent = parent;
898 klass->desc = desc; 903 klass->desc = desc;
899 klass->extensions = (const _Eo_Class **) ((char *) klass + _eo_class_sz); 904 klass->extensions = (const _Eo_Class **) ((char *) klass + _eo_class_sz);
@@ -1077,6 +1082,96 @@ eo_parent_set(Eo *obj_id, const Eo *parent_id)
1077 return EINA_TRUE; 1082 return EINA_TRUE;
1078} 1083}
1079 1084
1085/* Children accessor */
1086typedef struct _Eo_Children_Iterator Eo_Children_Iterator;
1087struct _Eo_Children_Iterator
1088{
1089 Eina_Iterator iterator;
1090 Eina_List *current;
1091 _Eo *obj;
1092 Eo *obj_id;
1093
1094};
1095
1096static Eina_Bool
1097_eo_children_iterator_next(Eo_Children_Iterator *it, void **data)
1098{
1099 if (!it->current) return EINA_FALSE;
1100
1101 if (data) *data = eina_list_data_get(it->current);
1102 it->current = eina_list_next(it->current);
1103
1104 return EINA_TRUE;
1105}
1106
1107static Eo *
1108_eo_children_iterator_container(Eo_Children_Iterator *it)
1109{
1110 return it->obj_id;
1111}
1112
1113static void
1114_eo_children_iterator_free(Eo_Children_Iterator *it)
1115{
1116 _Eo_Class *klass;
1117 _Eo *obj;
1118
1119 klass = (_Eo_Class*) it->obj->klass;
1120 obj = it->obj;
1121
1122 eina_lock_take(&klass->iterators.trash_lock);
1123 if (klass->iterators.trash_count < 8)
1124 {
1125 klass->iterators.trash_count++;
1126 eina_trash_push(&klass->iterators.trash, it);
1127 }
1128 else
1129 {
1130 free(it);
1131 }
1132 eina_lock_release(&klass->iterators.trash_lock);
1133
1134 _eo_unref(obj);
1135}
1136
1137EAPI Eina_Iterator *
1138eo_childrens_iterator_new(Eo *obj_id)
1139{
1140 Eo_Children_Iterator *it;
1141 _Eo_Class *klass;
1142
1143 EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
1144
1145 if (!obj->children) return NULL;
1146
1147 klass = (_Eo_Class*) obj->klass;
1148
1149 eina_lock_take(&klass->iterators.trash_lock);
1150 it = eina_trash_pop(&klass->iterators.trash);
1151 if (it)
1152 {
1153 klass->iterators.trash_count--;
1154 memset(it, 0, sizeof (Eo_Children_Iterator));
1155 }
1156 else
1157 {
1158 it = calloc(1, sizeof (Eo_Children_Iterator));
1159 }
1160 eina_lock_release(&klass->iterators.trash_lock);
1161 if (!it) return NULL;
1162
1163 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1164 it->current = obj->children;
1165 it->obj = _eo_ref(obj);
1166 it->obj_id = obj_id;
1167
1168 it->iterator.next = FUNC_ITERATOR_NEXT(_eo_children_iterator_next);
1169 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eo_children_iterator_container);
1170 it->iterator.free = FUNC_ITERATOR_FREE(_eo_children_iterator_free);
1171
1172 return &it->iterator;
1173}
1174
1080EAPI Eo * 1175EAPI Eo *
1081eo_add_internal(const char *file, int line, const Eo_Class *klass_id, Eo *parent_id, ...) 1176eo_add_internal(const char *file, int line, const Eo_Class *klass_id, Eo *parent_id, ...)
1082{ 1177{
@@ -1096,18 +1191,18 @@ eo_add_internal(const char *file, int line, const Eo_Class *klass_id, Eo *parent
1096 return NULL; 1191 return NULL;
1097 } 1192 }
1098 1193
1099 eina_lock_take(&klass->trash_lock); 1194 eina_lock_take(&klass->objects.trash_lock);
1100 obj = eina_trash_pop(&klass->trash); 1195 obj = eina_trash_pop(&klass->objects.trash);
1101 if (obj) 1196 if (obj)
1102 { 1197 {
1103 memset(obj, 0, klass->obj_size); 1198 memset(obj, 0, klass->obj_size);
1104 klass->trash_count--; 1199 klass->objects.trash_count--;
1105 } 1200 }
1106 else 1201 else
1107 { 1202 {
1108 obj = calloc(1, klass->obj_size); 1203 obj = calloc(1, klass->obj_size);
1109 } 1204 }
1110 eina_lock_release(&klass->trash_lock); 1205 eina_lock_release(&klass->objects.trash_lock);
1111 1206
1112 obj->refcount++; 1207 obj->refcount++;
1113 obj->klass = klass; 1208 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
140 const _Eo_Class **mro; 140 const _Eo_Class **mro;
141 141
142 /* cached object for faster allocation */ 142 /* cached object for faster allocation */
143 Eina_Trash *trash; 143 struct {
144 Eina_Lock trash_lock; 144 Eina_Trash *trash;
145 unsigned int trash_count; 145 Eina_Lock trash_lock;
146 unsigned int trash_count;
147 } objects;
148
149 /* cached iterator for faster allocation cycle */
150 struct {
151 Eina_Trash *trash;
152 Eina_Lock trash_lock;
153 unsigned int trash_count;
154 } iterators;
146 155
147 unsigned int obj_size; /**< size of an object of this class */ 156 unsigned int obj_size; /**< size of an object of this class */
148 unsigned int chain_size; 157 unsigned int chain_size;
@@ -219,18 +228,17 @@ _eo_free(_Eo *obj)
219#endif 228#endif
220 _eo_id_release(obj->obj_id); 229 _eo_id_release(obj->obj_id);
221 230
222 eina_lock_take(&klass->trash_lock); 231 eina_lock_take(&klass->objects.trash_lock);
223 if (klass->trash_count <= 8) 232 if (klass->objects.trash_count <= 8)
224 { 233 {
225 eina_trash_push(&klass->trash, obj); 234 eina_trash_push(&klass->objects.trash, obj);
226 klass->trash_count++; 235 klass->objects.trash_count++;
227 eina_lock_release(&klass->trash_lock);
228 } 236 }
229 else 237 else
230 { 238 {
231 eina_lock_release(&klass->trash_lock);
232 free(obj); 239 free(obj);
233 } 240 }
241 eina_lock_release(&klass->objects.trash_lock);
234} 242}
235 243
236static inline _Eo * 244static inline _Eo *