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