Eo: Allow interfaces to have class constructors/destructors.
[profile/ivi/eobj.git] / src / lib / eo.c
1 #include <Eina.h>
2
3 #include "Eo.h"
4 #include "eo_private.h"
5
6 #include "config.h"
7
8 /* The last id that should be reserved for statically allocated classes. */
9 #define EO_STATIC_IDS_LAST 10
10 #define EO_OP_IDS_FIRST 1
11
12 /* Used inside the class_get functions of classes, see #EO_DEFINE_CLASS */
13 EAPI Eina_Lock _eo_class_creation_lock;
14 int _eo_log_dom = -1;
15
16 static Eo_Class **_eo_classes;
17 static Eo_Class_Id _eo_classes_last_id;
18 static Eina_Bool _eo_init_count = 0;
19 static Eo_Op _eo_ops_last_id = 0;
20
21 static void _eo_condtor_reset(Eo *obj);
22 static inline void *_eo_data_get(const Eo *obj, const Eo_Class *klass);
23 static inline Eo *_eo_ref(Eo *obj);
24 static inline void _eo_unref(Eo *obj);
25
26 typedef struct
27 {
28    const Eo_Class **kls_itr;
29    Eina_Bool insuper_context:1;
30 } Eo_Kls_Itr;
31
32 struct _Eo {
33      EINA_MAGIC
34      EINA_INLIST;
35      Eo *parent;
36      Eina_Inlist *children;
37      const Eo_Class *klass;
38      int refcount;
39 #ifndef NDEBUG
40      Eina_Inlist *xrefs;
41 #endif
42
43      Eina_List *composite_objects;
44
45      Eo_Kls_Itr mro_itr;
46
47      Eina_Bool do_error:1;
48      Eina_Bool condtor_done:1;
49
50      Eina_Bool composite:1;
51      Eina_Bool del:1;
52      Eina_Bool manual_free:1;
53 };
54
55 /* Start of Dich */
56
57 /* How we search and store the implementations in classes. */
58 #define DICH_CHAIN_LAST_BITS 5
59 #define DICH_CHAIN_LAST_SIZE (1 << DICH_CHAIN_LAST_BITS)
60 #define DICH_CHAIN1(x) ((x) / DICH_CHAIN_LAST_SIZE)
61 #define DICH_CHAIN_LAST(x) ((x) % DICH_CHAIN_LAST_SIZE)
62
63 #define OP_CLASS_OFFSET_GET(x) (((x) >> EO_OP_CLASS_OFFSET) & 0xffff)
64
65 #define ID_CLASS_GET(id) ({ \
66       (Eo_Class *) ((id <= _eo_classes_last_id) && (id > 0)) ? \
67       (_eo_classes[id - 1]) : NULL; \
68       })
69
70 #define EO_ALIGN_SIZE(size) \
71         ((size) + (sizeof(void *) - ((size) % sizeof(void *))))
72
73 typedef struct _Dich_Chain1 Dich_Chain1;
74
75 typedef struct
76 {
77    eo_op_func_type func;
78    const Eo_Class *src;
79 } op_type_funcs;
80
81 struct _Dich_Chain1
82 {
83    op_type_funcs *funcs;
84 };
85
86 typedef struct
87 {
88    const Eo_Class *klass;
89    size_t offset;
90 } Eo_Extension_Data_Offset;
91
92 struct _Eo_Class
93 {
94    EINA_MAGIC
95    Eo_Class_Id class_id;
96    const Eo_Class *parent;
97    const Eo_Class_Description *desc;
98    Dich_Chain1 *chain; /**< The size is class_id */
99    size_t chain_size;
100    size_t base_id;
101
102    const Eo_Class **extensions;
103
104    Eo_Extension_Data_Offset *extn_data_off;
105    size_t extn_data_size;
106
107    const Eo_Class **mro;
108    Eo_Kls_Itr mro_itr;
109
110    size_t data_offset; /* < Offset of the data within object data. */
111
112    Eina_Bool constructed : 1;
113 };
114
115 static inline void
116 _dich_chain_alloc(Dich_Chain1 *chain1)
117 {
118    if (!chain1->funcs)
119      {
120         chain1->funcs = calloc(DICH_CHAIN_LAST_SIZE, sizeof(*(chain1->funcs)));
121      }
122 }
123
124 static inline void
125 _dich_copy_all(Eo_Class *dst, const Eo_Class *src)
126 {
127    Eo_Class_Id i;
128    const Dich_Chain1 *sc1 = src->chain;
129    Dich_Chain1 *dc1 = dst->chain;
130    for (i = 0 ; i <= DICH_CHAIN1(src->base_id) ; i++, sc1++, dc1++)
131      {
132         if (sc1->funcs)
133           {
134              size_t j;
135
136              _dich_chain_alloc(dc1);
137
138              const op_type_funcs *sf = sc1->funcs;
139              op_type_funcs *df = dc1->funcs;
140              for (j = 0 ; j < DICH_CHAIN_LAST_SIZE ; j++, df++, sf++)
141                {
142                   if (sf->func)
143                     {
144                        memcpy(df, sf, sizeof(*df));
145                     }
146                }
147           }
148      }
149 }
150
151 static inline const op_type_funcs *
152 _dich_func_get(const Eo_Class *klass, Eo_Op op)
153 {
154    size_t idx1 = DICH_CHAIN1(op);
155    if (EINA_UNLIKELY(idx1 >= klass->chain_size))
156       return NULL;
157    Dich_Chain1 *chain1 = &klass->chain[idx1];
158    if (EINA_UNLIKELY(!chain1->funcs))
159       return NULL;
160    return &chain1->funcs[DICH_CHAIN_LAST(op)];
161 }
162
163 static inline void
164 _dich_func_set(Eo_Class *klass, Eo_Op op, eo_op_func_type func)
165 {
166    size_t idx1 = DICH_CHAIN1(op);
167    Dich_Chain1 *chain1 = &klass->chain[idx1];
168    _dich_chain_alloc(chain1);
169    chain1->funcs[DICH_CHAIN_LAST(op)].func = func;
170    chain1->funcs[DICH_CHAIN_LAST(op)].src = klass;
171 }
172
173 static inline void
174 _dich_func_clean_all(Eo_Class *klass)
175 {
176    size_t i;
177    Dich_Chain1 *chain1 = klass->chain;
178
179    for (i = 0 ; i <= DICH_CHAIN1(klass->base_id) ; i++, chain1++)
180      {
181         if (chain1->funcs)
182            free(chain1->funcs);
183      }
184    free(klass->chain);
185    klass->chain = NULL;
186 }
187
188 /* END OF DICH */
189
190 static const Eo_Op_Description noop_desc =
191         EO_OP_DESCRIPTION(EO_NOOP, "No operation.");
192
193 static const Eo_Class *
194 _eo_op_class_get(Eo_Op op)
195 {
196    /* FIXME: Make it fast. */
197    const Eo_Class *klass = NULL;
198    Eo_Class **itr = _eo_classes;
199    Eo_Class_Id i;
200    for (i = 0 ; i < _eo_classes_last_id ; i++, itr++)
201      {
202         if (*itr && ((*itr)->base_id <= op) &&
203               (op <= (*itr)->base_id + (*itr)->desc->ops.count))
204           {
205              klass = *itr;
206              return klass;
207           }
208      }
209
210    return klass;
211 }
212
213 static const Eo_Op_Description *
214 _eo_op_id_desc_get(Eo_Op op)
215 {
216    const Eo_Class *klass;
217
218    if (op == EO_NOOP)
219       return &noop_desc;
220
221    klass = _eo_op_class_get(op);
222
223    if (klass)
224      {
225         Eo_Op sub_id = op - klass->base_id;
226        if (sub_id < klass->desc->ops.count)
227           return klass->desc->ops.descs + sub_id;
228      }
229
230    return NULL;
231 }
232
233 static const char *
234 _eo_op_id_name_get(Eo_Op op)
235 {
236    const Eo_Op_Description *desc = _eo_op_id_desc_get(op);
237    return (desc) ? desc->name : NULL;
238 }
239
240 static inline void
241 _eo_kls_itr_init(const Eo_Class *obj_klass, Eo_Kls_Itr *cur, Eo_Kls_Itr *prev_state)
242 {
243    if (cur->insuper_context)
244      {
245         memcpy(prev_state, cur, sizeof(*cur));
246         cur->kls_itr = obj_klass->mro;
247      }
248 }
249
250 static inline void
251 _eo_kls_itr_end(Eo_Kls_Itr *cur, Eo_Kls_Itr *prev_state)
252 {
253    if (cur->insuper_context)
254      {
255         memcpy(cur, prev_state, sizeof(*cur));
256      }
257 }
258
259 static inline const Eo_Class *
260 _eo_kls_itr_get(Eo_Kls_Itr *cur)
261 {
262    return *(cur->kls_itr);
263 }
264
265 static inline const Eo_Class *
266 _eo_kls_itr_next(Eo_Kls_Itr *cur, Eo_Kls_Itr *prev_state, Eo_Op op)
267 {
268    const Eo_Class **kls_itr = cur->kls_itr;
269    memcpy(prev_state, cur, sizeof(*cur));
270    cur->insuper_context = EINA_TRUE;
271    if (*kls_itr)
272      {
273         const op_type_funcs *fsrc = _dich_func_get(*kls_itr, op);
274
275         while (*kls_itr && (*(kls_itr++) != fsrc->src))
276            ;
277
278         cur->kls_itr = kls_itr;
279         return *kls_itr;
280      }
281    else
282      {
283         return NULL;
284      }
285 }
286
287 static inline const op_type_funcs *
288 _eo_kls_itr_func_get(Eo_Kls_Itr *mro_itr, Eo_Op op)
289 {
290    const Eo_Class *klass = _eo_kls_itr_get(mro_itr);
291    if (klass)
292      {
293         const op_type_funcs *func = _dich_func_get(klass, op);
294
295         if (func && func->func)
296           {
297              return func;
298           }
299      }
300
301    return NULL;
302 }
303
304 #define _EO_OP_ERR_NO_OP_PRINT(op, klass) \
305    do \
306       { \
307          const Eo_Class *op_klass = _eo_op_class_get(op); \
308          const char *_dom_name = (op_klass) ? op_klass->desc->name : NULL; \
309          ERR("Can't find func for op %x ('%s' of domain '%s') for class '%s'. Aborting.", \
310                op, _eo_op_id_name_get(op), _dom_name, \
311                (klass) ? klass->desc->name : NULL); \
312       } \
313    while (0)
314
315 static Eina_Bool
316 _eo_op_internal(Eo *obj, Eo_Op_Type op_type, Eo_Op op, va_list *p_list)
317 {
318 #ifndef NDEBUG
319    const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
320
321    if (op_desc)
322      {
323         if (op_desc->op_type == EO_OP_TYPE_CLASS)
324           {
325              ERR("Tried calling a class op '%s' (%x) from a non-class context.", (op_desc) ? op_desc->name : NULL, op);
326              return EINA_FALSE;
327           }
328      }
329 #endif
330
331      {
332         const op_type_funcs *func =
333            _eo_kls_itr_func_get(&obj->mro_itr, op);
334         if (func)
335           {
336              func->func(obj, _eo_data_get(obj, func->src), p_list);
337              return EINA_TRUE;
338           }
339      }
340
341    /* Try composite objects */
342      {
343         Eina_List *itr;
344         Eo *emb_obj;
345         EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj)
346           {
347              if (_eo_op_internal(emb_obj, op_type, op, p_list))
348                {
349                   return EINA_TRUE;
350                }
351           }
352      }
353    return EINA_FALSE;
354 }
355
356 EAPI Eina_Bool
357 eo_do_internal(Eo *obj, Eo_Op_Type op_type, ...)
358 {
359    Eina_Bool prev_error;
360    Eina_Bool ret = EINA_TRUE;
361    Eo_Op op = EO_NOOP;
362    Eo_Kls_Itr prev_state;
363    va_list p_list;
364
365    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
366
367    prev_error = obj->do_error;
368    _eo_ref(obj);
369    _eo_kls_itr_init(obj->klass, &obj->mro_itr, &prev_state);
370
371    va_start(p_list, op_type);
372
373    op = va_arg(p_list, Eo_Op);
374    while (op)
375      {
376         if (!_eo_op_internal(obj, op_type, op, &p_list))
377           {
378              _EO_OP_ERR_NO_OP_PRINT(op, obj->klass);
379              ret = EINA_FALSE;
380              break;
381           }
382         op = va_arg(p_list, Eo_Op);
383      }
384
385    va_end(p_list);
386
387    _eo_unref(obj);
388
389    if (obj->do_error)
390       ret = EINA_FALSE;
391
392    obj->do_error = prev_error;
393
394    _eo_kls_itr_end(&obj->mro_itr, &prev_state);
395    return ret;
396 }
397
398 EAPI Eina_Bool
399 eo_do_super_internal(Eo *obj, Eo_Op_Type op_type, Eo_Op op, ...)
400 {
401    const Eo_Class *nklass;
402    Eina_Bool ret = EINA_TRUE;
403    va_list p_list;
404    Eo_Kls_Itr prev_state;
405    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
406
407    /* Advance the kls itr. */
408    nklass = _eo_kls_itr_next(&obj->mro_itr, &prev_state, op);
409
410    va_start(p_list, op);
411    if (!_eo_op_internal(obj, op_type, op, &p_list))
412      {
413         _EO_OP_ERR_NO_OP_PRINT(op, nklass);
414         ret = EINA_FALSE;
415      }
416    va_end(p_list);
417
418    if (obj->do_error)
419       ret = EINA_FALSE;
420
421    _eo_kls_itr_end(&obj->mro_itr, &prev_state);
422    return ret;
423 }
424
425 static Eina_Bool
426 _eo_class_op_internal(Eo_Class *klass, Eo_Op op, va_list *p_list)
427 {
428 #ifndef NDEBUG
429    const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
430
431    if (op_desc)
432      {
433         if (op_desc->op_type != EO_OP_TYPE_CLASS)
434           {
435              ERR("Tried calling an instance op '%s' (%x) from a class context.", (op_desc) ? op_desc->name : NULL, op);
436              return EINA_FALSE;
437           }
438      }
439 #endif
440
441      {
442         const op_type_funcs *func =
443            _eo_kls_itr_func_get(&klass->mro_itr, op);
444         if (func)
445           {
446              ((eo_op_func_type_class) func->func)(klass, p_list);
447              return EINA_TRUE;
448           }
449      }
450
451    return EINA_FALSE;
452 }
453
454 EAPI Eina_Bool
455 eo_class_do_internal(const Eo_Class *klass, ...)
456 {
457    Eina_Bool ret = EINA_TRUE;
458    Eo_Op op = EO_NOOP;
459    Eo_Kls_Itr prev_state;
460    va_list p_list;
461
462    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
463
464    _eo_kls_itr_init(klass, &((Eo_Class *) klass)->mro_itr, &prev_state);
465
466    va_start(p_list, klass);
467
468    op = va_arg(p_list, Eo_Op);
469    while (op)
470      {
471         if (!_eo_class_op_internal((Eo_Class *) klass, op, &p_list))
472           {
473              _EO_OP_ERR_NO_OP_PRINT(op, klass);
474              ret = EINA_FALSE;
475              break;
476           }
477         op = va_arg(p_list, Eo_Op);
478      }
479
480    va_end(p_list);
481
482    _eo_kls_itr_end(&((Eo_Class *) klass)->mro_itr, &prev_state);
483    return ret;
484 }
485
486 EAPI Eina_Bool
487 eo_class_do_super_internal(const Eo_Class *klass, Eo_Op op, ...)
488 {
489    const Eo_Class *nklass;
490    Eina_Bool ret = EINA_TRUE;
491    va_list p_list;
492    Eo_Kls_Itr prev_state;
493    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
494
495    /* Advance the kls itr. */
496    nklass = _eo_kls_itr_next(&((Eo_Class *) klass)->mro_itr, &prev_state, op);
497
498    va_start(p_list, op);
499    if (!_eo_class_op_internal((Eo_Class *) klass, op, &p_list))
500      {
501         _EO_OP_ERR_NO_OP_PRINT(op, nklass);
502         ret = EINA_FALSE;
503      }
504    va_end(p_list);
505
506    _eo_kls_itr_end(&((Eo_Class *) klass)->mro_itr, &prev_state);
507    return ret;
508 }
509
510 EAPI const Eo_Class *
511 eo_class_get(const Eo *obj)
512 {
513    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
514
515    return obj->klass;
516 }
517
518 EAPI const char *
519 eo_class_name_get(const Eo_Class *klass)
520 {
521    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, NULL);
522
523    return klass->desc->name;
524 }
525
526 static void
527 _eo_class_base_op_init(Eo_Class *klass)
528 {
529    const Eo_Class_Description *desc = klass->desc;
530
531    klass->base_id = _eo_ops_last_id;
532
533    if (desc && desc->ops.base_op_id)
534       *(desc->ops.base_op_id) = klass->base_id;
535
536    _eo_ops_last_id += desc->ops.count + 1;
537
538    klass->chain_size = DICH_CHAIN1(_eo_ops_last_id) + 1;
539    klass->chain = calloc(klass->chain_size, sizeof(*klass->chain));
540 }
541
542 #ifndef NDEBUG
543 static Eina_Bool
544 _eo_class_mro_has(const Eo_Class *klass, const Eo_Class *find)
545 {
546    const Eo_Class **itr;
547    for (itr = klass->mro ; *itr ; itr++)
548      {
549         if (*itr == find)
550           {
551              return EINA_TRUE;
552           }
553      }
554    return EINA_FALSE;
555 }
556 #endif
557
558 static Eina_List *
559 _eo_class_mro_add(Eina_List *mro, const Eo_Class *klass)
560 {
561    Eina_List *extn_pos = NULL;
562    Eina_Bool check_consistency = !mro;
563    if (!klass)
564       return mro;
565
566    mro = eina_list_append(mro, klass);
567
568    /* ONLY ADD MIXINS! */
569
570    /* Recursively add extenions. */
571      {
572         const Eo_Class **extn_itr;
573
574         for (extn_itr = klass->extensions ; *extn_itr ; extn_itr++)
575           {
576              const Eo_Class *extn = *extn_itr;
577              if (extn->desc->type != EO_CLASS_TYPE_MIXIN)
578                 continue;
579
580              mro = _eo_class_mro_add(mro, extn);
581              /* Not possible: if (!mro) return NULL; */
582
583              if (check_consistency)
584                {
585                   extn_pos = eina_list_append(extn_pos, eina_list_last(mro));
586                }
587           }
588      }
589
590    /* Check if we can create a consistent mro. We only do it for the class
591     * we are working on (i.e no parents). */
592    if (check_consistency)
593      {
594         const Eo_Class **extn_itr;
595
596         Eina_List *itr = extn_pos;
597         for (extn_itr = klass->extensions ; *extn_itr ; extn_itr++)
598           {
599              const Eo_Class *extn = *extn_itr;
600              if (extn->desc->type != EO_CLASS_TYPE_MIXIN)
601                 continue;
602
603              /* Get the first one after the extension. */
604              Eina_List *extn_list = eina_list_next(eina_list_data_get(itr));
605
606              /* If we found the extension again. */
607              if (eina_list_data_find_list(extn_list, extn))
608                {
609                   eina_list_free(mro);
610                   ERR("Cannot create a consistent method resolution order for class '%s' because of '%s'.", klass->desc->name, extn->desc->name);
611                   return NULL;
612                }
613
614              itr = eina_list_next(itr);
615           }
616      }
617
618
619    mro = _eo_class_mro_add(mro, klass->parent);
620
621    return mro;
622 }
623
624 static Eina_Bool
625 _eo_class_mro_init(Eo_Class *klass)
626 {
627    Eina_List *mro = NULL;
628
629    DBG("Started creating MRO for class '%s'", klass->desc->name);
630    mro = _eo_class_mro_add(mro, klass);
631
632    if (!mro)
633       return EINA_FALSE;
634
635    /* Remove duplicates and make them the right order. */
636      {
637         Eina_List *itr1, *itr2, *itr2n;
638
639         itr1 = eina_list_last(mro);
640         while (itr1)
641           {
642              itr2 = eina_list_prev(itr1);
643
644              while (itr2)
645                {
646                   itr2n = eina_list_prev(itr2);
647
648                   if (eina_list_data_get(itr1) == eina_list_data_get(itr2))
649                     {
650                        mro = eina_list_remove_list(mro, itr2);
651                     }
652
653                   itr2 = itr2n;
654                }
655
656              itr1 = eina_list_prev(itr1);
657           }
658      }
659
660    /* Copy the mro and free the list. */
661      {
662         const Eo_Class *kls_itr;
663         const Eo_Class **mro_itr;
664         klass->mro = calloc(sizeof(*klass->mro), eina_list_count(mro) + 1);
665
666         mro_itr = klass->mro;
667
668         EINA_LIST_FREE(mro, kls_itr)
669           {
670              *(mro_itr++) = kls_itr;
671
672              DBG("Added '%s' to MRO", kls_itr->desc->name);
673           }
674         *(mro_itr) = NULL;
675      }
676
677    DBG("Finished creating MRO for class '%s'", klass->desc->name);
678
679    return EINA_TRUE;
680 }
681
682 static void
683 _eo_class_constructor(Eo_Class *klass)
684 {
685    if (klass->constructed)
686       return;
687
688    klass->constructed = EINA_TRUE;
689
690    if (klass->desc->class_constructor)
691       klass->desc->class_constructor(klass);
692 }
693
694 EAPI void
695 eo_class_funcs_set(Eo_Class *klass, const Eo_Op_Func_Description *func_descs)
696 {
697    EO_MAGIC_RETURN(klass, EO_CLASS_EINA_MAGIC);
698
699    const Eo_Op_Func_Description *itr;
700    itr = func_descs;
701    if (itr)
702      {
703         for ( ; itr->op_type != EO_OP_TYPE_INVALID ; itr++)
704           {
705              const Eo_Op_Description *op_desc = _eo_op_id_desc_get(itr->op);
706
707              if (EINA_UNLIKELY(!op_desc || (itr->op == EO_NOOP)))
708                {
709                   ERR("Setting implementation for non-existent op %x for class '%s'. Func index: %d", itr->op, klass->desc->name, itr - func_descs);
710                }
711              else if (EINA_LIKELY(itr->op_type == op_desc->op_type))
712                {
713                   _dich_func_set(klass, itr->op, itr->func);
714                }
715              else
716                {
717                   ERR("Set function's op type (%x) is different than the one in the op description (%d) for op '%s' in class '%s'. Func index: %d",
718                         itr->op_type,
719                         (op_desc) ? op_desc->op_type : EO_OP_TYPE_REGULAR,
720                         (op_desc) ? op_desc->name : NULL,
721                         klass->desc->name,
722                         itr - func_descs);
723                }
724           }
725      }
726 }
727
728 static void
729 eo_class_free(Eo_Class *klass)
730 {
731    if (klass->constructed)
732      {
733         if (klass->desc->class_destructor)
734            klass->desc->class_destructor(klass);
735
736         _dich_func_clean_all(klass);
737      }
738
739    free(klass->extensions);
740
741    if (klass->mro)
742       free(klass->mro);
743
744    if (klass->extn_data_off)
745       free(klass->extn_data_off);
746
747    free(klass);
748 }
749
750 /* DEVCHECK */
751 static Eina_Bool
752 _eo_class_check_op_descs(const Eo_Class *klass, Eo_Class_Id id)
753 {
754    const Eo_Class_Description *desc = klass->desc;
755    const Eo_Op_Description *itr;
756    size_t i;
757
758    if (desc->ops.count > 0)
759      {
760         if (((id == 0) || (id > EO_STATIC_IDS_LAST)) && !desc->ops.base_op_id)
761           {
762              ERR("Class '%s' has a non-zero ops count, but base_id is NULL.",
763                    desc->name);
764              return EINA_FALSE;
765           }
766
767         if (!desc->ops.descs)
768           {
769              ERR("Class '%s' has a non-zero ops count, but there are no descs.",
770                    desc->name);
771              return EINA_FALSE;
772           }
773      }
774
775    itr = desc->ops.descs;
776    for (i = 0 ; i < desc->ops.count ; i++, itr++)
777      {
778         if (itr->sub_op != i)
779           {
780              if (itr->name)
781                {
782                   ERR("Wrong order in Ops description for class '%s'. Expected %x and got %x", desc->name, i, itr->sub_op);
783                }
784              else
785                {
786                   ERR("Found too few Ops description for class '%s'. Expected %x descriptions, but found %x.", desc->name, desc->ops.count, i);
787                }
788              return EINA_FALSE;
789           }
790      }
791
792    if (itr && itr->name)
793      {
794         ERR("Found extra Ops description for class '%s'. Expected %d descriptions, but found more.", desc->name, desc->ops.count);
795         return EINA_FALSE;
796      }
797
798    return EINA_TRUE;
799 }
800
801 /* Not really called, just used for the ptr... */
802 static void
803 _eo_class_isa_func(Eo *obj EINA_UNUSED, void *class_data EINA_UNUSED, va_list *list EINA_UNUSED)
804 {
805    /* Do nonthing. */
806 }
807
808 EAPI const Eo_Class *
809 eo_class_new(const Eo_Class_Description *desc, Eo_Class_Id id, const Eo_Class *parent, ...)
810 {
811    Eo_Class *klass;
812    va_list p_list;
813
814    if (parent && !EINA_MAGIC_CHECK(parent, EO_CLASS_EINA_MAGIC))
815      {
816         EINA_MAGIC_FAIL(parent, EO_CLASS_EINA_MAGIC);
817         return NULL;
818      }
819
820    if (id > EO_STATIC_IDS_LAST)
821      {
822         ERR("Tried creating a class with the static id %d while the maximum static id is %d. Aborting.", id, EO_STATIC_IDS_LAST);
823         return NULL;
824      }
825
826    va_start(p_list, parent);
827
828    EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
829    EINA_SAFETY_ON_NULL_RETURN_VAL(desc->name, NULL);
830
831    /* Check restrictions on Interface types. */
832    if (desc->type == EO_CLASS_TYPE_INTERFACE)
833      {
834         EINA_SAFETY_ON_FALSE_RETURN_VAL(!desc->data_size, NULL);
835      }
836
837    klass = calloc(1, sizeof(Eo_Class));
838    klass->parent = parent;
839
840    /* Handle class extensions */
841      {
842         Eina_List *extn_list = NULL;
843         const Eo_Class *extn = NULL;
844         const Eo_Class **extn_itr = NULL;
845
846         extn = va_arg(p_list, Eo_Class *);
847         while (extn)
848           {
849              switch (extn->desc->type)
850                {
851                 case EO_CLASS_TYPE_REGULAR:
852                 case EO_CLASS_TYPE_REGULAR_NO_INSTANT:
853                 case EO_CLASS_TYPE_INTERFACE:
854                 case EO_CLASS_TYPE_MIXIN:
855                    extn_list = eina_list_append(extn_list, extn);
856                    break;
857                }
858
859              extn = va_arg(p_list, Eo_Class *);
860           }
861
862         klass->extensions = calloc(sizeof(*klass->extensions),
863               eina_list_count(extn_list) + 1);
864
865         extn_itr = klass->extensions;
866         EINA_LIST_FREE(extn_list, extn)
867           {
868              *(extn_itr++) = extn;
869           }
870      }
871
872    klass->desc = desc;
873
874    /* Handle the inheritance */
875    if (klass->parent)
876      {
877         /* Verify the inheritance is allowed. */
878         switch (klass->desc->type)
879           {
880            case EO_CLASS_TYPE_REGULAR:
881            case EO_CLASS_TYPE_REGULAR_NO_INSTANT:
882               if ((klass->parent->desc->type != EO_CLASS_TYPE_REGULAR) &&
883                     (klass->parent->desc->type != EO_CLASS_TYPE_REGULAR_NO_INSTANT))
884                 {
885                    ERR("Regular classes ('%s') aren't allowed to inherit from non-regular classes ('%s').", klass->desc->name, klass->parent->desc->name);
886                    goto cleanup;
887                 }
888               break;
889            case EO_CLASS_TYPE_INTERFACE:
890            case EO_CLASS_TYPE_MIXIN:
891               if ((klass->parent->desc->type != EO_CLASS_TYPE_INTERFACE) &&
892                     (klass->parent->desc->type != EO_CLASS_TYPE_MIXIN))
893                 {
894                    ERR("Non-regular classes ('%s') aren't allowed to inherit from regular classes ('%s').", klass->desc->name, klass->parent->desc->name);
895                    goto cleanup;
896                 }
897               break;
898           }
899
900
901         /* Update the current offset. */
902         /* FIXME: Make sure this alignment is enough. */
903         klass->data_offset = klass->parent->data_offset +
904            EO_ALIGN_SIZE(klass->parent->desc->data_size);
905      }
906
907    if (!_eo_class_check_op_descs(klass, id))
908      {
909         goto cleanup;
910      }
911
912    if (!_eo_class_mro_init(klass))
913      {
914         goto cleanup;
915      }
916
917    /* create MIXIN offset table. */
918      {
919         const Eo_Class **mro_itr = klass->mro;
920         Eo_Extension_Data_Offset *extn_data_itr;
921         size_t extn_num = 0;
922         size_t extn_data_off = klass->data_offset +
923            EO_ALIGN_SIZE(klass->desc->data_size);
924
925         /* FIXME: Make faster... */
926         while (*mro_itr)
927           {
928              if (((*mro_itr)->desc->type == EO_CLASS_TYPE_MIXIN) &&
929                    ((*mro_itr)->desc->data_size > 0))
930                {
931                   extn_num++;
932                }
933              mro_itr++;
934           }
935
936         klass->extn_data_off = calloc(extn_num + 1,
937               sizeof(*klass->extn_data_off));
938
939         extn_data_itr = klass->extn_data_off;
940         mro_itr = klass->mro;
941         while (*mro_itr)
942           {
943              if (((*mro_itr)->desc->type == EO_CLASS_TYPE_MIXIN) &&
944                    ((*mro_itr)->desc->data_size > 0))
945                {
946                   extn_data_itr->klass = *mro_itr;
947                   extn_data_itr->offset = extn_data_off;
948
949                   extn_data_off += EO_ALIGN_SIZE(extn_data_itr->klass->desc->data_size);
950                   extn_data_itr++;
951                }
952              mro_itr++;
953           }
954
955         klass->extn_data_size = extn_data_off;
956      }
957
958    eina_lock_take(&_eo_class_creation_lock);
959
960    if (id == 0)
961      {
962         klass->class_id = ++_eo_classes_last_id;
963      }
964    else
965      {
966 #ifndef NDEBUG
967         if (_eo_classes && _eo_classes[id - 1])
968           {
969              ERR("A class with id %d was already defined (%s). Aborting.", id,
970                    _eo_classes[id - 1]->desc->name);
971              eina_lock_release(&_eo_class_creation_lock);
972              goto cleanup;
973           }
974 #endif
975         klass->class_id = id;
976      }
977
978
979      {
980         /* FIXME: Handle errors. */
981         size_t arrsize = _eo_classes_last_id * sizeof(*_eo_classes);
982         Eo_Class **tmp;
983         tmp = realloc(_eo_classes, arrsize);
984
985         /* If it's the first allocation, memset. */
986         if (!_eo_classes)
987            memset(tmp, 0, arrsize);
988
989         _eo_classes = tmp;
990         _eo_classes[klass->class_id - 1] = klass;
991      }
992    eina_lock_release(&_eo_class_creation_lock);
993
994    EINA_MAGIC_SET(klass, EO_CLASS_EINA_MAGIC);
995
996    _eo_class_base_op_init(klass);
997    /* Flatten the function array */
998      {
999         const Eo_Class **mro_itr = klass->mro;
1000         for (  ; *mro_itr ; mro_itr++)
1001            ;
1002
1003         /* Skip ourselves. */
1004         for ( mro_itr-- ; mro_itr > klass->mro ; mro_itr--)
1005           {
1006              _dich_copy_all(klass, *mro_itr);
1007           }
1008      }
1009
1010    /* Mark which classes we implement */
1011      {
1012         const Eo_Class **extn_itr;
1013
1014         for (extn_itr = klass->extensions ; *extn_itr ; extn_itr++)
1015           {
1016              const Eo_Class *extn = *extn_itr;
1017              /* Set it in the dich. */
1018              _dich_func_set(klass, extn->base_id +
1019                    extn->desc->ops.count, _eo_class_isa_func);
1020           }
1021
1022         _dich_func_set(klass, klass->base_id + klass->desc->ops.count,
1023               _eo_class_isa_func);
1024
1025         if (klass->parent)
1026           {
1027              _dich_func_set(klass,
1028                    klass->parent->base_id + klass->parent->desc->ops.count,
1029                    _eo_class_isa_func);
1030           }
1031      }
1032
1033    klass->mro_itr.kls_itr = klass->mro;
1034
1035    _eo_class_constructor(klass);
1036
1037    va_end(p_list);
1038
1039    return klass;
1040
1041 cleanup:
1042    eo_class_free(klass);
1043    return NULL;
1044 }
1045
1046 EAPI Eina_Bool
1047 eo_isa(const Eo *obj, const Eo_Class *klass)
1048 {
1049    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
1050    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
1051    const op_type_funcs *func = _dich_func_get(obj->klass,
1052          klass->base_id + klass->desc->ops.count);
1053
1054    /* Currently implemented by reusing the LAST op id. Just marking it with
1055     * _eo_class_isa_func. */
1056    return (func && (func->func == _eo_class_isa_func));
1057 }
1058
1059 EAPI Eina_Bool
1060 eo_parent_set(Eo *obj, const Eo *parent)
1061 {
1062    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
1063    if (parent)
1064       EO_MAGIC_RETURN_VAL(parent, EO_EINA_MAGIC, EINA_FALSE);
1065
1066    if (obj->parent == parent)
1067       return EINA_TRUE;
1068
1069    _eo_ref(obj);
1070
1071    if (eo_composite_is(obj))
1072      {
1073         eo_composite_detach(obj, obj->parent);
1074      }
1075
1076    if (obj->parent)
1077      {
1078         obj->parent->children =
1079            eina_inlist_remove(obj->parent->children, EINA_INLIST_GET(obj));
1080         eo_xunref(obj, obj->parent);
1081      }
1082
1083    obj->parent = (Eo *) parent;
1084    if (obj->parent)
1085      {
1086         obj->parent->children =
1087            eina_inlist_append(obj->parent->children, EINA_INLIST_GET(obj));
1088         eo_xref(obj, obj->parent);
1089      }
1090
1091    _eo_unref(obj);
1092
1093    return EINA_TRUE;
1094 }
1095
1096 EAPI Eo *
1097 eo_add(const Eo_Class *klass, Eo *parent)
1098 {
1099    Eina_Bool do_err;
1100    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, NULL);
1101
1102    if (parent) EO_MAGIC_RETURN_VAL(parent, EO_EINA_MAGIC, NULL);
1103
1104    if (EINA_UNLIKELY(klass->desc->type != EO_CLASS_TYPE_REGULAR))
1105      {
1106         ERR("Class '%s' is not instantiate-able. Aborting.", klass->desc->name);
1107         return NULL;
1108      }
1109
1110    Eo *obj = calloc(1, EO_ALIGN_SIZE(sizeof(*obj)) +
1111          (klass->data_offset + EO_ALIGN_SIZE(klass->desc->data_size)) +
1112          klass->extn_data_size);
1113    EINA_MAGIC_SET(obj, EO_EINA_MAGIC);
1114    obj->refcount++;
1115    obj->klass = klass;
1116    obj->mro_itr.kls_itr = obj->klass->mro;
1117
1118    eo_parent_set(obj, parent);
1119
1120    _eo_condtor_reset(obj);
1121
1122    _eo_ref(obj);
1123    do_err = !eo_do(obj, eo_constructor());
1124
1125    if (EINA_UNLIKELY(do_err))
1126      {
1127         ERR("Object of class '%s' - One of the object constructors have failed.", klass->desc->name);
1128         goto fail;
1129      }
1130
1131    if (!obj->condtor_done)
1132      {
1133         ERR("Object of class '%s' - Not all of the object constructors have been executed.", klass->desc->name);
1134         goto fail;
1135      }
1136    _eo_unref(obj);
1137
1138    return obj;
1139
1140 fail:
1141    /* Unref twice, once for the ref above, and once for the basic object ref. */
1142    _eo_unref(obj);
1143    _eo_unref(obj);
1144    return NULL;
1145 }
1146
1147 typedef struct
1148 {
1149    EINA_INLIST;
1150    const Eo *ref_obj;
1151    const char *file;
1152    int line;
1153 } Eo_Xref_Node;
1154
1155 EAPI Eo *
1156 eo_xref_internal(Eo *obj, const Eo *ref_obj, const char *file, int line)
1157 {
1158    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, obj);
1159
1160    _eo_ref(obj);
1161
1162 #ifndef NDEBUG
1163    Eo_Xref_Node *xref = calloc(1, sizeof(*xref));
1164    xref->ref_obj = ref_obj;
1165    xref->file = file;
1166    xref->line = line;
1167
1168    obj->xrefs = eina_inlist_prepend(obj->xrefs, EINA_INLIST_GET(xref));
1169 #else
1170    (void) ref_obj;
1171    (void) file;
1172    (void) line;
1173 #endif
1174
1175    return obj;
1176 }
1177
1178 EAPI void
1179 eo_xunref(Eo *obj, const Eo *ref_obj)
1180 {
1181    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1182 #ifndef NDEBUG
1183    Eo_Xref_Node *xref = NULL;
1184    EINA_INLIST_FOREACH(obj->xrefs, xref)
1185      {
1186         if (xref->ref_obj == ref_obj)
1187            break;
1188      }
1189
1190    if (xref)
1191      {
1192         obj->xrefs = eina_inlist_remove(obj->xrefs, EINA_INLIST_GET(xref));
1193         free(xref);
1194      }
1195    else
1196      {
1197         ERR("ref_obj (%p) does not reference obj (%p). Aborting unref.", ref_obj, obj);
1198         return;
1199      }
1200 #else
1201    (void) ref_obj;
1202 #endif
1203    _eo_unref(obj);
1204 }
1205
1206 static inline Eo *
1207 _eo_ref(Eo *obj)
1208 {
1209    obj->refcount++;
1210    return obj;
1211 }
1212
1213 EAPI Eo *
1214 eo_ref(const Eo *_obj)
1215 {
1216    Eo *obj = (Eo *) _obj;
1217    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, obj);
1218
1219    return _eo_ref(obj);
1220 }
1221
1222 static inline void
1223 _eo_del_internal(Eo *obj)
1224 {
1225    Eina_Bool do_err;
1226    /* We need that for the event callbacks that may ref/unref. */
1227    obj->refcount++;
1228
1229    eo_do(obj, eo_event_callback_call(EO_EV_DEL, NULL, NULL));
1230
1231    const Eo_Class *klass = eo_class_get(obj);
1232
1233    _eo_condtor_reset(obj);
1234
1235    do_err = eo_do(obj, eo_destructor());
1236    if (EINA_UNLIKELY(!do_err))
1237      {
1238         ERR("Object of class '%s' - One of the object destructors have failed.", klass->desc->name);
1239      }
1240
1241    if (!obj->condtor_done)
1242      {
1243         ERR("Object of class '%s' - Not all of the object destructors have been executed.", klass->desc->name);
1244      }
1245    /*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */
1246
1247      {
1248         Eina_List *itr, *itr_n;
1249         Eo *emb_obj;
1250         EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)
1251           {
1252              eo_composite_detach(emb_obj, obj);
1253           }
1254      }
1255
1256    while (obj->children)
1257      {
1258         eo_parent_set(EINA_INLIST_CONTAINER_GET(obj->children, Eo), NULL);
1259      }
1260
1261    obj->del = EINA_TRUE;
1262    obj->refcount--;
1263 }
1264
1265 static inline void
1266 _eo_free(Eo *obj)
1267 {
1268    EINA_MAGIC_SET(obj, EO_FREED_EINA_MAGIC);
1269    free(obj);
1270 }
1271
1272 static inline void
1273 _eo_unref(Eo *obj)
1274 {
1275    if (--(obj->refcount) == 0)
1276      {
1277         if (obj->del)
1278           {
1279              ERR("Object %p already deleted.", obj);
1280              return;
1281           }
1282
1283         _eo_del_internal(obj);
1284
1285 #ifndef NDEBUG
1286         /* If for some reason it's not empty, clear it. */
1287         while (obj->xrefs)
1288           {
1289              WRN("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.");
1290              Eina_Inlist *nitr = obj->xrefs->next;
1291              free(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node));
1292              obj->xrefs = nitr;
1293           }
1294 #endif
1295
1296         if (!obj->manual_free)
1297            _eo_free(obj);
1298         else
1299            _eo_ref(obj); /* If we manual free, we keep a phantom ref. */
1300      }
1301 }
1302
1303 EAPI void
1304 eo_unref(const Eo *_obj)
1305 {
1306    Eo *obj = (Eo *) _obj;
1307    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1308
1309    _eo_unref(obj);
1310 }
1311
1312 EAPI void
1313 eo_del(const Eo *obj)
1314 {
1315    eo_parent_set((Eo *) obj, NULL);
1316    eo_unref(obj);
1317 }
1318
1319 EAPI int
1320 eo_ref_get(const Eo *obj)
1321 {
1322    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, 0);
1323
1324    return obj->refcount;
1325 }
1326
1327 EAPI Eo *
1328 eo_parent_get(const Eo *obj)
1329 {
1330    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, NULL);
1331
1332    return obj->parent;
1333 }
1334
1335 EAPI void
1336 eo_error_set_internal(const Eo *obj, const char *file, int line)
1337 {
1338    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1339
1340    ERR("Error with obj '%p' at %s:%d", obj, file, line);
1341
1342    ((Eo *) obj)->do_error = EINA_TRUE;
1343 }
1344
1345 void
1346 _eo_condtor_done(Eo *obj)
1347 {
1348    if (obj->condtor_done)
1349      {
1350         ERR("Object %p is already constructed at this point.", obj);
1351         return;
1352      }
1353
1354    obj->condtor_done = EINA_TRUE;
1355 }
1356
1357 static void
1358 _eo_condtor_reset(Eo *obj)
1359 {
1360    obj->condtor_done = EINA_FALSE;
1361 }
1362
1363 static inline void *
1364 _eo_data_get(const Eo *obj, const Eo_Class *klass)
1365 {
1366    if (EINA_LIKELY(klass->desc->data_size > 0))
1367      {
1368         if (EINA_UNLIKELY(klass->desc->type == EO_CLASS_TYPE_MIXIN))
1369           {
1370              Eo_Extension_Data_Offset *doff_itr =
1371                 eo_class_get(obj)->extn_data_off;
1372
1373              if (!doff_itr)
1374                 return NULL;
1375
1376              while (doff_itr->klass)
1377                {
1378                   if (doff_itr->klass == klass)
1379                      return ((char *) obj) + EO_ALIGN_SIZE(sizeof(*obj)) +
1380                         doff_itr->offset;
1381                   doff_itr++;
1382                }
1383           }
1384         else
1385           {
1386              return ((char *) obj) + EO_ALIGN_SIZE(sizeof(*obj)) +
1387                 klass->data_offset;
1388           }
1389      }
1390
1391    return NULL;
1392 }
1393
1394 EAPI void *
1395 eo_data_get(const Eo *obj, const Eo_Class *klass)
1396 {
1397    void *ret;
1398    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, NULL);
1399    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, NULL);
1400
1401 #ifndef NDEBUG
1402    if (!_eo_class_mro_has(obj->klass, klass))
1403      {
1404         ERR("Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter.", klass->desc->name, obj->klass->desc->name);
1405         return NULL;
1406      }
1407 #endif
1408
1409    ret = _eo_data_get(obj, klass);
1410
1411 #ifndef NDEBUG
1412    if (!ret && (klass->desc->data_size == 0))
1413      {
1414         ERR("Tried getting data of class '%s', but it has none..", klass->desc->name);
1415      }
1416 #endif
1417
1418    return ret;
1419 }
1420
1421 EAPI Eina_Bool
1422 eo_init(void)
1423 {
1424    const char *log_dom = "eo";
1425    if (_eo_init_count++ > 0)
1426       return EINA_TRUE;
1427
1428    eina_init();
1429
1430    _eo_classes = NULL;
1431    _eo_classes_last_id = EO_STATIC_IDS_LAST;
1432    _eo_ops_last_id = EO_OP_IDS_FIRST;
1433    _eo_log_dom = eina_log_domain_register(log_dom, EINA_COLOR_LIGHTBLUE);
1434    if (_eo_log_dom < 0)
1435      {
1436         EINA_LOG_ERR("Could not register log domain: %s", log_dom);
1437         return EINA_FALSE;
1438      }
1439
1440    if (!eina_lock_new(&_eo_class_creation_lock))
1441      {
1442         EINA_LOG_ERR("Could not init lock.");
1443         return EINA_FALSE;
1444      }
1445
1446    eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR);
1447    eina_magic_string_static_set(EO_FREED_EINA_MAGIC,
1448          EO_FREED_EINA_MAGIC_STR);
1449    eina_magic_string_static_set(EO_CLASS_EINA_MAGIC,
1450          EO_CLASS_EINA_MAGIC_STR);
1451
1452 #ifndef NDEBUG
1453    /* Call it just for coverage purposes. Ugly I know, but I like it better than
1454     * casting everywhere else. */
1455    _eo_class_isa_func(NULL, NULL, NULL);
1456 #endif
1457
1458    return EINA_TRUE;
1459 }
1460
1461 EAPI Eina_Bool
1462 eo_shutdown(void)
1463 {
1464    size_t i;
1465    Eo_Class **cls_itr = _eo_classes;
1466
1467    if (--_eo_init_count > 0)
1468       return EINA_TRUE;
1469
1470    for (i = 0 ; i < _eo_classes_last_id ; i++, cls_itr++)
1471      {
1472         if (*cls_itr)
1473            eo_class_free(*cls_itr);
1474      }
1475
1476    if (_eo_classes)
1477       free(_eo_classes);
1478
1479    eina_lock_free(&_eo_class_creation_lock);
1480
1481    eina_log_domain_unregister(_eo_log_dom);
1482    _eo_log_dom = -1;
1483
1484    eina_shutdown();
1485    return EINA_TRUE;
1486 }
1487
1488 EAPI void
1489 eo_composite_attach(Eo *comp_obj, Eo *parent)
1490 {
1491    EO_MAGIC_RETURN(comp_obj, EO_EINA_MAGIC);
1492    EO_MAGIC_RETURN(parent, EO_EINA_MAGIC);
1493
1494    comp_obj->composite = EINA_TRUE;
1495    eo_parent_set(comp_obj, parent);
1496    parent->composite_objects = eina_list_prepend(parent->composite_objects, comp_obj);
1497 }
1498
1499 EAPI void
1500 eo_composite_detach(Eo *comp_obj, Eo *parent)
1501 {
1502    EO_MAGIC_RETURN(comp_obj, EO_EINA_MAGIC);
1503    EO_MAGIC_RETURN(parent, EO_EINA_MAGIC);
1504
1505    comp_obj->composite = EINA_FALSE;
1506    parent->composite_objects = eina_list_remove(parent->composite_objects, comp_obj);
1507    eo_parent_set(comp_obj, NULL);
1508 }
1509
1510 EAPI Eina_Bool
1511 eo_composite_is(const Eo *comp_obj)
1512 {
1513    if (!EINA_MAGIC_CHECK(comp_obj, EO_EINA_MAGIC))
1514      {
1515         EINA_MAGIC_FAIL(comp_obj, EO_EINA_MAGIC);
1516         return EINA_FALSE;
1517      }
1518
1519    return comp_obj->composite;
1520 }
1521
1522 EAPI void
1523 eo_manual_free_set(Eo *obj, Eina_Bool manual_free)
1524 {
1525    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1526    obj->manual_free = manual_free;
1527 }
1528
1529 EAPI void
1530 eo_manual_free(Eo *obj)
1531 {
1532    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1533
1534    if (EINA_FALSE == obj->manual_free)
1535      {
1536         ERR("Tried to manually free the object %p while the option has not been set; see eo_manual_free_set for more information.", obj);
1537         return;
1538      }
1539
1540    if (!obj->del)
1541      {
1542         ERR("Tried deleting the object %p while still referenced(%d).", obj, eo_ref_get(obj));
1543         return;
1544      }
1545
1546    _eo_free(obj);
1547 }
1548