From 7849c5de3245a5cb677974872c40040c1b1b0fcc Mon Sep 17 00:00:00 2001 From: Cedric Bail Date: Thu, 27 Jun 2013 17:58:49 +0900 Subject: [PATCH] eo: 30% speed improvement in message propagation. --- src/lib/eo/eo.c | 199 ------------------------------------- src/lib/eo/eo_base_class.c | 13 +-- src/lib/eo/eo_private.h | 211 +++++++++++++++++++++++++++++++++++++++- src/lib/eo/eo_ptr_indirection.h | 14 --- 4 files changed, 217 insertions(+), 220 deletions(-) diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index 221f8d7..8863639 100644 --- a/src/lib/eo/eo.c +++ b/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) { diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c index a183493..d87bcff 100644 --- a/src/lib/eo/eo_base_class.c +++ b/src/lib/eo/eo_base_class.c @@ -5,6 +5,7 @@ #include #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 diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h index 28666d1..4332383 100644 --- a/src/lib/eo/eo_private.h +++ b/src/lib/eo/eo_private.h @@ -54,8 +54,217 @@ extern int _eo_log_dom; #endif #define DBG(...) EINA_LOG_DOM_DBG(_eo_log_dom, __VA_ARGS__) +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); -typedef struct _Eo_Internal _Eo; +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 diff --git a/src/lib/eo/eo_ptr_indirection.h b/src/lib/eo/eo_ptr_indirection.h index 4a35208..c8f4e9c 100644 --- a/src/lib/eo/eo_ptr_indirection.h +++ b/src/lib/eo/eo_ptr_indirection.h @@ -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 -- 2.7.4