Eo: Improved the data structure used for func fetching.

Made it 2 levels instead of 1 and made it a lot smaller.

SVN revision: 70797
This commit is contained in:
Tom Hacohen 2012-05-06 12:03:23 +00:00
parent 3754fd077c
commit 019ba402d0
1 changed files with 38 additions and 48 deletions

View File

@ -5,7 +5,7 @@
#include "config.h"
typedef int Eo_Class_Id;
typedef size_t Eo_Class_Id;
/* Used inside the class_get functions of classes, see #EO_DEFINE_CLASS */
EAPI Eina_Lock _eo_class_creation_lock;
@ -75,25 +75,24 @@ struct _Eo {
/* Start of Dich */
/* Dich search, split to 0xff 0xff 0xffff */
#define DICH_CHAIN1_MASK (0xff)
#define DICH_CHAIN2_MASK (0xff)
#define DICH_CHAIN1_MASK (0xffff)
#define DICH_CHAIN_LAST_MASK (0xffff)
#define DICH_CHAIN1_SIZE (DICH_CHAIN1_MASK + 1)
#define DICH_CHAIN2_SIZE (DICH_CHAIN2_MASK + 1)
#define DICH_CHAIN_LAST_SIZE (DICH_CHAIN_LAST_MASK + 1)
#define DICH_CHAIN1(x) (((x) >> 24) & DICH_CHAIN1_MASK)
#define DICH_CHAIN2(x) (((x) >> 16) & DICH_CHAIN2_MASK)
#define DICH_CHAIN1(x) (((x) >> 16) & DICH_CHAIN1_MASK)
#define DICH_CHAIN_LAST(x) ((x) & DICH_CHAIN_LAST_MASK)
#define OP_CLASS_OFFSET 16
#define OP_CLASS_OFFSET_GET(x) (((x) >> OP_CLASS_OFFSET) & 0xffff)
#define OP_CLASS_GET(op) ({ \
Eo_Class_Id tmp = OP_CLASS_OFFSET_GET(op); \
(Eo_Class *) ((tmp <= _eo_classes_last_id) && (tmp > 0)) ? \
(_eo_classes[tmp - 1]) : NULL; \
ID_CLASS_GET(tmp); \
})
#define OP_SUB_ID_GET(op) ((op) & 0xffff)
#define ID_CLASS_GET(id) ({ \
(Eo_Class *) ((id <= _eo_classes_last_id) && (id > 0)) ? \
(_eo_classes[id - 1]) : NULL; \
})
#define EO_ALIGN_SIZE(size) \
((size) + (sizeof(void *) - ((size) % sizeof(void *))))
@ -109,14 +108,9 @@ typedef struct
eo_op_func_type func;
} op_type_funcs;
typedef struct
{
op_type_funcs *funcs;
} Dich_Chain2;
struct _Dich_Chain1
{
Dich_Chain2 *chain;
op_type_funcs *funcs;
};
typedef struct
@ -137,7 +131,7 @@ struct _Eo_Class
Eo_Class_Id class_id;
const Eo_Class *parent;
const Eo_Class_Description *desc;
Dich_Chain1 chain[DICH_CHAIN1_SIZE];
Dich_Chain1 *chain; /**< The size is class_id */
Eina_Inlist *extensions;
Eo_Extension_Data_Offset *extn_data_off;
@ -153,19 +147,20 @@ struct _Eo_Class
static inline eo_op_func_type
dich_func_get(const Eo_Class *klass, Eo_Op op)
{
const Dich_Chain1 *chain1 = &klass->chain[DICH_CHAIN1(op)];
if (!chain1) return NULL;
if (!chain1->chain) return NULL;
Dich_Chain2 *chain2 = &chain1->chain[DICH_CHAIN2(op)];
if (!chain2) return NULL;
if (!chain2->funcs) return NULL;
if (!klass->chain) return NULL;
size_t idx1 = DICH_CHAIN1(op) - 1;
if (idx1 >= klass->class_id) return NULL;
const Dich_Chain1 *chain1 = &klass->chain[idx1];
if (!chain1->funcs) return NULL;
size_t idxl = DICH_CHAIN_LAST(op);
/* num_ops is calculated from the class. */
const Eo_Class *op_klass = OP_CLASS_GET(op);
if (!op_klass || (DICH_CHAIN_LAST(op) >= op_klass->desc->ops.count))
const Eo_Class *op_klass = ID_CLASS_GET(idx1 + 1);
if (!op_klass || (idxl >= op_klass->desc->ops.count))
return NULL;
return chain2->funcs[DICH_CHAIN_LAST(op)].func;
return chain1->funcs[idxl].func;
}
static inline void
@ -192,42 +187,37 @@ dich_func_set(Eo_Class *klass, Eo_Op op, eo_op_func_type func)
return;
}
Dich_Chain1 *chain1 = &klass->chain[DICH_CHAIN1(op)];
if (!chain1->chain)
if (!klass->chain)
{
chain1->chain = calloc(DICH_CHAIN2_SIZE, sizeof(*(chain1->chain)));
klass->chain = calloc(klass->class_id, sizeof(*klass->chain));
}
Dich_Chain2 *chain2 = &chain1->chain[DICH_CHAIN2(op)];
if (!chain2->funcs)
size_t idx1 = DICH_CHAIN1(op) - 1;
Dich_Chain1 *chain1 = &klass->chain[idx1];
if (!chain1->funcs)
{
chain2->funcs = calloc(num_ops, sizeof(*(chain2->funcs)));
chain1->funcs = calloc(num_ops, sizeof(*(chain1->funcs)));
}
chain2->funcs[DICH_CHAIN_LAST(op)].func = func;
chain1->funcs[DICH_CHAIN_LAST(op)].func = func;
}
static inline void
dich_func_clean_all(Eo_Class *klass)
{
int i;
size_t i;
Dich_Chain1 *chain1 = klass->chain;
for (i = 0 ; i < DICH_CHAIN1_SIZE ; i++, chain1++)
if (!chain1)
return;
for (i = 0 ; i < klass->class_id ; i++, chain1++)
{
int j;
Dich_Chain2 *chain2 = chain1->chain;
if (!chain2)
continue;
for (j = 0 ; j < DICH_CHAIN2_SIZE ; j++, chain2++)
{
free(chain2->funcs);
}
free(chain1->chain);
chain1->chain = NULL;
if (chain1->funcs)
free(chain1->funcs);
}
free(klass->chain);
klass->chain = NULL;
}
/* END OF DICH */
@ -1261,7 +1251,7 @@ eo_init(void)
EAPI Eina_Bool
eo_shutdown(void)
{
int i;
size_t i;
Eo_Class **cls_itr = _eo_classes;
if (--_eo_init_count > 0)