Eo: Added eo_parent_set.
[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    _eo_ref(obj);
1073
1074    if (obj->parent)
1075      {
1076         obj->parent->children =
1077            eina_inlist_remove(obj->parent->children, EINA_INLIST_GET(obj));
1078 //        eo_xunref(obj, obj->parent);
1079      }
1080
1081    obj->parent = (Eo *) parent;
1082    if (obj->parent)
1083      {
1084         obj->parent->children =
1085            eina_inlist_append(obj->parent->children, EINA_INLIST_GET(obj));
1086 //        eo_xref(obj, obj->parent);
1087      }
1088
1089    _eo_unref(obj);
1090
1091    return EINA_TRUE;
1092 }
1093
1094 EAPI Eo *
1095 eo_add(const Eo_Class *klass, Eo *parent)
1096 {
1097    EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, NULL);
1098
1099    if (parent) EO_MAGIC_RETURN_VAL(parent, EO_EINA_MAGIC, NULL);
1100
1101    if (EINA_UNLIKELY(klass->desc->type != EO_CLASS_TYPE_REGULAR))
1102      {
1103         ERR("Class '%s' is not instantiate-able. Aborting.", klass->desc->name);
1104         return NULL;
1105      }
1106
1107    Eo *obj = calloc(1, EO_ALIGN_SIZE(sizeof(*obj)) +
1108          (klass->data_offset + EO_ALIGN_SIZE(klass->desc->data_size)) +
1109          klass->extn_data_size);
1110    EINA_MAGIC_SET(obj, EO_EINA_MAGIC);
1111    obj->refcount++;
1112    obj->klass = klass;
1113
1114    eo_parent_set(obj, parent);
1115
1116    Eo_Kls_Itr prev_state;
1117
1118    _eo_kls_itr_init(klass, &obj->mro_itr, EO_NOOP, &prev_state);
1119    _eo_error_unset(obj);
1120
1121    _eo_ref(obj);
1122    _eo_constructor(obj, klass);
1123
1124    if (EINA_UNLIKELY(_eo_error_get(obj)))
1125      {
1126         ERR("Type '%s' - One of the object constructors have failed.", klass->desc->name);
1127         goto fail;
1128      }
1129
1130    if (EINA_UNLIKELY(!_eo_kls_itr_reached_end(&obj->mro_itr)))
1131      {
1132         ERR("Type '%s' - Not all of the object constructors have been executed.", klass->desc->name);
1133         goto fail;
1134      }
1135    _eo_kls_itr_end(&obj->mro_itr, &prev_state);
1136    _eo_unref(obj);
1137
1138    return obj;
1139
1140 fail:
1141    _eo_kls_itr_end(&obj->mro_itr, &prev_state);
1142    /* Unref twice, once for the ref above, and once for the basic object ref. */
1143    _eo_unref(obj);
1144    _eo_unref(obj);
1145    return NULL;
1146 }
1147
1148 typedef struct
1149 {
1150    EINA_INLIST;
1151    const Eo *ref_obj;
1152    const char *file;
1153    int line;
1154 } Eo_Xref_Node;
1155
1156 EAPI Eo *
1157 eo_xref_internal(Eo *obj, const Eo *ref_obj, const char *file, int line)
1158 {
1159    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, obj);
1160
1161    _eo_ref(obj);
1162
1163 #ifndef NDEBUG
1164    Eo_Xref_Node *xref = calloc(1, sizeof(*xref));
1165    xref->ref_obj = ref_obj;
1166    xref->file = file;
1167    xref->line = line;
1168
1169    /* FIXME: Make it sorted. */
1170    obj->xrefs = eina_inlist_prepend(obj->xrefs, EINA_INLIST_GET(xref));
1171 #else
1172    (void) ref_obj;
1173    (void) file;
1174    (void) line;
1175 #endif
1176
1177    return obj;
1178 }
1179
1180 EAPI void
1181 eo_xunref(Eo *obj, const Eo *ref_obj)
1182 {
1183    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1184 #ifndef NDEBUG
1185    Eo_Xref_Node *xref = NULL;
1186    EINA_INLIST_FOREACH(obj->xrefs, xref)
1187      {
1188         if (xref->ref_obj == ref_obj)
1189            break;
1190      }
1191
1192    if (xref)
1193      {
1194         obj->xrefs = eina_inlist_remove(obj->xrefs, EINA_INLIST_GET(xref));
1195         free(xref);
1196      }
1197    else
1198      {
1199         ERR("ref_obj (%p) does not reference obj (%p). Aborting unref.", ref_obj, obj);
1200         return;
1201      }
1202 #else
1203    (void) ref_obj;
1204 #endif
1205    _eo_unref(obj);
1206 }
1207
1208 static inline Eo *
1209 _eo_ref(Eo *obj)
1210 {
1211    obj->refcount++;
1212    return obj;
1213 }
1214
1215 EAPI Eo *
1216 eo_ref(const Eo *_obj)
1217 {
1218    Eo *obj = (Eo *) _obj;
1219    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, obj);
1220
1221    return _eo_ref(obj);
1222 }
1223
1224 static inline void
1225 _eo_del_internal(Eo *obj)
1226 {
1227    /* We need that for the event callbacks that may ref/unref. */
1228    obj->refcount++;
1229
1230    eo_do(obj, eo_event_callback_call(EO_EV_DEL, NULL, NULL));
1231
1232    const Eo_Class *klass = eo_class_get(obj);
1233    Eo_Kls_Itr prev_state;
1234
1235    _eo_kls_itr_init(klass, &obj->mro_itr, EO_NOOP, &prev_state);
1236    _eo_error_unset(obj);
1237    _eo_destructor(obj, klass);
1238    if (_eo_error_get(obj))
1239      {
1240         ERR("Type '%s' - One of the object destructors have failed.", klass->desc->name);
1241      }
1242
1243    if (!_eo_kls_itr_reached_end(&obj->mro_itr))
1244      {
1245         ERR("Type '%s' - Not all of the object destructors have been executed.", klass->desc->name);
1246      }
1247    _eo_kls_itr_end(&obj->mro_itr, &prev_state);
1248    /*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */
1249
1250      {
1251         Eina_List *itr, *itr_n;
1252         Eo *emb_obj;
1253         EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)
1254           {
1255              eo_composite_object_detach(obj, emb_obj);
1256           }
1257      }
1258
1259    eo_parent_set(obj, NULL);
1260    while (obj->children)
1261      {
1262         eo_parent_set(EINA_INLIST_CONTAINER_GET(obj->children, Eo), NULL);
1263      }
1264
1265    obj->del = EINA_TRUE;
1266    obj->refcount--;
1267 }
1268
1269 static inline void
1270 _eo_free(Eo *obj)
1271 {
1272    EINA_MAGIC_SET(obj, EO_FREED_EINA_MAGIC);
1273    free(obj);
1274 }
1275
1276 static inline void
1277 _eo_unref(Eo *obj)
1278 {
1279    if (--(obj->refcount) == 0)
1280      {
1281         _eo_del_internal(obj);
1282
1283 #ifndef NDEBUG
1284         /* If for some reason it's not empty, clear it. */
1285         while (obj->xrefs)
1286           {
1287              WRN("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.");
1288              Eina_Inlist *nitr = obj->xrefs->next;
1289              free(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node));
1290              obj->xrefs = nitr;
1291           }
1292 #endif
1293
1294         if (!obj->manual_free) _eo_free(obj);
1295      }
1296 }
1297
1298 EAPI void
1299 eo_unref(const Eo *_obj)
1300 {
1301    Eo *obj = (Eo *) _obj;
1302    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1303
1304    _eo_unref(obj);
1305 }
1306
1307 EAPI int
1308 eo_ref_get(const Eo *obj)
1309 {
1310    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, 0);
1311
1312    return obj->refcount;
1313 }
1314
1315 EAPI Eo *
1316 eo_parent_get(const Eo *obj)
1317 {
1318    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, NULL);
1319
1320    return obj->parent;
1321 }
1322
1323 EAPI void
1324 eo_error_set_internal(const Eo *obj, const char *file, int line)
1325 {
1326    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1327
1328    ERR("Error with obj '%p' at %s:%d", obj, file, line);
1329
1330    ((Eo *) obj)->construct_error = EINA_TRUE;
1331 }
1332
1333 static inline void
1334 _eo_error_unset(Eo *obj)
1335 {
1336    obj->construct_error = EINA_FALSE;
1337 }
1338
1339 /**
1340  * @internal
1341  * @brief Check if there was an error when constructing, destructing or calling a function of the object.
1342  * @param obj the object to work on.
1343  * @return @c EINA_TRUE if there was an error.
1344  */
1345 static inline Eina_Bool
1346 _eo_error_get(const Eo *obj)
1347 {
1348    return obj->construct_error;
1349 }
1350
1351 static inline void
1352 _eo_constructor_default(Eo *obj)
1353 {
1354    eo_constructor_super(obj);
1355 }
1356
1357 static inline void
1358 _eo_destructor_default(Eo *obj)
1359 {
1360    eo_destructor_super(obj);
1361 }
1362
1363 static void
1364 _eo_constructor(Eo *obj, const Eo_Class *klass)
1365 {
1366    if (!klass)
1367       return;
1368
1369    if (klass->desc->constructor)
1370       klass->desc->constructor(obj, _eo_data_get(obj, klass));
1371    else
1372       _eo_constructor_default(obj);
1373 }
1374
1375 static void
1376 _eo_destructor(Eo *obj, const Eo_Class *klass)
1377 {
1378    if (!klass)
1379       return;
1380
1381    if (klass->desc->destructor)
1382       klass->desc->destructor(obj, _eo_data_get(obj, klass));
1383    else
1384       _eo_destructor_default(obj);
1385 }
1386
1387 EAPI void
1388 eo_constructor_super(Eo *obj)
1389 {
1390    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1391
1392    _eo_constructor(obj, _eo_kls_itr_next(&obj->mro_itr, EO_NOOP));
1393 }
1394
1395 EAPI void
1396 eo_destructor_super(Eo *obj)
1397 {
1398    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1399
1400    _eo_destructor(obj, _eo_kls_itr_next(&obj->mro_itr, EO_NOOP));
1401 }
1402
1403 static inline void *
1404 _eo_data_get(const Eo *obj, const Eo_Class *klass)
1405 {
1406    if (EINA_LIKELY(klass->desc->data_size > 0))
1407      {
1408         if (EINA_UNLIKELY(klass->desc->type == EO_CLASS_TYPE_MIXIN))
1409           {
1410              Eo_Extension_Data_Offset *doff_itr =
1411                 eo_class_get(obj)->extn_data_off;
1412
1413              if (!doff_itr)
1414                 return NULL;
1415
1416              while (doff_itr->klass)
1417                {
1418                   if (doff_itr->klass == klass)
1419                      return ((char *) obj) + EO_ALIGN_SIZE(sizeof(*obj)) +
1420                            doff_itr->offset;
1421                   doff_itr++;
1422                }
1423           }
1424         else
1425           {
1426           return ((char *) obj) + EO_ALIGN_SIZE(sizeof(*obj)) +
1427              klass->data_offset;
1428           }
1429      }
1430
1431    return NULL;
1432 }
1433
1434 EAPI void *
1435 eo_data_get(const Eo *obj, const Eo_Class *klass)
1436 {
1437    void *ret;
1438    EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, NULL);
1439
1440 #ifndef NDEBUG
1441    if (!_eo_class_mro_has(obj->klass, klass))
1442      {
1443         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);
1444         return NULL;
1445      }
1446 #endif
1447
1448    ret = _eo_data_get(obj, klass);
1449
1450 #ifndef NDEBUG
1451    if (!ret && (klass->desc->data_size == 0))
1452      {
1453         ERR("Tried getting data of class '%s', but it has none..", klass->desc->name);
1454      }
1455 #endif
1456
1457    return ret;
1458 }
1459
1460 EAPI Eina_Bool
1461 eo_init(void)
1462 {
1463    const char *log_dom = "eo";
1464    if (_eo_init_count++ > 0)
1465       return EINA_TRUE;
1466
1467    eina_init();
1468
1469    _eo_classes = NULL;
1470    _eo_classes_last_id = EO_STATIC_IDS_LAST;
1471    _eo_log_dom = eina_log_domain_register(log_dom, EINA_COLOR_LIGHTBLUE);
1472    if (_eo_log_dom < 0)
1473      {
1474         EINA_LOG_ERR("Could not register log domain: %s", log_dom);
1475         return EINA_FALSE;
1476      }
1477
1478    if (!eina_lock_new(&_eo_class_creation_lock))
1479      {
1480         EINA_LOG_ERR("Could not init lock.");
1481         return EINA_FALSE;
1482      }
1483
1484    eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR);
1485    eina_magic_string_static_set(EO_FREED_EINA_MAGIC,
1486          EO_FREED_EINA_MAGIC_STR);
1487    eina_magic_string_static_set(EO_CLASS_EINA_MAGIC,
1488          EO_CLASS_EINA_MAGIC_STR);
1489
1490    return EINA_TRUE;
1491 }
1492
1493 EAPI Eina_Bool
1494 eo_shutdown(void)
1495 {
1496    size_t i;
1497    Eo_Class **cls_itr = _eo_classes;
1498
1499    if (--_eo_init_count > 0)
1500       return EINA_TRUE;
1501
1502    for (i = 0 ; i < _eo_classes_last_id ; i++, cls_itr++)
1503      {
1504         if (*cls_itr)
1505            eo_class_free(*cls_itr);
1506      }
1507
1508    if (_eo_classes)
1509       free(_eo_classes);
1510
1511    eina_lock_free(&_eo_class_creation_lock);
1512
1513    eina_log_domain_unregister(_eo_log_dom);
1514    _eo_log_dom = -1;
1515
1516    eina_shutdown();
1517    return EINA_TRUE;
1518 }
1519
1520 EAPI void
1521 eo_composite_object_attach(Eo *obj, Eo *emb_obj)
1522 {
1523    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1524    EO_MAGIC_RETURN(emb_obj, EO_EINA_MAGIC);
1525
1526    eo_xref(emb_obj, obj);
1527    obj->composite_objects = eina_list_prepend(obj->composite_objects, emb_obj);
1528 }
1529
1530 EAPI void
1531 eo_composite_object_detach(Eo *obj, Eo *emb_obj)
1532 {
1533    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1534    EO_MAGIC_RETURN(emb_obj, EO_EINA_MAGIC);
1535
1536    obj->composite_objects = eina_list_remove(obj->composite_objects, emb_obj);
1537    eo_xunref(emb_obj, obj);
1538 }
1539
1540 EAPI Eina_Bool
1541 eo_composite_is(const Eo *emb_obj)
1542 {
1543    if (!EINA_MAGIC_CHECK(emb_obj, EO_EINA_MAGIC))
1544      {
1545         EINA_MAGIC_FAIL(emb_obj, EO_EINA_MAGIC);
1546         return EINA_FALSE;
1547      }
1548
1549    Eo *obj = eo_parent_get(emb_obj);
1550    Eina_List *itr;
1551    Eo *tmp;
1552
1553    if (!obj)
1554       return EINA_FALSE;
1555
1556    EINA_LIST_FOREACH(obj->composite_objects, itr, tmp)
1557      {
1558         if (tmp == emb_obj)
1559            return EINA_TRUE;
1560      }
1561
1562    return EINA_FALSE;
1563 }
1564
1565 EAPI void
1566 eo_manual_free_set(Eo *obj, Eina_Bool manual_free)
1567 {
1568    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1569    obj->manual_free = manual_free;
1570 }
1571
1572 EAPI void
1573 eo_manual_free(Eo *obj)
1574 {
1575    EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1576
1577    if (EINA_FALSE == obj->manual_free)
1578      {
1579         ERR("Tried manually free the object %p while the option has not been set; see eo_manual_free_set for more information.", obj);
1580         return;
1581      }
1582
1583    if (0 != obj->refcount)
1584      {
1585         ERR("Tried deleting the object %p while still referenced(%d).", obj, eo_ref_get(obj));
1586         return;
1587      }
1588
1589    _eo_free(obj);
1590 }
1591