summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Hacohen <tom@stosb.com>2016-05-18 18:12:39 +0100
committerTom Hacohen <tom@stosb.com>2016-05-20 10:25:00 +0100
commite1efe2e651ac1c475be27729f212445c8cb3486a (patch)
treec8161fd53d8461e75f9475fca97afd71660cb706
parentb5511464a1d712db9b385b03bb137174d58efb1a (diff)
Eo: Reorganise the vtable in classes and add pointer from objects.
This is the first step towards supporting eo_override(). More details about eo_override() to follow.
-rw-r--r--src/lib/eo/eo.c57
-rw-r--r--src/lib/eo/eo_private.h15
-rw-r--r--src/tests/eo/suite/eo_test_class_errors.c2
3 files changed, 41 insertions, 33 deletions
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index e11ef13ec4..48669a7d1e 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -58,7 +58,7 @@ static inline void _eo_data_xunref_internal(_Eo_Object *obj, void *data, const _
58 }) 58 })
59 59
60static inline void 60static inline void
61_dich_chain_alloc(Dich_Chain1 *chain1) 61_vtable_chain_alloc(Dich_Chain1 *chain1)
62{ 62{
63 if (!chain1->funcs) 63 if (!chain1->funcs)
64 { 64 {
@@ -67,18 +67,18 @@ _dich_chain_alloc(Dich_Chain1 *chain1)
67} 67}
68 68
69static inline void 69static inline void
70_dich_copy_all(_Eo_Class *dst, const _Eo_Class *src) 70_vtable_copy_all(Eo_Vtable *dst, const Eo_Vtable *src)
71{ 71{
72 Eo_Op i; 72 Eo_Op i;
73 const Dich_Chain1 *sc1 = src->chain; 73 const Dich_Chain1 *sc1 = src->chain;
74 Dich_Chain1 *dc1 = dst->chain; 74 Dich_Chain1 *dc1 = dst->chain;
75 for (i = 0 ; i < src->chain_size ; i++, sc1++, dc1++) 75 for (i = 0 ; i < src->size ; i++, sc1++, dc1++)
76 { 76 {
77 if (sc1->funcs) 77 if (sc1->funcs)
78 { 78 {
79 size_t j; 79 size_t j;
80 80
81 _dich_chain_alloc(dc1); 81 _vtable_chain_alloc(dc1);
82 82
83 const op_type_funcs *sf = sc1->funcs; 83 const op_type_funcs *sf = sc1->funcs;
84 op_type_funcs *df = dc1->funcs; 84 op_type_funcs *df = dc1->funcs;
@@ -94,12 +94,12 @@ _dich_copy_all(_Eo_Class *dst, const _Eo_Class *src)
94} 94}
95 95
96static inline const op_type_funcs * 96static inline const op_type_funcs *
97_dich_func_get(const _Eo_Class *klass, Eo_Op op) 97_vtable_func_get(const Eo_Vtable *vtable, Eo_Op op)
98{ 98{
99 size_t idx1 = DICH_CHAIN1(op); 99 size_t idx1 = DICH_CHAIN1(op);
100 if (EINA_UNLIKELY(idx1 >= klass->chain_size)) 100 if (EINA_UNLIKELY(idx1 >= vtable->size))
101 return NULL; 101 return NULL;
102 Dich_Chain1 *chain1 = &klass->chain[idx1]; 102 Dich_Chain1 *chain1 = &vtable->chain[idx1];
103 if (EINA_UNLIKELY(!chain1->funcs)) 103 if (EINA_UNLIKELY(!chain1->funcs))
104 return NULL; 104 return NULL;
105 return &chain1->funcs[DICH_CHAIN_LAST(op)]; 105 return &chain1->funcs[DICH_CHAIN_LAST(op)];
@@ -130,12 +130,12 @@ _eo_op_class_get(Eo_Op op)
130} 130}
131 131
132static inline Eina_Bool 132static inline Eina_Bool
133_dich_func_set(_Eo_Class *klass, Eo_Op op, eo_op_func_type func) 133_vtable_func_set(_Eo_Class *klass, Eo_Op op, eo_op_func_type func)
134{ 134{
135 op_type_funcs *fsrc; 135 op_type_funcs *fsrc;
136 size_t idx1 = DICH_CHAIN1(op); 136 size_t idx1 = DICH_CHAIN1(op);
137 Dich_Chain1 *chain1 = &klass->chain[idx1]; 137 Dich_Chain1 *chain1 = &klass->vtable.chain[idx1];
138 _dich_chain_alloc(chain1); 138 _vtable_chain_alloc(chain1);
139 fsrc = &chain1->funcs[DICH_CHAIN_LAST(op)]; 139 fsrc = &chain1->funcs[DICH_CHAIN_LAST(op)];
140 if (fsrc->src == klass) 140 if (fsrc->src == klass)
141 { 141 {
@@ -152,18 +152,18 @@ _dich_func_set(_Eo_Class *klass, Eo_Op op, eo_op_func_type func)
152} 152}
153 153
154static inline void 154static inline void
155_dich_func_clean_all(_Eo_Class *klass) 155_vtable_func_clean_all(_Eo_Class *klass)
156{ 156{
157 size_t i; 157 size_t i;
158 Dich_Chain1 *chain1 = klass->chain; 158 Dich_Chain1 *chain1 = klass->vtable.chain;
159 159
160 for (i = 0 ; i < klass->chain_size ; i++, chain1++) 160 for (i = 0 ; i < klass->vtable.size ; i++, chain1++)
161 { 161 {
162 if (chain1->funcs) 162 if (chain1->funcs)
163 free(chain1->funcs); 163 free(chain1->funcs);
164 } 164 }
165 free(klass->chain); 165 free(klass->vtable.chain);
166 klass->chain = NULL; 166 klass->vtable.chain = NULL;
167} 167}
168 168
169/* END OF DICH */ 169/* END OF DICH */
@@ -236,7 +236,7 @@ _eo_kls_itr_next(const _Eo_Class *orig_kls, const _Eo_Class *cur_klass, Eo_Op op
236 kls_itr++; 236 kls_itr++;
237 while (*kls_itr) 237 while (*kls_itr)
238 { 238 {
239 const op_type_funcs *fsrc = _dich_func_get(*kls_itr, op); 239 const op_type_funcs *fsrc = _vtable_func_get(&(*kls_itr)->vtable, op);
240 if (!fsrc || !fsrc->func) 240 if (!fsrc || !fsrc->func)
241 { 241 {
242 kls_itr++; 242 kls_itr++;
@@ -358,7 +358,7 @@ _eo_call_resolve(Eo *eo_id, const char *func_name, Eo_Op_Call_Data *call, Eo_Cal
358 } 358 }
359#endif 359#endif
360 360
361 func = _dich_func_get(klass, cache->op); 361 func = _vtable_func_get(&klass->vtable, cache->op);
362 362
363 if (!func) 363 if (!func)
364 goto end; 364 goto end;
@@ -414,7 +414,7 @@ end:
414 if (!emb_obj) 414 if (!emb_obj)
415 continue; 415 continue;
416 416
417 func = _dich_func_get(emb_obj->klass, cache->op); 417 func = _vtable_func_get(emb_obj->vtable, cache->op);
418 if (func == NULL) 418 if (func == NULL)
419 continue; 419 continue;
420 420
@@ -607,7 +607,7 @@ _eo_class_funcs_set(_Eo_Class *klass)
607 607
608 DBG("%p->%p '%s'", op_desc->api_func, op_desc->func, _eo_op_desc_name_get(op_desc)); 608 DBG("%p->%p '%s'", op_desc->api_func, op_desc->func, _eo_op_desc_name_get(op_desc));
609 609
610 if (!_dich_func_set(klass, op, op_desc->func)) 610 if (!_vtable_func_set(klass, op, op_desc->func))
611 return EINA_FALSE; 611 return EINA_FALSE;
612 612
613 last_api_func = op_desc->api_func; 613 last_api_func = op_desc->api_func;
@@ -655,6 +655,7 @@ _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo
655 655
656 obj->refcount++; 656 obj->refcount++;
657 obj->klass = klass; 657 obj->klass = klass;
658 obj->vtable = &klass->vtable;
658 659
659#ifndef HAVE_EO_ID 660#ifndef HAVE_EO_ID
660 EINA_MAGIC_SET((Eo_Header *) obj, EO_EINA_MAGIC); 661 EINA_MAGIC_SET((Eo_Header *) obj, EO_EINA_MAGIC);
@@ -806,8 +807,8 @@ _eo_class_base_op_init(_Eo_Class *klass)
806 807
807 _eo_ops_last_id += desc->ops.count + 1; 808 _eo_ops_last_id += desc->ops.count + 1;
808 809
809 klass->chain_size = DICH_CHAIN1(_eo_ops_last_id) + 1; 810 klass->vtable.size = DICH_CHAIN1(_eo_ops_last_id) + 1;
810 klass->chain = calloc(klass->chain_size, sizeof(*klass->chain)); 811 klass->vtable.chain = calloc(klass->vtable.size, sizeof(*klass->vtable.chain));
811} 812}
812 813
813#ifdef EO_DEBUG 814#ifdef EO_DEBUG
@@ -950,7 +951,7 @@ eo_class_free(_Eo_Class *klass)
950 if (klass->desc->class_destructor) 951 if (klass->desc->class_destructor)
951 klass->desc->class_destructor(_eo_class_id_get(klass)); 952 klass->desc->class_destructor(_eo_class_id_get(klass));
952 953
953 _dich_func_clean_all(klass); 954 _vtable_func_clean_all(klass);
954 } 955 }
955 956
956 EINA_TRASH_CLEAN(&klass->objects.trash, data) 957 EINA_TRASH_CLEAN(&klass->objects.trash, data)
@@ -1245,7 +1246,7 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...)
1245 /* Skip ourselves. */ 1246 /* Skip ourselves. */
1246 for ( mro_itr-- ; mro_itr > klass->mro ; mro_itr--) 1247 for ( mro_itr-- ; mro_itr > klass->mro ; mro_itr--)
1247 { 1248 {
1248 _dich_copy_all(klass, *mro_itr); 1249 _vtable_copy_all(&klass->vtable, &(*mro_itr)->vtable);
1249 } 1250 }
1250 } 1251 }
1251 1252
@@ -1257,16 +1258,16 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...)
1257 { 1258 {
1258 const _Eo_Class *extn = *extn_itr; 1259 const _Eo_Class *extn = *extn_itr;
1259 /* Set it in the dich. */ 1260 /* Set it in the dich. */
1260 _dich_func_set(klass, extn->base_id + 1261 _vtable_func_set(klass, extn->base_id +
1261 extn->desc->ops.count, _eo_class_isa_func); 1262 extn->desc->ops.count, _eo_class_isa_func);
1262 } 1263 }
1263 1264
1264 _dich_func_set(klass, klass->base_id + klass->desc->ops.count, 1265 _vtable_func_set(klass, klass->base_id + klass->desc->ops.count,
1265 _eo_class_isa_func); 1266 _eo_class_isa_func);
1266 1267
1267 if (klass->parent) 1268 if (klass->parent)
1268 { 1269 {
1269 _dich_func_set(klass, 1270 _vtable_func_set(klass,
1270 klass->parent->base_id + klass->parent->desc->ops.count, 1271 klass->parent->base_id + klass->parent->desc->ops.count,
1271 _eo_class_isa_func); 1272 _eo_class_isa_func);
1272 } 1273 }
@@ -1276,7 +1277,7 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...)
1276 { 1277 {
1277 eina_spinlock_free(&klass->objects.trash_lock); 1278 eina_spinlock_free(&klass->objects.trash_lock);
1278 eina_spinlock_free(&klass->iterators.trash_lock); 1279 eina_spinlock_free(&klass->iterators.trash_lock);
1279 _dich_func_clean_all(klass); 1280 _vtable_func_clean_all(klass);
1280 free(klass); 1281 free(klass);
1281 return NULL; 1282 return NULL;
1282 } 1283 }
@@ -1305,7 +1306,7 @@ eo_isa(const Eo *eo_id, const Eo_Class *klass_id)
1305{ 1306{
1306 EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, EINA_FALSE); 1307 EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, EINA_FALSE);
1307 EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, EINA_FALSE); 1308 EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, EINA_FALSE);
1308 const op_type_funcs *func = _dich_func_get(obj->klass, 1309 const op_type_funcs *func = _vtable_func_get(obj->vtable,
1309 klass->base_id + klass->desc->ops.count); 1310 klass->base_id + klass->desc->ops.count);
1310 1311
1311 /* Currently implemented by reusing the LAST op id. Just marking it with 1312 /* Currently implemented by reusing the LAST op id. Just marking it with
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index a05bdf62a9..62f9b73c4c 100644
--- a/src/lib/eo/eo_private.h
+++ b/src/lib/eo/eo_private.h
@@ -77,6 +77,14 @@ static inline void _eo_free_ids_tables(void);
77 77
78void _eo_condtor_done(Eo *obj); 78void _eo_condtor_done(Eo *obj);
79 79
80typedef struct _Dich_Chain1 Dich_Chain1;
81
82typedef struct _Eo_Vtable
83{
84 Dich_Chain1 *chain;
85 unsigned int size;
86} Eo_Vtable;
87
80struct _Eo_Header 88struct _Eo_Header
81{ 89{
82#ifndef HAVE_EO_ID 90#ifndef HAVE_EO_ID
@@ -95,6 +103,8 @@ struct _Eo_Object
95 Eina_Inlist *data_xrefs; 103 Eina_Inlist *data_xrefs;
96#endif 104#endif
97 105
106 Eo_Vtable *vtable;
107
98 Eina_List *composite_objects; 108 Eina_List *composite_objects;
99 Eo_Del_Intercept del_intercept; 109 Eo_Del_Intercept del_intercept;
100 110
@@ -114,8 +124,6 @@ struct _Eo_Object
114/* FIXME: Change the type to something generic that makes sense for eo */ 124/* FIXME: Change the type to something generic that makes sense for eo */
115typedef void (*eo_op_func_type)(Eo *, void *class_data, va_list *list); 125typedef void (*eo_op_func_type)(Eo *, void *class_data, va_list *list);
116 126
117typedef struct _Dich_Chain1 Dich_Chain1;
118
119typedef struct 127typedef struct
120{ 128{
121 eo_op_func_type func; 129 eo_op_func_type func;
@@ -139,7 +147,7 @@ struct _Eo_Class
139 147
140 const _Eo_Class *parent; 148 const _Eo_Class *parent;
141 const Eo_Class_Description *desc; 149 const Eo_Class_Description *desc;
142 Dich_Chain1 *chain; /**< The size is chain size */ 150 Eo_Vtable vtable;
143 151
144 const _Eo_Class **extensions; 152 const _Eo_Class **extensions;
145 153
@@ -162,7 +170,6 @@ struct _Eo_Class
162 } iterators; 170 } iterators;
163 171
164 unsigned int obj_size; /**< size of an object of this class */ 172 unsigned int obj_size; /**< size of an object of this class */
165 unsigned int chain_size;
166 unsigned int base_id; 173 unsigned int base_id;
167 unsigned int data_offset; /* < Offset of the data within object data. */ 174 unsigned int data_offset; /* < Offset of the data within object data. */
168 175
diff --git a/src/tests/eo/suite/eo_test_class_errors.c b/src/tests/eo/suite/eo_test_class_errors.c
index 6fc6e3be52..8155c5ded6 100644
--- a/src/tests/eo/suite/eo_test_class_errors.c
+++ b/src/tests/eo/suite/eo_test_class_errors.c
@@ -329,7 +329,7 @@ START_TEST(eo_dich_func_override)
329 NULL 329 NULL
330 }; 330 };
331 331
332 TEST_EO_ERROR("_dich_func_set", "Class '%s': Overriding func %p for op %d (%s) with %p."); 332 TEST_EO_ERROR("_vtable_func_set", "Class '%s': Overriding func %p for op %d (%s) with %p.");
333 klass = eo_class_new(&class_desc, SIMPLE_CLASS, NULL); 333 klass = eo_class_new(&class_desc, SIMPLE_CLASS, NULL);
334 fail_if(klass); 334 fail_if(klass);
335 fail_unless(ctx.did); 335 fail_unless(ctx.did);