eo: 30% speed improvement in message propagation.
authorCedric Bail <cedric.bail@samsung.com>
Thu, 27 Jun 2013 08:58:49 +0000 (17:58 +0900)
committerCedric Bail <cedric.bail@samsung.com>
Fri, 28 Jun 2013 01:18:39 +0000 (10:18 +0900)
src/lib/eo/eo.c
src/lib/eo/eo_base_class.c
src/lib/eo/eo_private.h
src/lib/eo/eo_ptr_indirection.h

index 221f8d7..8863639 100644 (file)
 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)
 {
index a183493..d87bcff 100644 (file)
@@ -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
index 28666d1..4332383 100644 (file)
@@ -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
index 4a35208..c8f4e9c 100644 (file)
@@ -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