Eo: Overhauled the mro-walking mechanism.

A lot faster now.

SVN revision: 70793
This commit is contained in:
Tom Hacohen 2012-05-06 12:03:13 +00:00
parent 8c5644d5f8
commit dba7e09641
1 changed files with 39 additions and 67 deletions

View File

@ -22,6 +22,12 @@ static void eo_constructor_error_unset(Eo *obj);
typedef struct _Eo_Callback_Description Eo_Callback_Description; typedef struct _Eo_Callback_Description Eo_Callback_Description;
typedef struct
{
Eo_Op op;
const Eo_Class **kls_itr;
} Eo_Kls_Itr;
#define EO_EINA_MAGIC 0xa186bc32 /* Nothing magical about this number. */ #define EO_EINA_MAGIC 0xa186bc32 /* Nothing magical about this number. */
#define EO_EINA_MAGIC_STR "Eo" #define EO_EINA_MAGIC_STR "Eo"
#define EO_CLASS_EINA_MAGIC 0xa186bb32 /* Nothing magical about this number. */ #define EO_CLASS_EINA_MAGIC 0xa186bb32 /* Nothing magical about this number. */
@ -59,7 +65,7 @@ struct _Eo {
Eina_Inlist *callbacks; Eina_Inlist *callbacks;
int walking_list; int walking_list;
Eina_Inlist *kls_itr; Eo_Kls_Itr mro_itr;
Eina_Bool delete:1; Eina_Bool delete:1;
Eina_Bool construct_error:1; Eina_Bool construct_error:1;
@ -250,80 +256,53 @@ _eo_op_id_name_get(Eo_Op op)
return (desc) ? desc->name : NULL; return (desc) ? desc->name : NULL;
} }
typedef struct static inline void
_eo_kls_itr_init(Eo *obj, Eo_Op op, Eo_Kls_Itr *prev_state)
{ {
EINA_INLIST; prev_state->op = obj->mro_itr.op;
Eo_Op op; prev_state->kls_itr = obj->mro_itr.kls_itr;
const Eo_Class **kls_itr;
} Eo_Kls_Itr_Node;
static inline Eina_Bool /* If we are in a constructor/destructor or we changed an op - init. */
_eo_kls_itr_init(Eo *obj, Eo_Op op) if ((op == EO_NOOP) || (obj->mro_itr.op != op))
{
if (obj->kls_itr)
{ {
Eo_Kls_Itr_Node *node = obj->mro_itr.op = op;
EINA_INLIST_CONTAINER_GET(obj->kls_itr, Eo_Kls_Itr_Node); obj->mro_itr.kls_itr = obj->klass->mro;
if (node->op == op)
{
return EINA_FALSE;
}
}
{
Eo_Kls_Itr_Node *node = calloc(1, sizeof(*node));
node->op = op;
node->kls_itr = obj->klass->mro;
obj->kls_itr = eina_inlist_prepend(obj->kls_itr,
EINA_INLIST_GET(node));
return EINA_TRUE;
} }
} }
static inline void static inline void
_eo_kls_itr_end(Eo *obj, Eo_Op op) _eo_kls_itr_end(Eo *obj, Eo_Kls_Itr *prev_state)
{ {
Eo_Kls_Itr_Node *node = if (obj->mro_itr.op != prev_state->op)
EINA_INLIST_CONTAINER_GET(obj->kls_itr, Eo_Kls_Itr_Node); {
obj->mro_itr.op = prev_state->op;
if (node->op != op) obj->mro_itr.kls_itr = prev_state->kls_itr;
return; }
obj->kls_itr = eina_inlist_remove(obj->kls_itr, obj->kls_itr);
free(node);
} }
static inline const Eo_Class * static inline const Eo_Class *
_eo_kls_itr_get(Eo *obj) _eo_kls_itr_get(Eo *obj)
{ {
Eo_Kls_Itr_Node *node = return (obj->mro_itr.kls_itr) ? *(obj->mro_itr.kls_itr) : NULL;
EINA_INLIST_CONTAINER_GET(obj->kls_itr, Eo_Kls_Itr_Node);
return (node) ? *(node->kls_itr) : NULL;
} }
static inline const Eo_Class * static inline const Eo_Class *
_eo_kls_itr_next(Eo *obj, Eo_Op op) _eo_kls_itr_next(Eo *obj, Eo_Op op)
{ {
Eo_Kls_Itr_Node *node = if (obj->mro_itr.op != op)
EINA_INLIST_CONTAINER_GET(obj->kls_itr, Eo_Kls_Itr_Node);
if (!node || (node->op != op))
{ {
Eo_Op node_op = (node) ? node->op : EO_NOOP; Eo_Op node_op = obj->mro_itr.op;
ERR("Called with op %d ('%s') while expecting: %d ('%s'). This probaly means you called eo_*_super functions from a wrong place.", ERR("Called with op %d ('%s') while expecting: %d ('%s'). This probaly means you called eo_*_super functions from a wrong place.",
op, _eo_op_id_name_get(op), op, _eo_op_id_name_get(op),
node_op, _eo_op_id_name_get(node_op)); node_op, _eo_op_id_name_get(node_op));
return NULL; return NULL;
} }
const Eo_Class **kls_itr = node->kls_itr; const Eo_Class **kls_itr = obj->mro_itr.kls_itr;
if (*kls_itr) if (*kls_itr)
{ {
kls_itr++; kls_itr++;
node->kls_itr = kls_itr; obj->mro_itr.kls_itr = kls_itr;
return *kls_itr; return *kls_itr;
} }
else else
@ -335,9 +314,7 @@ _eo_kls_itr_next(Eo *obj, Eo_Op op)
static inline Eina_Bool static inline Eina_Bool
_eo_kls_itr_reached_end(const Eo *obj) _eo_kls_itr_reached_end(const Eo *obj)
{ {
Eo_Kls_Itr_Node *node = const Eo_Class **kls_itr = obj->mro_itr.kls_itr;
EINA_INLIST_CONTAINER_GET(obj->kls_itr, Eo_Kls_Itr_Node);
const Eo_Class **kls_itr = node->kls_itr;
return !(*kls_itr && *(kls_itr + 1)); return !(*kls_itr && *(kls_itr + 1));
} }
@ -346,7 +323,6 @@ _eo_op_internal(Eo *obj, Eina_Bool constant, Eo_Op op, va_list *p_list)
{ {
const Eo_Class *klass; const Eo_Class *klass;
Eina_Bool ret = EINA_FALSE; Eina_Bool ret = EINA_FALSE;
Eina_Bool _itr_init;
const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op); const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
@ -357,7 +333,8 @@ _eo_op_internal(Eo *obj, Eina_Bool constant, Eo_Op op, va_list *p_list)
return EINA_FALSE; return EINA_FALSE;
} }
_itr_init = _eo_kls_itr_init(obj, op); Eo_Kls_Itr prev_state;
_eo_kls_itr_init(obj, op, &prev_state);
klass = _eo_kls_itr_get(obj); klass = _eo_kls_itr_get(obj);
while (klass) while (klass)
{ {
@ -388,8 +365,7 @@ _eo_op_internal(Eo *obj, Eina_Bool constant, Eo_Op op, va_list *p_list)
} }
end: end:
_eo_kls_itr_end(obj, &prev_state);
if (_itr_init) _eo_kls_itr_end(obj, op);
return ret; return ret;
} }
@ -923,7 +899,9 @@ eo_add(const Eo_Class *klass, Eo *parent)
obj->refcount++; obj->refcount++;
_eo_kls_itr_init(obj, EO_NOOP); Eo_Kls_Itr prev_state;
_eo_kls_itr_init(obj, EO_NOOP, &prev_state);
eo_constructor_error_unset(obj); eo_constructor_error_unset(obj);
EINA_MAGIC_SET(obj, EO_EINA_MAGIC); EINA_MAGIC_SET(obj, EO_EINA_MAGIC);
@ -941,12 +919,13 @@ eo_add(const Eo_Class *klass, Eo *parent)
ERR("Type '%s' - Not all of the object constructors have been executed.", klass->desc->name); ERR("Type '%s' - Not all of the object constructors have been executed.", klass->desc->name);
goto fail; goto fail;
} }
_eo_kls_itr_end(obj, EO_NOOP); _eo_kls_itr_end(obj, &prev_state);
eo_unref(obj); eo_unref(obj);
return obj; return obj;
fail: fail:
_eo_kls_itr_end(obj, &prev_state);
/* Unref twice, once for the ref above, and once for the basic object ref. */ /* Unref twice, once for the ref above, and once for the basic object ref. */
eo_unref(obj); eo_unref(obj);
eo_unref(obj); eo_unref(obj);
@ -1036,7 +1015,9 @@ _eo_del_internal(Eo *obj)
obj->refcount--; obj->refcount--;
const Eo_Class *klass = eo_class_get(obj); const Eo_Class *klass = eo_class_get(obj);
_eo_kls_itr_init(obj, EO_NOOP); Eo_Kls_Itr prev_state;
_eo_kls_itr_init(obj, EO_NOOP, &prev_state);
eo_constructor_error_unset(obj); eo_constructor_error_unset(obj);
_eo_destructor(obj, klass); _eo_destructor(obj, klass);
if (eo_constructor_error_get(obj)) if (eo_constructor_error_get(obj))
@ -1048,18 +1029,9 @@ _eo_del_internal(Eo *obj)
{ {
ERR("Type '%s' - Not all of the object destructors have been executed.", klass->desc->name); ERR("Type '%s' - Not all of the object destructors have been executed.", klass->desc->name);
} }
_eo_kls_itr_end(obj, EO_NOOP); _eo_kls_itr_end(obj, &prev_state);
/*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */ /*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */
/* If for some reason it's not empty, clear it. */
while (obj->kls_itr)
{
WRN("Kls_Itr is not empty, possibly a bug, please report. - An error will be reported for each kls_itr in the stack.");
Eina_Inlist *nitr = obj->kls_itr->next;
free(EINA_INLIST_CONTAINER_GET(obj->kls_itr, Eo_Kls_Itr_Node));
obj->kls_itr = nitr;
}
Eina_List *itr, *itr_n; Eina_List *itr, *itr_n;
Eo *emb_obj; Eo *emb_obj;
EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj) EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)