forked from enlightenment/efl
eo: 30% speed improvement in message propagation.
This commit is contained in:
parent
383592b444
commit
7849c5de32
199
src/lib/eo/eo.c
199
src/lib/eo/eo.c
|
@ -16,15 +16,6 @@
|
|||
EAPI Eina_Lock _eo_class_creation_lock;
|
||||
int _eo_log_dom = -1;
|
||||
|
||||
/**
|
||||
* @typedef Eo_Class_Id
|
||||
* An Id of a class.
|
||||
* @ingroup Eo_Class
|
||||
*/
|
||||
typedef uintptr_t Eo_Class_Id;
|
||||
|
||||
typedef struct _Eo_Class _Eo_Class;
|
||||
|
||||
static _Eo_Class **_eo_classes;
|
||||
static Eo_Class_Id _eo_classes_last_id;
|
||||
static Eina_Bool _eo_init_count = 0;
|
||||
|
@ -37,38 +28,9 @@ static void _eo_condtor_reset(_Eo *obj);
|
|||
static inline void *_eo_data_scope_get(const _Eo *obj, const _Eo_Class *klass);
|
||||
static inline void *_eo_data_xref_internal(const char *file, int line, _Eo *obj, const _Eo_Class *klass, const _Eo *ref_obj);
|
||||
static inline void _eo_data_xunref_internal(_Eo *obj, void *data, const _Eo *ref_obj);
|
||||
static inline _Eo *_eo_ref(_Eo *obj);
|
||||
static inline void _eo_unref(_Eo *obj);
|
||||
static const _Eo_Class *_eo_op_class_get(Eo_Op op);
|
||||
static const Eo_Op_Description *_eo_op_id_desc_get(Eo_Op op);
|
||||
|
||||
struct _Eo_Internal {
|
||||
#ifndef HAVE_EO_ID
|
||||
EINA_MAGIC
|
||||
#endif
|
||||
Eo *parent;
|
||||
Eina_List *children;
|
||||
const _Eo_Class *klass;
|
||||
#ifdef EO_DEBUG
|
||||
Eina_Inlist *xrefs;
|
||||
Eina_Inlist *data_xrefs;
|
||||
#endif
|
||||
|
||||
Eina_List *composite_objects;
|
||||
|
||||
Eo_Id obj_id;
|
||||
|
||||
int refcount;
|
||||
int datarefcount;
|
||||
|
||||
Eina_Bool do_error:1;
|
||||
Eina_Bool condtor_done:1;
|
||||
|
||||
Eina_Bool composite:1;
|
||||
Eina_Bool del:1;
|
||||
Eina_Bool manual_free:1;
|
||||
};
|
||||
|
||||
/* Start of Dich */
|
||||
|
||||
/* How we search and store the implementations in classes. */
|
||||
|
@ -86,50 +48,6 @@ struct _Eo_Internal {
|
|||
|
||||
#define EO_ALIGN_SIZE(size) eina_mempool_alignof(size)
|
||||
|
||||
typedef struct _Dich_Chain1 Dich_Chain1;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
eo_op_func_type func;
|
||||
const _Eo_Class *src;
|
||||
} op_type_funcs;
|
||||
|
||||
struct _Dich_Chain1
|
||||
{
|
||||
op_type_funcs *funcs;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const _Eo_Class *klass;
|
||||
size_t offset;
|
||||
} Eo_Extension_Data_Offset;
|
||||
|
||||
struct _Eo_Class
|
||||
{
|
||||
EINA_MAGIC
|
||||
Eo_Class_Id class_id;
|
||||
const _Eo_Class *parent;
|
||||
const Eo_Class_Description *desc;
|
||||
Dich_Chain1 *chain; /**< The size is chain size */
|
||||
|
||||
const _Eo_Class **extensions;
|
||||
|
||||
Eo_Extension_Data_Offset *extn_data_off;
|
||||
|
||||
const _Eo_Class **mro;
|
||||
|
||||
unsigned int obj_size; /**< size of an object of this class */
|
||||
unsigned int chain_size;
|
||||
unsigned int base_id;
|
||||
unsigned int data_offset; /* < Offset of the data within object data. */
|
||||
|
||||
Eina_Bool constructed : 1;
|
||||
/* [extensions*] + NULL */
|
||||
/* [mro*] + NULL */
|
||||
/* [extensions data offset] + NULL */
|
||||
};
|
||||
|
||||
static inline void
|
||||
_dich_chain_alloc(Dich_Chain1 *chain1)
|
||||
{
|
||||
|
@ -1275,13 +1193,6 @@ eo_xunref(Eo *obj_id, const Eo *ref_obj_id)
|
|||
_eo_unref(obj);
|
||||
}
|
||||
|
||||
static inline _Eo *
|
||||
_eo_ref(_Eo *obj)
|
||||
{
|
||||
obj->refcount++;
|
||||
return obj;
|
||||
}
|
||||
|
||||
EAPI Eo *
|
||||
eo_ref(const Eo *obj_id)
|
||||
{
|
||||
|
@ -1291,110 +1202,6 @@ eo_ref(const Eo *obj_id)
|
|||
return (Eo *)obj_id;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eo_del_internal(const char *file, int line, _Eo *obj)
|
||||
{
|
||||
Eina_Bool do_err;
|
||||
/* We need that for the event callbacks that may ref/unref. */
|
||||
obj->refcount++;
|
||||
|
||||
eo_do((Eo *) obj->obj_id, eo_event_callback_call(EO_EV_DEL, NULL, NULL));
|
||||
|
||||
const _Eo_Class *klass = obj->klass;
|
||||
|
||||
_eo_condtor_reset(obj);
|
||||
|
||||
do_err = eo_do((Eo *)obj->obj_id, eo_destructor());
|
||||
if (EINA_UNLIKELY(!do_err))
|
||||
{
|
||||
ERR("in %s:%d: Object of class '%s' - One of the object destructors have failed.",
|
||||
file, line, klass->desc->name);
|
||||
}
|
||||
|
||||
if (!obj->condtor_done)
|
||||
{
|
||||
ERR("in %s:%d: Object of class '%s' - Not all of the object destructors have been executed.",
|
||||
file, line, klass->desc->name);
|
||||
}
|
||||
/*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */
|
||||
|
||||
{
|
||||
Eina_List *itr, *itr_n;
|
||||
Eo *emb_obj;
|
||||
EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)
|
||||
{
|
||||
eo_composite_detach(emb_obj, (Eo *)obj->obj_id);
|
||||
}
|
||||
}
|
||||
|
||||
while (obj->children)
|
||||
{
|
||||
eo_parent_set(eina_list_data_get(obj->children), NULL); // ZZZ
|
||||
}
|
||||
|
||||
obj->del = EINA_TRUE;
|
||||
obj->refcount--;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eo_free(_Eo *obj)
|
||||
{
|
||||
#ifdef EO_DEBUG
|
||||
if (obj->datarefcount)
|
||||
{
|
||||
ERR("Object %p data still referenced %d time(s).", obj, obj->datarefcount);
|
||||
}
|
||||
#endif
|
||||
_eo_id_release(obj->obj_id);
|
||||
free(obj);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eo_unref(_Eo *obj)
|
||||
{
|
||||
--(obj->refcount);
|
||||
if (obj->refcount == 0)
|
||||
{
|
||||
if (obj->del)
|
||||
{
|
||||
ERR("Object %p already deleted.", obj);
|
||||
return;
|
||||
}
|
||||
|
||||
_eo_del_internal(__FILE__, __LINE__, obj);
|
||||
|
||||
#ifdef EO_DEBUG
|
||||
/* If for some reason it's not empty, clear it. */
|
||||
while (obj->xrefs)
|
||||
{
|
||||
ERR("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.");
|
||||
Eina_Inlist *nitr = obj->xrefs->next;
|
||||
free(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node));
|
||||
obj->xrefs = nitr;
|
||||
}
|
||||
while (obj->data_xrefs)
|
||||
{
|
||||
Eina_Inlist *nitr = obj->data_xrefs->next;
|
||||
Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
|
||||
ERR("Data of object 0x%lx is still referenced by object %p", (unsigned long)obj->obj_id, xref->ref_obj);
|
||||
|
||||
free(xref);
|
||||
obj->data_xrefs = nitr;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!obj->manual_free)
|
||||
_eo_free(obj);
|
||||
else
|
||||
_eo_ref(obj); /* If we manual free, we keep a phantom ref. */
|
||||
}
|
||||
else if (obj->refcount < 0)
|
||||
{
|
||||
ERR("Obj:%p. Refcount (%d) < 0. Too many unrefs.", obj, obj->refcount);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EAPI void
|
||||
eo_unref(const Eo *obj_id)
|
||||
{
|
||||
|
@ -1449,12 +1256,6 @@ _eo_condtor_done(Eo *obj_id)
|
|||
obj->condtor_done = EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_eo_condtor_reset(_Eo *obj)
|
||||
{
|
||||
obj->condtor_done = EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
_eo_data_scope_get(const _Eo *obj, const _Eo_Class *klass)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <Eina.h>
|
||||
|
||||
#include "Eo.h"
|
||||
#include "eo_ptr_indirection.h"
|
||||
#include "eo_private.h"
|
||||
|
||||
EAPI Eo_Op EO_BASE_BASE_ID = 0;
|
||||
|
@ -446,17 +447,17 @@ _ev_cb_array_del(Eo *obj, void *class_data, va_list *list)
|
|||
}
|
||||
|
||||
static void
|
||||
_ev_cb_call(Eo *obj, void *class_data, va_list *list)
|
||||
_ev_cb_call(Eo *obj_id, void *class_data, va_list *list)
|
||||
{
|
||||
Private_Data *pd = (Private_Data *) class_data;
|
||||
const Eo_Event_Description *desc = va_arg(*list, const Eo_Event_Description *);
|
||||
void *event_info = va_arg(*list, void *);
|
||||
Eina_Bool *ret = va_arg(*list, Eina_Bool *);
|
||||
EO_OBJ_POINTER_RETURN(obj_id, obj);
|
||||
|
||||
if (ret) *ret = EINA_TRUE;
|
||||
|
||||
/* FIXME: Change eo_ref to _eo_ref and unref. */
|
||||
eo_ref(obj);
|
||||
_eo_ref(obj);
|
||||
pd->walking_list++;
|
||||
|
||||
Eo_Callback_Description *cb;
|
||||
|
@ -476,7 +477,7 @@ _ev_cb_call(Eo *obj, void *class_data, va_list *list)
|
|||
continue;
|
||||
|
||||
/* Abort callback calling if the func says so. */
|
||||
if (!it->func((void *) cb->func_data, obj, desc,
|
||||
if (!it->func((void *) cb->func_data, obj_id, desc,
|
||||
(void *) event_info))
|
||||
{
|
||||
if (ret) *ret = EINA_FALSE;
|
||||
|
@ -494,7 +495,7 @@ _ev_cb_call(Eo *obj, void *class_data, va_list *list)
|
|||
if (cb->items.item.desc == desc)
|
||||
{
|
||||
/* Abort callback calling if the func says so. */
|
||||
if (!cb->items.item.func((void *) cb->func_data, obj, desc,
|
||||
if (!cb->items.item.func((void *) cb->func_data, obj_id, desc,
|
||||
(void *) event_info))
|
||||
{
|
||||
if (ret) *ret = EINA_FALSE;
|
||||
|
@ -508,7 +509,7 @@ _ev_cb_call(Eo *obj, void *class_data, va_list *list)
|
|||
end:
|
||||
pd->walking_list--;
|
||||
_eo_callbacks_clear(pd);
|
||||
eo_unref(obj);
|
||||
_eo_unref(obj);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
|
|
|
@ -54,8 +54,217 @@ extern int _eo_log_dom;
|
|||
#endif
|
||||
#define DBG(...) EINA_LOG_DOM_DBG(_eo_log_dom, __VA_ARGS__)
|
||||
|
||||
void _eo_condtor_done(Eo *obj);
|
||||
|
||||
typedef size_t Eo_Id;
|
||||
typedef struct _Eo_Class _Eo_Class;
|
||||
typedef struct _Eo_Internal _Eo;
|
||||
|
||||
/* Retrieves the pointer to the object from the id */
|
||||
_Eo *_eo_obj_pointer_get(const Eo_Id obj_id);
|
||||
|
||||
/* Allocates an entry for the given object */
|
||||
Eo_Id _eo_id_allocate(const _Eo *obj);
|
||||
|
||||
/* Releases an entry by the object id */
|
||||
void _eo_id_release(const Eo_Id obj_id);
|
||||
|
||||
/* Free all the entries and the tables */
|
||||
void _eo_free_ids_tables();
|
||||
|
||||
void _eo_condtor_done(Eo *obj);
|
||||
|
||||
struct _Eo_Internal {
|
||||
#ifndef HAVE_EO_ID
|
||||
EINA_MAGIC
|
||||
#endif
|
||||
Eo *parent;
|
||||
Eina_List *children;
|
||||
const _Eo_Class *klass;
|
||||
#ifdef EO_DEBUG
|
||||
Eina_Inlist *xrefs;
|
||||
Eina_Inlist *data_xrefs;
|
||||
#endif
|
||||
|
||||
Eina_List *composite_objects;
|
||||
|
||||
Eo_Id obj_id;
|
||||
|
||||
int refcount;
|
||||
int datarefcount;
|
||||
|
||||
Eina_Bool do_error:1;
|
||||
Eina_Bool condtor_done:1;
|
||||
|
||||
Eina_Bool composite:1;
|
||||
Eina_Bool del:1;
|
||||
Eina_Bool manual_free:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef Eo_Class_Id
|
||||
* An Id of a class.
|
||||
* @ingroup Eo_Class
|
||||
*/
|
||||
typedef uintptr_t Eo_Class_Id;
|
||||
|
||||
typedef struct _Dich_Chain1 Dich_Chain1;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
eo_op_func_type func;
|
||||
const _Eo_Class *src;
|
||||
} op_type_funcs;
|
||||
|
||||
struct _Dich_Chain1
|
||||
{
|
||||
op_type_funcs *funcs;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const _Eo_Class *klass;
|
||||
size_t offset;
|
||||
} Eo_Extension_Data_Offset;
|
||||
|
||||
struct _Eo_Class
|
||||
{
|
||||
EINA_MAGIC
|
||||
Eo_Class_Id class_id;
|
||||
const _Eo_Class *parent;
|
||||
const Eo_Class_Description *desc;
|
||||
Dich_Chain1 *chain; /**< The size is chain size */
|
||||
|
||||
const _Eo_Class **extensions;
|
||||
|
||||
Eo_Extension_Data_Offset *extn_data_off;
|
||||
|
||||
const _Eo_Class **mro;
|
||||
|
||||
unsigned int obj_size; /**< size of an object of this class */
|
||||
unsigned int chain_size;
|
||||
unsigned int base_id;
|
||||
unsigned int data_offset; /* < Offset of the data within object data. */
|
||||
|
||||
Eina_Bool constructed : 1;
|
||||
/* [extensions*] + NULL */
|
||||
/* [mro*] + NULL */
|
||||
/* [extensions data offset] + NULL */
|
||||
};
|
||||
|
||||
static inline void
|
||||
_eo_condtor_reset(_Eo *obj)
|
||||
{
|
||||
obj->condtor_done = EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eo_del_internal(const char *file, int line, _Eo *obj)
|
||||
{
|
||||
Eina_Bool do_err;
|
||||
/* We need that for the event callbacks that may ref/unref. */
|
||||
obj->refcount++;
|
||||
|
||||
eo_do((Eo *) obj->obj_id, eo_event_callback_call(EO_EV_DEL, NULL, NULL));
|
||||
|
||||
const _Eo_Class *klass = obj->klass;
|
||||
|
||||
_eo_condtor_reset(obj);
|
||||
|
||||
do_err = eo_do((Eo *)obj->obj_id, eo_destructor());
|
||||
if (EINA_UNLIKELY(!do_err))
|
||||
{
|
||||
ERR("in %s:%d: Object of class '%s' - One of the object destructors have failed.",
|
||||
file, line, klass->desc->name);
|
||||
}
|
||||
|
||||
if (!obj->condtor_done)
|
||||
{
|
||||
ERR("in %s:%d: Object of class '%s' - Not all of the object destructors have been executed.",
|
||||
file, line, klass->desc->name);
|
||||
}
|
||||
/*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */
|
||||
|
||||
{
|
||||
Eina_List *itr, *itr_n;
|
||||
Eo *emb_obj;
|
||||
EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)
|
||||
{
|
||||
eo_composite_detach(emb_obj, (Eo *)obj->obj_id);
|
||||
}
|
||||
}
|
||||
|
||||
while (obj->children)
|
||||
{
|
||||
eo_parent_set(eina_list_data_get(obj->children), NULL); // ZZZ
|
||||
}
|
||||
|
||||
obj->del = EINA_TRUE;
|
||||
obj->refcount--;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eo_free(_Eo *obj)
|
||||
{
|
||||
#ifdef EO_DEBUG
|
||||
if (obj->datarefcount)
|
||||
{
|
||||
ERR("Object %p data still referenced %d time(s).", obj, obj->datarefcount);
|
||||
}
|
||||
#endif
|
||||
_eo_id_release(obj->obj_id);
|
||||
free(obj);
|
||||
}
|
||||
|
||||
static inline _Eo *
|
||||
_eo_ref(_Eo *obj)
|
||||
{
|
||||
obj->refcount++;
|
||||
return obj;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eo_unref(_Eo *obj)
|
||||
{
|
||||
--(obj->refcount);
|
||||
if (obj->refcount == 0)
|
||||
{
|
||||
if (obj->del)
|
||||
{
|
||||
ERR("Object %p already deleted.", obj);
|
||||
return;
|
||||
}
|
||||
|
||||
_eo_del_internal(__FILE__, __LINE__, obj);
|
||||
|
||||
#ifdef EO_DEBUG
|
||||
/* If for some reason it's not empty, clear it. */
|
||||
while (obj->xrefs)
|
||||
{
|
||||
ERR("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.");
|
||||
Eina_Inlist *nitr = obj->xrefs->next;
|
||||
free(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node));
|
||||
obj->xrefs = nitr;
|
||||
}
|
||||
while (obj->data_xrefs)
|
||||
{
|
||||
Eina_Inlist *nitr = obj->data_xrefs->next;
|
||||
Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
|
||||
ERR("Data of object 0x%lx is still referenced by object %p", (unsigned long)obj->obj_id, xref->ref_obj);
|
||||
|
||||
free(xref);
|
||||
obj->data_xrefs = nitr;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!obj->manual_free)
|
||||
_eo_free(obj);
|
||||
else
|
||||
_eo_ref(obj); /* If we manual free, we keep a phantom ref. */
|
||||
}
|
||||
else if (obj->refcount < 0)
|
||||
{
|
||||
ERR("Obj:%p. Refcount (%d) < 0. Too many unrefs.", obj, obj->refcount);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,20 +4,6 @@
|
|||
#include "Eo.h"
|
||||
#include "eo_private.h"
|
||||
|
||||
typedef size_t Eo_Id;
|
||||
|
||||
/* Retrieves the pointer to the object from the id */
|
||||
_Eo *_eo_obj_pointer_get(const Eo_Id obj_id);
|
||||
|
||||
/* Allocates an entry for the given object */
|
||||
Eo_Id _eo_id_allocate(const _Eo *obj);
|
||||
|
||||
/* Releases an entry by the object id */
|
||||
void _eo_id_release(const Eo_Id obj_id);
|
||||
|
||||
/* Free all the entries and the tables */
|
||||
void _eo_free_ids_tables();
|
||||
|
||||
/* Macro used to obtain the object pointer and return if fails. */
|
||||
|
||||
#ifdef HAVE_EO_ID
|
||||
|
|
Loading…
Reference in New Issue