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