eo base - optimize memory by extending extension memory
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>
Sun, 24 Apr 2016 05:38:02 +0000 (14:38 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Sun, 24 Apr 2016 05:40:46 +0000 (14:40 +0900)
so geneirc data, wrefs, comments and id's are not that common so put
them all into their own memory segment that's allocated separately to
the core object so we only use this memory when needed. we already had
an extension section anyway so it's not new - just using it now for
more of the rarer bits of data. 2 more pointers gone from most objects
anyway and now extension code handling is a bit cleaner.

src/lib/eo/eo_base_class.c

index a525886..7e3c442 100644 (file)
@@ -19,6 +19,8 @@ typedef struct
 {
    const char                *id;
    const char                *comment;
+   Eina_Inlist               *generic_data;
+   Eo                      ***wrefs;
 } Eo_Base_Extension;
 
 typedef struct
@@ -27,10 +29,7 @@ typedef struct
    Eo                        *parent;
    Eina_List                 *parent_list;
 
-   Eina_Inlist               *generic_data;
-   Eo                      ***wrefs;
-
-   Eo_Base_Extension         *extension;
+   Eo_Base_Extension         *ext;
    Eo_Callback_Description   *callbacks;
 
    Eina_Inlist               *current;
@@ -56,21 +55,32 @@ typedef struct
    Eo_Callback_Description *current;
 } Eo_Current_Callback_Description;
 
-static Eo_Base_Extension *
-_eo_base_extension_new(void)
+static inline void
+_eo_base_extension_free(Eo_Base_Extension *ext)
 {
-   Eo_Base_Extension *extension = calloc(1, sizeof(Eo_Base_Extension));
-   return extension;
+   free(ext);
 }
 
-static void
-_eo_base_extension_free(Eo_Base_Extension *extension)
+static inline void
+_eo_base_extension_need(Eo_Base_Data *pd)
 {
-   free(extension);
+   if (pd->ext) return;
+   pd->ext = calloc(1, sizeof(Eo_Base_Extension));
+}
+
+static inline void
+_eo_base_extension_noneed(Eo_Base_Data *pd)
+{
+   Eo_Base_Extension *ext = pd->ext;
+   if ((!ext) || (ext->id) || (ext->comment) || (ext->generic_data) ||
+       (ext->wrefs)) return;
+   _eo_base_extension_free(pd->ext);
+   pd->ext = NULL;
 }
 
 
 
+
 static void
 _eo_generic_data_node_free(Eo_Generic_Data_Node *node)
 {
@@ -87,13 +97,15 @@ _eo_base_cb_key_obj_del(void *data, const Eo_Event *event)
    if (pd)
      {
         Eo_Generic_Data_Node *node;
+        Eo_Base_Extension *ext = pd->ext;
 
-        EINA_INLIST_FOREACH(pd->generic_data, node)
+        if (!ext) return EINA_TRUE;
+        EINA_INLIST_FOREACH(ext->generic_data, node)
           {
              if ((node->data_is_obj) && (node->data == event->obj))
                {
-                  pd->generic_data = eina_inlist_remove(pd->generic_data,
-                                                        EINA_INLIST_GET(node));
+                  ext->generic_data = eina_inlist_remove
+                    (ext->generic_data, EINA_INLIST_GET(node));
                   eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
                                         _eo_base_cb_key_obj_del, data);
                   _eo_generic_data_node_free(node);
@@ -108,12 +120,14 @@ static void
 _eo_generic_data_del_all(Eo *obj, Eo_Base_Data *pd)
 {
    Eo_Generic_Data_Node *node;
+   Eo_Base_Extension *ext = pd->ext;
 
-   while (pd->generic_data)
+   if (!ext) return;
+   while (ext->generic_data)
      {
-        node = (Eo_Generic_Data_Node *)pd->generic_data;
-        pd->generic_data = eina_inlist_remove(pd->generic_data,
-                                              EINA_INLIST_GET(node));
+        node = (Eo_Generic_Data_Node *)ext->generic_data;
+        ext->generic_data = eina_inlist_remove(ext->generic_data,
+                                               EINA_INLIST_GET(node));
         if (node->data_is_obj)
           {
              eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
@@ -129,51 +143,62 @@ EOLIAN static void
 _eo_base_key_data_set(Eo *obj, Eo_Base_Data *pd, const char *key, const void *data)
 {
    Eo_Generic_Data_Node *node;
+   Eo_Base_Extension *ext = pd->ext;
 
    if (!key) return;
-   EINA_INLIST_FOREACH(pd->generic_data, node)
+   if (ext)
      {
-        if (!strcmp(node->key, key))
+        EINA_INLIST_FOREACH(ext->generic_data, node)
           {
-             if ((!node->data_is_obj) && (!node->data_is_value) &&
-                 (node->data == data)) return;
-             pd->generic_data = eina_inlist_remove(pd->generic_data,
-                                                   EINA_INLIST_GET(node));
-             if (node->data_is_obj)
+             if (!strcmp(node->key, key))
                {
-                  eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
-                                        _eo_base_cb_key_obj_del, obj);
-                  eo_unref(node->data);
+                  if ((!node->data_is_obj) && (!node->data_is_value) &&
+                      (node->data == data)) return;
+                  ext->generic_data = eina_inlist_remove
+                    (ext->generic_data, EINA_INLIST_GET(node));
+                  if (node->data_is_obj)
+                    {
+                       eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
+                                             _eo_base_cb_key_obj_del, obj);
+                       eo_unref(node->data);
+                    }
+                  else if (node->data_is_value) eina_value_free(node->data);
+                  _eo_generic_data_node_free(node);
+                  break;
                }
-             else if (node->data_is_value) eina_value_free(node->data);
-             _eo_generic_data_node_free(node);
-             break;
           }
      }
 
-   node = calloc(1, sizeof(Eo_Generic_Data_Node));
-   if (!node) return;
-   node->key = eina_stringshare_add(key);
-   node->data = (void *)data;
-   node->data_is_obj = EINA_FALSE;
-   pd->generic_data = eina_inlist_prepend(pd->generic_data,
-                                          EINA_INLIST_GET(node));
+   _eo_base_extension_need(pd);
+   ext = pd->ext;
+   if (ext)
+     {
+        node = calloc(1, sizeof(Eo_Generic_Data_Node));
+        if (!node) return;
+        node->key = eina_stringshare_add(key);
+        node->data = (void *)data;
+        node->data_is_obj = EINA_FALSE;
+        ext->generic_data = eina_inlist_prepend
+          (ext->generic_data, EINA_INLIST_GET(node));
+     }
 }
 
 EOLIAN static void *
 _eo_base_key_data_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
 {
    Eo_Generic_Data_Node *node;
+   Eo_Base_Extension *ext = pd->ext;
 
    if (!key) return NULL;
-   EINA_INLIST_FOREACH(pd->generic_data, node)
+   if (!ext) return NULL;
+   EINA_INLIST_FOREACH(ext->generic_data, node)
      {
         if (!strcmp(node->key, key))
           {
              if ((!node->data_is_obj) && (!node->data_is_value))
                {
-                  pd->generic_data = eina_inlist_promote(pd->generic_data,
-                                                         EINA_INLIST_GET(node));
+                  ext->generic_data = eina_inlist_promote
+                    (ext->generic_data, EINA_INLIST_GET(node));
                   return node->data;
                }
              else
@@ -191,14 +216,16 @@ EOLIAN static void
 _eo_base_key_del(Eo *obj, Eo_Base_Data *pd, const char *key)
 {
    Eo_Generic_Data_Node *node;
+   Eo_Base_Extension *ext = pd->ext;
 
    if (!key) return;
-   EINA_INLIST_FOREACH(pd->generic_data, node)
+   if (!ext) return;
+   EINA_INLIST_FOREACH(ext->generic_data, node)
      {
         if (!strcmp(node->key, key))
           {
-             pd->generic_data = eina_inlist_remove(pd->generic_data,
-                                                   EINA_INLIST_GET(node));
+             ext->generic_data = eina_inlist_remove
+               (ext->generic_data, EINA_INLIST_GET(node));
              if (node->data_is_obj)
                {
                   eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
@@ -216,53 +243,64 @@ EOLIAN static void
 _eo_base_key_obj_set(Eo *obj, Eo_Base_Data *pd, const char *key, Eo *objdata)
 {
    Eo_Generic_Data_Node *node;
+   Eo_Base_Extension *ext = pd->ext;
 
    if (!key) return;
-   EINA_INLIST_FOREACH(pd->generic_data, node)
+   if (ext)
      {
-        if (!strcmp(node->key, key))
+        EINA_INLIST_FOREACH(ext->generic_data, node)
           {
-             if ((node->data_is_obj) && (node->data == objdata)) return;
-             pd->generic_data = eina_inlist_remove(pd->generic_data,
-                                                   EINA_INLIST_GET(node));
-             if (node->data_is_obj)
+             if (!strcmp(node->key, key))
                {
-                  eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
-                                        _eo_base_cb_key_obj_del, obj);
-                  eo_unref(node->data);
+                  if ((node->data_is_obj) && (node->data == objdata)) return;
+                  ext->generic_data = eina_inlist_remove
+                    (ext->generic_data, EINA_INLIST_GET(node));
+                  if (node->data_is_obj)
+                    {
+                       eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
+                                             _eo_base_cb_key_obj_del, obj);
+                       eo_unref(node->data);
+                    }
+                  else if (node->data_is_value) eina_value_free(node->data);
+                  _eo_generic_data_node_free(node);
+                  break;
                }
-             else if (node->data_is_value) eina_value_free(node->data);
-             _eo_generic_data_node_free(node);
-             break;
           }
      }
 
-   node = calloc(1, sizeof(Eo_Generic_Data_Node));
-   if (!node) return;
-   node->key = eina_stringshare_add(key);
-   node->data = (void *)objdata;
-   node->data_is_obj = EINA_TRUE;
-   eo_event_callback_add(node->data, EO_BASE_EVENT_DEL,
-                         _eo_base_cb_key_obj_del, obj);
-   eo_ref(node->data);
-   pd->generic_data = eina_inlist_prepend(pd->generic_data,
-                                          EINA_INLIST_GET(node));
+   _eo_base_extension_need(pd);
+   ext = pd->ext;
+   if (ext)
+     {
+        node = calloc(1, sizeof(Eo_Generic_Data_Node));
+        if (!node) return;
+        node->key = eina_stringshare_add(key);
+        node->data = (void *)objdata;
+        node->data_is_obj = EINA_TRUE;
+        eo_event_callback_add(node->data, EO_BASE_EVENT_DEL,
+                              _eo_base_cb_key_obj_del, obj);
+        eo_ref(node->data);
+        ext->generic_data = eina_inlist_prepend
+          (ext->generic_data, EINA_INLIST_GET(node));
+     }
 }
 
 EOLIAN static Eo *
 _eo_base_key_obj_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
 {
    Eo_Generic_Data_Node *node;
+   Eo_Base_Extension *ext = pd->ext;
 
    if (!key) return NULL;
-   EINA_INLIST_FOREACH(pd->generic_data, node)
+   if (!ext) return NULL;
+   EINA_INLIST_FOREACH(ext->generic_data, node)
      {
         if (!strcmp(node->key, key))
           {
              if (node->data_is_obj)
                {
-                  pd->generic_data = eina_inlist_promote(pd->generic_data,
-                                                         EINA_INLIST_GET(node));
+                  ext->generic_data = eina_inlist_promote
+                    (ext->generic_data, EINA_INLIST_GET(node));
                   return node->data;
                }
              else
@@ -280,52 +318,63 @@ EOLIAN static void
 _eo_base_key_value_set(Eo *obj, Eo_Base_Data *pd, const char *key, Eina_Value *value)
 {
    Eo_Generic_Data_Node *node;
+   Eo_Base_Extension *ext = pd->ext;
 
    if (!key) return;
-   EINA_INLIST_FOREACH(pd->generic_data, node)
+   if (ext)
      {
-        if (!strcmp(node->key, key))
+        EINA_INLIST_FOREACH(ext->generic_data, node)
           {
-             if ((node->data_is_value) && (node->data == value)) return;
-             pd->generic_data = eina_inlist_remove(pd->generic_data,
-                                                   EINA_INLIST_GET(node));
-             if (node->data_is_obj)
+             if (!strcmp(node->key, key))
                {
-                  eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
-                                        _eo_base_cb_key_obj_del, obj);
-                  eo_unref(node->data);
+                  if ((node->data_is_value) && (node->data == value)) return;
+                  ext->generic_data = eina_inlist_remove
+                    (ext->generic_data, EINA_INLIST_GET(node));
+                  if (node->data_is_obj)
+                    {
+                       eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
+                                             _eo_base_cb_key_obj_del, obj);
+                       eo_unref(node->data);
+                    }
+                  else if (node->data_is_value) eina_value_free(node->data);
+                  _eo_generic_data_node_free(node);
+                  break;
                }
-             else if (node->data_is_value) eina_value_free(node->data);
-             _eo_generic_data_node_free(node);
-             break;
           }
      }
 
-   node = calloc(1, sizeof(Eo_Generic_Data_Node));
-   if (!node) return;
-   node->key = eina_stringshare_add(key);
-   node->data = (void *)value;
-   node->data_is_value = EINA_TRUE;
-   eo_event_callback_add(node->data, EO_BASE_EVENT_DEL,
-                         _eo_base_cb_key_obj_del, obj);
-   pd->generic_data = eina_inlist_prepend(pd->generic_data,
-                                          EINA_INLIST_GET(node));
+   _eo_base_extension_need(pd);
+   ext = pd->ext;
+   if (ext)
+     {
+        node = calloc(1, sizeof(Eo_Generic_Data_Node));
+        if (!node) return;
+        node->key = eina_stringshare_add(key);
+        node->data = (void *)value;
+        node->data_is_value = EINA_TRUE;
+        eo_event_callback_add(node->data, EO_BASE_EVENT_DEL,
+                              _eo_base_cb_key_obj_del, obj);
+        ext->generic_data = eina_inlist_prepend
+          (ext->generic_data, EINA_INLIST_GET(node));
+     }
 }
 
 EOLIAN static Eina_Value *
 _eo_base_key_value_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
 {
    Eo_Generic_Data_Node *node;
+   Eo_Base_Extension *ext = pd->ext;
 
    if (!key) return NULL;
-   EINA_INLIST_FOREACH(pd->generic_data, node)
+   if (!ext) return NULL;
+   EINA_INLIST_FOREACH(ext->generic_data, node)
      {
         if (!strcmp(node->key, key))
           {
              if (node->data_is_value)
                {
-                  pd->generic_data = eina_inlist_promote(pd->generic_data,
-                                                         EINA_INLIST_GET(node));
+                  ext->generic_data = eina_inlist_promote
+                    (ext->generic_data, EINA_INLIST_GET(node));
                   return node->data;
                }
              else
@@ -345,22 +394,16 @@ _eo_base_id_set(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *id)
    if ((id) && (!id[0])) id = NULL;
    if (id)
      {
-        if (!pd->extension)
-          pd->extension = _eo_base_extension_new();
-        if (pd->extension)
-          eina_stringshare_replace(&(pd->extension->id), id);
+        _eo_base_extension_need(pd);
+        if (pd->ext) eina_stringshare_replace(&(pd->ext->id), id);
      }
    else
      {
-        if (!pd->extension) return;
-        if (pd->extension->id)
+        if (!pd->ext) return;
+        if (pd->ext->id)
           {
-             eina_stringshare_replace(&(pd->extension->id), id);
-             if (!pd->extension->comment)
-               {
-                  _eo_base_extension_free(pd->extension);
-                  pd->extension = NULL;
-               }
+             eina_stringshare_replace(&(pd->ext->id), id);
+             _eo_base_extension_noneed(pd);
           }
      }
 }
@@ -368,8 +411,8 @@ _eo_base_id_set(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *id)
 EOLIAN static const char *
 _eo_base_id_get(Eo *obj EINA_UNUSED, Eo_Base_Data *pd)
 {
-   if (!pd->extension) return NULL;
-   return pd->extension->id;
+   if (!pd->ext) return NULL;
+   return pd->ext->id;
 }
 
 static inline Eina_Bool
@@ -530,22 +573,16 @@ _eo_base_comment_set(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *comment)
    if ((comment) && (!comment[0])) comment = NULL;
    if (comment)
      {
-        if (!pd->extension)
-          pd->extension = _eo_base_extension_new();
-        if (pd->extension)
-          eina_stringshare_replace(&(pd->extension->comment), comment);
+        _eo_base_extension_need(pd);
+        if (pd->ext) eina_stringshare_replace(&(pd->ext->comment), comment);
      }
    else
      {
-        if (!pd->extension) return;
-        if (pd->extension->comment)
+        if (!pd->ext) return;
+        if (pd->ext->comment)
           {
-             eina_stringshare_replace(&(pd->extension->comment), comment);
-             if (!pd->extension->id)
-               {
-                  _eo_base_extension_free(pd->extension);
-                  pd->extension = NULL;
-               }
+             eina_stringshare_replace(&(pd->ext->comment), comment);
+             _eo_base_extension_noneed(pd);
           }
      }
 }
@@ -553,8 +590,8 @@ _eo_base_comment_set(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *comment)
 EOLIAN static const char *
 _eo_base_comment_get(Eo *obj EINA_UNUSED, Eo_Base_Data *pd)
 {
-   if (!pd->extension) return NULL;
-   return pd->extension->comment;
+   if (!pd->ext) return NULL;
+   return pd->ext->comment;
 }
 
 
@@ -740,13 +777,12 @@ _eo_base_dbg_info_get(Eo *obj EINA_UNUSED, Eo_Base_Data *pd EINA_UNUSED, Eo_Dbg_
 static inline size_t
 _wref_count(Eo_Base_Data *pd)
 {
+   Eo ***itr;
    size_t count = 0;
-   if (!pd->wrefs)
-      return 0;
+   Eo_Base_Extension *ext = pd->ext;
 
-   Eo ***itr;
-   for (itr = pd->wrefs; *itr; itr++)
-      count++;
+   if ((!ext) || (!ext->wrefs)) return 0;
+   for (itr = ext->wrefs; *itr; itr++) count++;
 
    return count;
 }
@@ -756,16 +792,21 @@ _eo_base_wref_add(Eo *obj, Eo_Base_Data *pd, Eo **wref)
 {
    size_t count;
    Eo ***tmp;
+   Eo_Base_Extension *ext;
 
    count = _wref_count(pd);
    count += 1; /* New wref. */
 
-   tmp = realloc(pd->wrefs, sizeof(*pd->wrefs) * (count + 1));
+   _eo_base_extension_need(pd);
+   ext = pd->ext;
+   if (!ext) return;
+
+   tmp = realloc(ext->wrefs, sizeof(*ext->wrefs) * (count + 1));
    if (!tmp) return;
-   pd->wrefs = tmp;
+   ext->wrefs = tmp;
 
-   pd->wrefs[count - 1] = wref;
-   pd->wrefs[count] = NULL;
+   ext->wrefs[count - 1] = wref;
+   ext->wrefs[count] = NULL;
    *wref = obj;
 }
 
@@ -773,15 +814,16 @@ EOLIAN static void
 _eo_base_wref_del(Eo *obj, Eo_Base_Data *pd, Eo **wref)
 {
    size_t count;
+   Eo_Base_Extension *ext = pd->ext;
 
    if (*wref != obj)
      {
         ERR("Wref is a weak ref to %p, while this function was called on %p.",
-              *wref, obj);
+            *wref, obj);
         return;
      }
 
-   if (!pd->wrefs)
+   if ((!ext) || (!ext->wrefs))
      {
         ERR("There are no weak refs for object %p", obj);
         *wref = NULL;
@@ -793,11 +835,11 @@ _eo_base_wref_del(Eo *obj, Eo_Base_Data *pd, Eo **wref)
 
      {
         Eo ***itr;
-        for (itr = pd->wrefs; *itr; itr++)
+        for (itr = ext->wrefs; *itr; itr++)
           {
              if (*itr == wref)
                {
-                  *itr = pd->wrefs[count - 1];
+                  *itr = ext->wrefs[count - 1];
                   break;
                }
           }
@@ -813,16 +855,17 @@ _eo_base_wref_del(Eo *obj, Eo_Base_Data *pd, Eo **wref)
    if (count > 1)
      {
         Eo ***tmp;
-        // No count--; because of the NULL that is not included in the count. */
-        tmp = realloc(pd->wrefs, sizeof(*pd->wrefs) * count);
+        // No count--; because of the NULL that is not included in the count
+        tmp = realloc(ext->wrefs, sizeof(*ext->wrefs) * count);
         if (!tmp) return;
-        pd->wrefs = tmp;
-        pd->wrefs[count - 1] = NULL;
+        ext->wrefs = tmp;
+        ext->wrefs[count - 1] = NULL;
      }
    else
      {
-        free(pd->wrefs);
-        pd->wrefs = NULL;
+        free(ext->wrefs);
+        ext->wrefs = NULL;
+        _eo_base_extension_noneed(pd);
      }
 
    *wref = NULL;
@@ -832,15 +875,12 @@ static inline void
 _wref_destruct(Eo_Base_Data *pd)
 {
    Eo ***itr;
-   if (!pd->wrefs)
-      return;
-
-   for (itr = pd->wrefs; *itr; itr++)
-     {
-        **itr = NULL;
-     }
+   Eo_Base_Extension *ext = pd->ext;
 
-   free(pd->wrefs);
+   if ((!ext) || (!ext->wrefs)) return;
+   for (itr = ext->wrefs; *itr; itr++) **itr = NULL;
+   free(ext->wrefs);
+   ext->wrefs = NULL;
 }
 
 /* EOF Weak reference. */
@@ -1478,6 +1518,7 @@ EOLIAN static void
 _eo_base_destructor(Eo *obj, Eo_Base_Data *pd)
 {
    Eo *child;
+   Eo_Base_Extension *ext;
 
    DBG("%p - %s.", obj, eo_class_name_get(obj));
 
@@ -1501,14 +1542,15 @@ _eo_base_destructor(Eo *obj, Eo_Base_Data *pd)
    _wref_destruct(pd);
    _eo_callback_remove_all(pd);
 
-   if (pd->extension)
+   ext = pd->ext;
+   if (ext)
      {
-        eina_stringshare_del(pd->extension->id);
-        pd->extension->id = NULL;
-        eina_stringshare_del(pd->extension->comment);
-        pd->extension->comment = NULL;
-        _eo_base_extension_free(pd->extension);
-        pd->extension = NULL;
+        eina_stringshare_del(ext->id);
+        ext->id = NULL;
+        eina_stringshare_del(ext->comment);
+        ext->comment = NULL;
+        _eo_base_extension_free(ext);
+        pd->ext = NULL;
      }
 
    _eo_condtor_done(obj);