eo: replace composite_objects Eina_List with an array of Eo_Object*
authorJérémy Zurcher <jeremy@asynk.ch>
Wed, 5 Mar 2014 22:57:39 +0000 (23:57 +0100)
committerJérémy Zurcher <jeremy@asynk.ch>
Wed, 5 Mar 2014 22:57:39 +0000 (23:57 +0100)
as we don't support multiple composites of the same class,
and know at class elaboration how many composites we should have,
we can create the composites array and pack it at the end of the object.

src/lib/eo/Eo.h
src/lib/eo/eo.c
src/lib/eo/eo_private.h
src/tests/eo/composite_objects/composite_objects_main.c

index 47cb0a0..ef43dec 100644 (file)
@@ -940,7 +940,8 @@ EAPI Eina_Bool eo_destructed_is(const Eo *obj);
  * @param parent the "parent" object.
  * @return EINA_TRUE if successfull. EINA_FALSE otherwise.
  *
- * The class of comp_obj must be part of the extensions of the class of the parent.
+ * The class of comp_obj must be of the type EO_CLASS_TYPE_REGULAR
+ * and be part of the extensions of the class of the parent.
  * It is not possible to attach more then 1 composite of the same class.
  * This functions also sets the parent of comp_obj to parent.
  *
@@ -953,13 +954,14 @@ EAPI Eina_Bool eo_composite_attach(Eo *comp_obj, Eo *parent);
  * @brief Detach a composite object from another object.
  * @param comp_obj the object attached to parent.
  * @param parent the "parent" object.
+ * @return EINA_TRUE if successfull. EINA_FALSE otherwise.
  *
  * This functions also sets the parent of comp_obj to @c NULL.
  *
  * @see eo_composite_attach()
  * @see eo_composite_is()
  */
-EAPI void eo_composite_detach(Eo *comp_obj, Eo *parent);
+EAPI Eina_Bool eo_composite_detach(Eo *comp_obj, Eo *parent);
 
 /**
  * @brief Check if an object is a composite object.
index bce20dd..26a91d2 100644 (file)
@@ -311,18 +311,19 @@ _eo_op_internal(const char *file, int line, Eo_Base *eo_ptr, const _Eo_Class *cu
    /* Try composite objects */
    if (op_type == EO_OP_TYPE_REGULAR)
      {
-        Eina_List *itr;
-        Eo *emb_obj_id;
-        EINA_LIST_FOREACH(((_Eo_Object *) eo_ptr)->composite_objects, itr, emb_obj_id)
-          {
-             /* FIXME: Clean this up a bit. */
-             EO_OBJ_POINTER_RETURN_VAL(emb_obj_id, emb_obj, EINA_FALSE);
-             if (_eo_op_internal(file, line, (Eo_Base *) emb_obj, emb_obj->klass, op_type, op, p_list))
-               {
-                  return EINA_TRUE;
-               }
-          }
+        const _Eo_Object **comp_itr = ((_Eo_Object *) eo_ptr)->composites;
+        if (!comp_itr) return EINA_FALSE;
+
+        for (unsigned int i = 0; i < ((_Eo_Object *) eo_ptr)->klass->composites_count; i++, comp_itr++)
+          if (*comp_itr)
+            {
+               if (_eo_op_internal(file, line, (Eo_Base *) (*comp_itr), (*comp_itr)->klass, op_type, op, p_list))
+                 {
+                    return EINA_TRUE;
+                 }
+            }
      }
+
    return EINA_FALSE;
 }
 
@@ -921,6 +922,8 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...)
         EINA_LIST_FREE(extn_list, extn)
           {
              *(extn_itr++) = extn;
+             if (extn->desc->type == EO_CLASS_TYPE_REGULAR)
+               klass->composites_count += 1;
 
              DBG("Added '%s' extension", extn->desc->name);
           }
@@ -963,6 +966,8 @@ eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent_id, ...)
      }
 
    klass->obj_size = _eo_sz + extn_data_off;
+   if (klass->composites_count > 0)
+     klass->obj_size += (klass->composites_count * sizeof(_Eo_Object *));
    if (getenv("EO_DEBUG"))
      {
         fprintf(stderr, "Eo class '%s' will take %u bytes per object.\n",
@@ -1089,6 +1094,11 @@ eo_add_internal(const char *file, int line, const Eo_Class *klass_id, Eo *parent
 
    obj->refcount++;
    obj->klass = klass;
+   if (klass->composites_count == 0)
+     obj->composites = NULL;
+   else
+     obj->composites = (const _Eo_Object **)
+        ((char *) obj + klass->obj_size - (klass->composites_count * sizeof(_Eo_Object *)));
 
 #ifndef HAVE_EO_ID
    EINA_MAGIC_SET((Eo_Base *) obj, EO_EINA_MAGIC);
@@ -1497,39 +1507,62 @@ eo_shutdown(void)
 EAPI Eina_Bool
 eo_composite_attach(Eo *comp_obj_id, Eo *parent_id)
 {
+   const _Eo_Object **comp_itr;
+   const _Eo_Object **comp_dst;
+
    EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
    EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, EINA_FALSE);
 
+   if (!parent->composites) return EINA_FALSE;
+   if (comp_obj->klass->desc->type != EO_CLASS_TYPE_REGULAR) return EINA_FALSE;
    if (!eo_isa(parent_id, _eo_class_id_get(comp_obj->klass))) return EINA_FALSE;
 
+   comp_dst = NULL;
+   comp_itr = parent->composites;
+   for (unsigned int i = 0; i < parent->klass->composites_count; i++, comp_itr++)
      {
-        Eina_List *itr;
-        Eo *emb_obj_id;
-        EINA_LIST_FOREACH(parent->composite_objects, itr, emb_obj_id)
+        if (*comp_itr)
           {
-             EO_OBJ_POINTER_RETURN_VAL(emb_obj_id, emb_obj, EINA_FALSE);
-             if(emb_obj->klass == comp_obj->klass)
+             if ((*comp_itr)->klass == comp_obj->klass)
                return EINA_FALSE;
           }
+        else if (!comp_dst)
+          comp_dst = comp_itr;
      }
 
-   comp_obj->composite = EINA_TRUE;
-   parent->composite_objects = eina_list_prepend(parent->composite_objects, comp_obj_id);
+   if (!comp_dst)
+     return EINA_FALSE;
 
+   comp_obj->composite = EINA_TRUE;
+   *comp_dst = comp_obj;
    eo_do(comp_obj_id, eo_parent_set(parent_id));
 
    return EINA_TRUE;
 }
 
-EAPI void
+EAPI Eina_Bool
 eo_composite_detach(Eo *comp_obj_id, Eo *parent_id)
 {
-   EO_OBJ_POINTER_RETURN(comp_obj_id, comp_obj);
-   EO_OBJ_POINTER_RETURN(parent_id, parent);
+   const _Eo_Object **comp_itr;
+
+   EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
+   EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, EINA_FALSE);
+
+   if (!parent->composites) return EINA_FALSE;
+
+   comp_itr = parent->composites;
+   for (unsigned int i = 0; i < parent->klass->composites_count; i++, comp_itr++)
+     {
+        if (*comp_itr == comp_obj)
+          {
+             comp_obj->composite = EINA_FALSE;
+             *comp_itr = NULL;
+             eo_do(comp_obj_id, eo_parent_set(NULL));
+             return EINA_TRUE;
+          }
+     }
 
-   comp_obj->composite = EINA_FALSE;
-   parent->composite_objects = eina_list_remove(parent->composite_objects, comp_obj_id);
-   eo_do(comp_obj_id, eo_parent_set(NULL));
+   return EINA_FALSE;
 }
 
 EAPI Eina_Bool
index 2fd13a9..a985556 100644 (file)
@@ -94,7 +94,7 @@ struct _Eo_Object
      Eina_Inlist *data_xrefs;
 #endif
 
-     Eina_List *composite_objects;
+     const _Eo_Object **composites;
 
      int refcount;
      int datarefcount;
@@ -105,6 +105,8 @@ struct _Eo_Object
      Eina_Bool composite:1;
      Eina_Bool del:1;
      Eina_Bool manual_free:1;
+     /* data [parents, self, mixins]*/
+     /* [composite*] */
 };
 
 typedef struct _Dich_Chain1 Dich_Chain1;
@@ -158,6 +160,7 @@ struct _Eo_Class
    unsigned int chain_size;
    unsigned int base_id;
    unsigned int data_offset; /* < Offset of the data within object data. */
+   unsigned int composites_count;
 
    Eina_Bool constructed : 1;
    /* [extensions*] + NULL */
@@ -229,11 +232,11 @@ _eo_del_internal(const char *file, int line, _Eo_Object *obj)
    /*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)
+        const _Eo_Object **comp_itr = obj->composites;
+        for (unsigned int i = 0; i < obj->klass->composites_count; i++, comp_itr++)
           {
-             eo_composite_detach(emb_obj, _eo_id_get(obj));
+             if (*comp_itr)
+               eo_composite_detach(_eo_id_get(*comp_itr), _eo_id_get(obj));
           }
      }
 
index 1d5b8c0..ba96eb4 100644 (file)
@@ -54,7 +54,8 @@ main(int argc, char *argv[])
    fail_if(cb_called);
 
    fail_if(!eo_composite_is(simple));
-   eo_composite_detach(simple, obj);
+   fail_if(!eo_composite_detach(simple, obj));
+   fail_if(eo_composite_detach(simple, obj));
    fail_if(eo_composite_is(simple));
    fail_if(!eo_composite_attach(simple, obj));
    fail_if(!eo_composite_is(simple));