8 #include "eo_private.h"
10 /* The last id that should be reserved for statically allocated classes. */
11 #define EO_CLASS_IDS_FIRST 1
12 #define EO_OP_IDS_FIRST 1
14 /* Used inside the class_get functions of classes, see #EO_DEFINE_CLASS */
15 EAPI Eina_Lock _eo_class_creation_lock;
18 static Eo_Class **_eo_classes;
19 static Eo_Class_Id _eo_classes_last_id;
20 static Eina_Bool _eo_init_count = 0;
21 static Eo_Op _eo_ops_last_id = 0;
23 static void _eo_condtor_reset(Eo *obj);
24 static inline void *_eo_data_get(const Eo *obj, const Eo_Class *klass);
25 static inline Eo *_eo_ref(Eo *obj);
26 static inline void _eo_unref(Eo *obj);
27 static const Eo_Class *_eo_op_class_get(Eo_Op op);
28 static const Eo_Op_Description *_eo_op_id_desc_get(Eo_Op op);
39 Eina_Inlist *children;
40 const Eo_Class *klass;
46 Eina_List *composite_objects;
51 Eina_Bool condtor_done:1;
53 Eina_Bool composite:1;
55 Eina_Bool manual_free:1;
60 /* How we search and store the implementations in classes. */
61 #define DICH_CHAIN_LAST_BITS 5
62 #define DICH_CHAIN_LAST_SIZE (1 << DICH_CHAIN_LAST_BITS)
63 #define DICH_CHAIN1(x) ((x) / DICH_CHAIN_LAST_SIZE)
64 #define DICH_CHAIN_LAST(x) ((x) % DICH_CHAIN_LAST_SIZE)
66 #define OP_CLASS_OFFSET_GET(x) (((x) >> EO_OP_CLASS_OFFSET) & 0xffff)
68 #define ID_CLASS_GET(id) ({ \
69 (Eo_Class *) ((id <= _eo_classes_last_id) && (id > 0)) ? \
70 (_eo_classes[id - 1]) : NULL; \
73 #define EO_ALIGN_SIZE(size) \
74 ((size) + (sizeof(void *) - ((size) % sizeof(void *))))
76 typedef struct _Dich_Chain1 Dich_Chain1;
91 const Eo_Class *klass;
93 } Eo_Extension_Data_Offset;
99 const Eo_Class *parent;
100 const Eo_Class_Description *desc;
101 Dich_Chain1 *chain; /**< The size is chain size */
105 const Eo_Class **extensions;
107 Eo_Extension_Data_Offset *extn_data_off;
108 size_t extn_data_size;
110 const Eo_Class **mro;
113 size_t data_offset; /* < Offset of the data within object data. */
115 Eina_Bool constructed : 1;
119 _dich_chain_alloc(Dich_Chain1 *chain1)
123 chain1->funcs = calloc(DICH_CHAIN_LAST_SIZE, sizeof(*(chain1->funcs)));
128 _dich_copy_all(Eo_Class *dst, const Eo_Class *src)
131 const Dich_Chain1 *sc1 = src->chain;
132 Dich_Chain1 *dc1 = dst->chain;
133 for (i = 0 ; i < src->chain_size ; i++, sc1++, dc1++)
139 _dich_chain_alloc(dc1);
141 const op_type_funcs *sf = sc1->funcs;
142 op_type_funcs *df = dc1->funcs;
143 for (j = 0 ; j < DICH_CHAIN_LAST_SIZE ; j++, df++, sf++)
147 memcpy(df, sf, sizeof(*df));
154 static inline const op_type_funcs *
155 _dich_func_get(const Eo_Class *klass, Eo_Op op)
157 size_t idx1 = DICH_CHAIN1(op);
158 if (EINA_UNLIKELY(idx1 >= klass->chain_size))
160 Dich_Chain1 *chain1 = &klass->chain[idx1];
161 if (EINA_UNLIKELY(!chain1->funcs))
163 return &chain1->funcs[DICH_CHAIN_LAST(op)];
167 _dich_func_set(Eo_Class *klass, Eo_Op op, eo_op_func_type func)
169 size_t idx1 = DICH_CHAIN1(op);
170 Dich_Chain1 *chain1 = &klass->chain[idx1];
171 _dich_chain_alloc(chain1);
172 if (chain1->funcs[DICH_CHAIN_LAST(op)].src == klass)
174 const Eo_Class *op_kls = _eo_op_class_get(op);
175 const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
176 ERR("Already set function for op %x (%s:%s). Overriding with func %p",
177 op, op_kls->desc->name, op_desc->name, func);
180 chain1->funcs[DICH_CHAIN_LAST(op)].func = func;
181 chain1->funcs[DICH_CHAIN_LAST(op)].src = klass;
185 _dich_func_clean_all(Eo_Class *klass)
188 Dich_Chain1 *chain1 = klass->chain;
190 for (i = 0 ; i < klass->chain_size ; i++, chain1++)
201 static const Eo_Op_Description noop_desc =
202 EO_OP_DESCRIPTION(EO_NOOP, "No operation.");
204 static const Eo_Class *
205 _eo_op_class_get(Eo_Op op)
207 /* FIXME: Make it fast. */
208 Eo_Class **itr = _eo_classes;
212 max = _eo_classes_last_id - 1;
215 mid = (min + max) / 2;
217 if (itr[mid]->base_id + itr[mid]->desc->ops.count < op)
219 else if (itr[mid]->base_id > op)
228 static const Eo_Op_Description *
229 _eo_op_id_desc_get(Eo_Op op)
231 const Eo_Class *klass;
236 klass = _eo_op_class_get(op);
240 Eo_Op sub_id = op - klass->base_id;
241 if (sub_id < klass->desc->ops.count)
242 return klass->desc->ops.descs + sub_id;
249 _eo_op_id_name_get(Eo_Op op)
251 const Eo_Op_Description *desc = _eo_op_id_desc_get(op);
252 return (desc) ? desc->name : NULL;
256 _eo_kls_itr_init(const Eo_Class *obj_klass, Eo_Kls_Itr *cur, Eo_Kls_Itr *prev_state)
258 memcpy(prev_state, cur, sizeof(*cur));
259 cur->kls = *obj_klass->mro;
263 _eo_kls_itr_end(Eo_Kls_Itr *cur, Eo_Kls_Itr *prev_state)
265 memcpy(cur, prev_state, sizeof(*cur));
268 static inline const Eo_Class *
269 _eo_kls_itr_get(Eo_Kls_Itr *cur)
275 _eo_kls_itr_set(Eo_Kls_Itr *cur, const Eo_Class *kls)
280 static inline const Eo_Class *
281 _eo_kls_itr_next(const Eo_Class *orig_kls, Eo_Kls_Itr *cur, Eo_Kls_Itr *prev_state, Eo_Op op)
283 const Eo_Class **kls_itr = NULL;
284 memcpy(prev_state, cur, sizeof(*cur));
286 /* Find the kls itr. */
287 kls_itr = orig_kls->mro;
288 while (*kls_itr && (*kls_itr != cur->kls))
296 const op_type_funcs *fsrc = _dich_func_get(*kls_itr, op);
297 if (!fsrc || !fsrc->func)
302 cur->kls = fsrc->src;
311 static inline const op_type_funcs *
312 _eo_kls_itr_func_get(Eo_Kls_Itr *mro_itr, Eo_Op op)
314 const Eo_Class *klass = _eo_kls_itr_get(mro_itr);
317 const op_type_funcs *func = _dich_func_get(klass, op);
319 if (func && func->func)
321 _eo_kls_itr_set(mro_itr, func->src);
326 _eo_kls_itr_set(mro_itr, NULL);
330 #define _EO_OP_ERR_NO_OP_PRINT(op, klass) \
333 const Eo_Class *op_klass = _eo_op_class_get(op); \
334 const char *_dom_name = (op_klass) ? op_klass->desc->name : NULL; \
335 ERR("Can't find func for op %x (%s:%s) for class '%s'. Aborting.", \
336 op, _dom_name, _eo_op_id_name_get(op), \
337 (klass) ? klass->desc->name : NULL); \
342 _eo_op_internal(Eo *obj, Eo_Op_Type op_type, Eo_Op op, va_list *p_list)
345 const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
349 if (op_desc->op_type == EO_OP_TYPE_CLASS)
351 ERR("Tried calling a class op '%s' (%x) from a non-class context.", (op_desc) ? op_desc->name : NULL, op);
358 const op_type_funcs *func =
359 _eo_kls_itr_func_get(&obj->mro_itr, op);
362 void *func_data =_eo_data_get(obj, func->src);
363 func->func(obj, func_data, p_list);
368 /* Try composite objects */
372 EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj)
374 /* FIXME: Clean this up a bit. */
375 Eo_Kls_Itr prev_state;
376 _eo_kls_itr_init(emb_obj->klass, &emb_obj->mro_itr, &prev_state);
377 if (_eo_op_internal(emb_obj, op_type, op, p_list))
379 _eo_kls_itr_end(&emb_obj->mro_itr, &prev_state);
382 _eo_kls_itr_end(&emb_obj->mro_itr, &prev_state);
388 static inline Eina_Bool
389 _eo_dov_internal(Eo *obj, Eo_Op_Type op_type, va_list p_list)
391 Eina_Bool prev_error;
392 Eina_Bool ret = EINA_TRUE;
394 Eo_Kls_Itr prev_state;
396 prev_error = obj->do_error;
399 op = va_arg(p_list, Eo_Op);
402 _eo_kls_itr_init(obj->klass, &obj->mro_itr, &prev_state);
403 if (!_eo_op_internal(obj, op_type, op, &p_list))
405 _EO_OP_ERR_NO_OP_PRINT(op, obj->klass);
407 _eo_kls_itr_end(&obj->mro_itr, &prev_state);
410 op = va_arg(p_list, Eo_Op);
411 _eo_kls_itr_end(&obj->mro_itr, &prev_state);
419 obj->do_error = prev_error;
425 eo_do_internal(Eo *obj, Eo_Op_Type op_type, ...)
427 Eina_Bool ret = EINA_TRUE;
430 EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
432 va_start(p_list, op_type);
434 ret = _eo_dov_internal(obj, op_type, p_list);
442 eo_do_super_internal(Eo *obj, Eo_Op_Type op_type, Eo_Op op, ...)
444 const Eo_Class *nklass;
445 Eina_Bool ret = EINA_TRUE;
447 Eo_Kls_Itr prev_state;
448 EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
450 /* Advance the kls itr. */
451 nklass = _eo_kls_itr_next(obj->klass, &obj->mro_itr, &prev_state, op);
453 va_start(p_list, op);
454 if (!_eo_op_internal(obj, op_type, op, &p_list))
456 _EO_OP_ERR_NO_OP_PRINT(op, nklass);
464 _eo_kls_itr_end(&obj->mro_itr, &prev_state);
469 _eo_class_op_internal(Eo_Class *klass, Eo_Op op, va_list *p_list)
472 const Eo_Op_Description *op_desc = _eo_op_id_desc_get(op);
476 if (op_desc->op_type != EO_OP_TYPE_CLASS)
478 ERR("Tried calling an instance op '%s' (%x) from a class context.", (op_desc) ? op_desc->name : NULL, op);
485 const op_type_funcs *func =
486 _eo_kls_itr_func_get(&klass->mro_itr, op);
489 ((eo_op_func_type_class) func->func)(klass, p_list);
498 eo_class_do_internal(const Eo_Class *klass, ...)
500 Eina_Bool ret = EINA_TRUE;
502 Eo_Kls_Itr prev_state;
505 EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
507 va_start(p_list, klass);
509 op = va_arg(p_list, Eo_Op);
512 _eo_kls_itr_init(klass, &((Eo_Class *) klass)->mro_itr, &prev_state);
513 if (!_eo_class_op_internal((Eo_Class *) klass, op, &p_list))
515 _EO_OP_ERR_NO_OP_PRINT(op, klass);
517 _eo_kls_itr_end(&((Eo_Class *) klass)->mro_itr, &prev_state);
520 _eo_kls_itr_end(&((Eo_Class *) klass)->mro_itr, &prev_state);
521 op = va_arg(p_list, Eo_Op);
530 eo_class_do_super_internal(const Eo_Class *klass, Eo_Op op, ...)
532 const Eo_Class *nklass;
533 Eina_Bool ret = EINA_TRUE;
535 Eo_Kls_Itr prev_state;
536 EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE);
538 /* Advance the kls itr. */
539 nklass = _eo_kls_itr_next(klass, &((Eo_Class *) klass)->mro_itr, &prev_state, op);
541 va_start(p_list, op);
542 if (!_eo_class_op_internal((Eo_Class *) klass, op, &p_list))
544 _EO_OP_ERR_NO_OP_PRINT(op, nklass);
549 _eo_kls_itr_end(&((Eo_Class *) klass)->mro_itr, &prev_state);
553 EAPI const Eo_Class *
554 eo_class_get(const Eo *obj)
556 EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
562 eo_class_name_get(const Eo_Class *klass)
564 EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, NULL);
566 return klass->desc->name;
570 _eo_class_base_op_init(Eo_Class *klass)
572 const Eo_Class_Description *desc = klass->desc;
574 klass->base_id = _eo_ops_last_id;
576 if (desc && desc->ops.base_op_id)
577 *(desc->ops.base_op_id) = klass->base_id;
579 _eo_ops_last_id += desc->ops.count + 1;
581 klass->chain_size = DICH_CHAIN1(_eo_ops_last_id) + 1;
582 klass->chain = calloc(klass->chain_size, sizeof(*klass->chain));
587 _eo_class_mro_has(const Eo_Class *klass, const Eo_Class *find)
589 const Eo_Class **itr;
590 for (itr = klass->mro ; *itr ; itr++)
602 _eo_class_mro_add(Eina_List *mro, const Eo_Class *klass)
604 Eina_List *extn_pos = NULL;
605 Eina_Bool check_consistency = !mro;
609 mro = eina_list_append(mro, klass);
611 /* ONLY ADD MIXINS! */
613 /* Recursively add extenions. */
615 const Eo_Class **extn_itr;
617 for (extn_itr = klass->extensions ; *extn_itr ; extn_itr++)
619 const Eo_Class *extn = *extn_itr;
620 if (extn->desc->type != EO_CLASS_TYPE_MIXIN)
623 mro = _eo_class_mro_add(mro, extn);
624 /* Not possible: if (!mro) return NULL; */
626 if (check_consistency)
628 extn_pos = eina_list_append(extn_pos, eina_list_last(mro));
633 /* Check if we can create a consistent mro. We only do it for the class
634 * we are working on (i.e no parents). */
635 if (check_consistency)
637 const Eo_Class **extn_itr;
639 Eina_List *itr = extn_pos;
640 for (extn_itr = klass->extensions ; *extn_itr ; extn_itr++)
642 const Eo_Class *extn = *extn_itr;
643 if (extn->desc->type != EO_CLASS_TYPE_MIXIN)
646 /* Get the first one after the extension. */
647 Eina_List *extn_list = eina_list_next(eina_list_data_get(itr));
649 /* If we found the extension again. */
650 if (eina_list_data_find_list(extn_list, extn))
653 ERR("Cannot create a consistent method resolution order for class '%s' because of '%s'.", klass->desc->name, extn->desc->name);
657 itr = eina_list_next(itr);
662 mro = _eo_class_mro_add(mro, klass->parent);
668 _eo_class_mro_init(Eo_Class *klass)
670 Eina_List *mro = NULL;
672 DBG("Started creating MRO for class '%s'", klass->desc->name);
673 mro = _eo_class_mro_add(mro, klass);
678 /* Remove duplicates and make them the right order. */
680 Eina_List *itr1, *itr2, *itr2n;
682 itr1 = eina_list_last(mro);
685 itr2 = eina_list_prev(itr1);
689 itr2n = eina_list_prev(itr2);
691 if (eina_list_data_get(itr1) == eina_list_data_get(itr2))
693 mro = eina_list_remove_list(mro, itr2);
699 itr1 = eina_list_prev(itr1);
703 /* Copy the mro and free the list. */
705 const Eo_Class *kls_itr;
706 const Eo_Class **mro_itr;
707 klass->mro = calloc(sizeof(*klass->mro), eina_list_count(mro) + 1);
709 mro_itr = klass->mro;
711 EINA_LIST_FREE(mro, kls_itr)
713 *(mro_itr++) = kls_itr;
715 DBG("Added '%s' to MRO", kls_itr->desc->name);
720 DBG("Finished creating MRO for class '%s'", klass->desc->name);
726 _eo_class_constructor(Eo_Class *klass)
728 if (klass->constructed)
731 klass->constructed = EINA_TRUE;
733 if (klass->desc->class_constructor)
734 klass->desc->class_constructor(klass);
738 eo_class_funcs_set(Eo_Class *klass, const Eo_Op_Func_Description *func_descs)
740 EO_MAGIC_RETURN(klass, EO_CLASS_EINA_MAGIC);
742 const Eo_Op_Func_Description *itr;
746 for ( ; itr->op_type != EO_OP_TYPE_INVALID ; itr++)
748 const Eo_Op_Description *op_desc = _eo_op_id_desc_get(itr->op);
750 if (EINA_UNLIKELY(!op_desc || (itr->op == EO_NOOP)))
752 ERR("Setting implementation for non-existent op %x for class '%s'. Func index: %d", itr->op, klass->desc->name, itr - func_descs);
754 else if (EINA_LIKELY(itr->op_type == op_desc->op_type))
756 _dich_func_set(klass, itr->op, itr->func);
760 ERR("Set function's op type (%x) is different than the one in the op description (%d) for op '%s:%s'. Func index: %d",
762 (op_desc) ? op_desc->op_type : EO_OP_TYPE_REGULAR,
764 (op_desc) ? op_desc->name : NULL,
772 eo_class_free(Eo_Class *klass)
774 if (klass->constructed)
776 if (klass->desc->class_destructor)
777 klass->desc->class_destructor(klass);
779 _dich_func_clean_all(klass);
782 free(klass->extensions);
787 if (klass->extn_data_off)
788 free(klass->extn_data_off);
795 _eo_class_check_op_descs(const Eo_Class *klass)
797 const Eo_Class_Description *desc = klass->desc;
798 const Eo_Op_Description *itr;
801 if (desc->ops.count > 0)
803 if (!desc->ops.base_op_id)
805 ERR("Class '%s' has a non-zero ops count, but base_id is NULL.",
810 if (!desc->ops.descs)
812 ERR("Class '%s' has a non-zero ops count, but there are no descs.",
818 itr = desc->ops.descs;
819 for (i = 0 ; i < desc->ops.count ; i++, itr++)
821 if (itr->sub_op != i)
825 ERR("Wrong order in Ops description for class '%s'. Expected %x and got %x", desc->name, i, itr->sub_op);
829 ERR("Found too few Ops description for class '%s'. Expected %x descriptions, but found %x.", desc->name, desc->ops.count, i);
835 if (itr && itr->name)
837 ERR("Found extra Ops description for class '%s'. Expected %d descriptions, but found more.", desc->name, desc->ops.count);
844 /* Not really called, just used for the ptr... */
846 _eo_class_isa_func(Eo *obj EINA_UNUSED, void *class_data EINA_UNUSED, va_list *list EINA_UNUSED)
851 EAPI const Eo_Class *
852 eo_class_new(const Eo_Class_Description *desc, const Eo_Class *parent, ...)
857 if (parent && !EINA_MAGIC_CHECK(parent, EO_CLASS_EINA_MAGIC))
859 EINA_MAGIC_FAIL(parent, EO_CLASS_EINA_MAGIC);
863 va_start(p_list, parent);
865 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
866 EINA_SAFETY_ON_NULL_RETURN_VAL(desc->name, NULL);
868 /* Check restrictions on Interface types. */
869 if (desc->type == EO_CLASS_TYPE_INTERFACE)
871 EINA_SAFETY_ON_FALSE_RETURN_VAL(!desc->data_size, NULL);
874 klass = calloc(1, sizeof(Eo_Class));
875 klass->parent = parent;
877 /* Handle class extensions */
879 Eina_List *extn_list = NULL;
880 const Eo_Class *extn = NULL;
881 const Eo_Class **extn_itr = NULL;
883 extn = va_arg(p_list, Eo_Class *);
886 switch (extn->desc->type)
888 case EO_CLASS_TYPE_REGULAR:
889 case EO_CLASS_TYPE_REGULAR_NO_INSTANT:
890 case EO_CLASS_TYPE_INTERFACE:
891 case EO_CLASS_TYPE_MIXIN:
892 extn_list = eina_list_append(extn_list, extn);
896 extn = va_arg(p_list, Eo_Class *);
899 klass->extensions = calloc(sizeof(*klass->extensions),
900 eina_list_count(extn_list) + 1);
902 extn_itr = klass->extensions;
903 EINA_LIST_FREE(extn_list, extn)
905 *(extn_itr++) = extn;
911 /* Handle the inheritance */
914 /* Verify the inheritance is allowed. */
915 switch (klass->desc->type)
917 case EO_CLASS_TYPE_REGULAR:
918 case EO_CLASS_TYPE_REGULAR_NO_INSTANT:
919 if ((klass->parent->desc->type != EO_CLASS_TYPE_REGULAR) &&
920 (klass->parent->desc->type != EO_CLASS_TYPE_REGULAR_NO_INSTANT))
922 ERR("Regular classes ('%s') aren't allowed to inherit from non-regular classes ('%s').", klass->desc->name, klass->parent->desc->name);
926 case EO_CLASS_TYPE_INTERFACE:
927 case EO_CLASS_TYPE_MIXIN:
928 if ((klass->parent->desc->type != EO_CLASS_TYPE_INTERFACE) &&
929 (klass->parent->desc->type != EO_CLASS_TYPE_MIXIN))
931 ERR("Non-regular classes ('%s') aren't allowed to inherit from regular classes ('%s').", klass->desc->name, klass->parent->desc->name);
938 /* Update the current offset. */
939 /* FIXME: Make sure this alignment is enough. */
940 klass->data_offset = klass->parent->data_offset +
941 EO_ALIGN_SIZE(klass->parent->desc->data_size);
944 if (!_eo_class_check_op_descs(klass))
949 if (!_eo_class_mro_init(klass))
954 /* create MIXIN offset table. */
956 const Eo_Class **mro_itr = klass->mro;
957 Eo_Extension_Data_Offset *extn_data_itr;
959 size_t extn_data_off = klass->data_offset +
960 EO_ALIGN_SIZE(klass->desc->data_size);
962 /* FIXME: Make faster... */
965 if (((*mro_itr)->desc->type == EO_CLASS_TYPE_MIXIN) &&
966 ((*mro_itr)->desc->data_size > 0))
973 klass->extn_data_off = calloc(extn_num + 1,
974 sizeof(*klass->extn_data_off));
976 extn_data_itr = klass->extn_data_off;
977 mro_itr = klass->mro;
980 if (((*mro_itr)->desc->type == EO_CLASS_TYPE_MIXIN) &&
981 ((*mro_itr)->desc->data_size > 0))
983 extn_data_itr->klass = *mro_itr;
984 extn_data_itr->offset = extn_data_off;
986 extn_data_off += EO_ALIGN_SIZE(extn_data_itr->klass->desc->data_size);
992 klass->extn_data_size = extn_data_off;
995 eina_lock_take(&_eo_class_creation_lock);
997 klass->class_id = ++_eo_classes_last_id;
1000 /* FIXME: Handle errors. */
1001 size_t arrsize = _eo_classes_last_id * sizeof(*_eo_classes);
1003 tmp = realloc(_eo_classes, arrsize);
1005 /* If it's the first allocation, memset. */
1007 memset(tmp, 0, arrsize);
1010 _eo_classes[klass->class_id - 1] = klass;
1012 eina_lock_release(&_eo_class_creation_lock);
1014 EINA_MAGIC_SET(klass, EO_CLASS_EINA_MAGIC);
1016 _eo_class_base_op_init(klass);
1017 /* Flatten the function array */
1019 const Eo_Class **mro_itr = klass->mro;
1020 for ( ; *mro_itr ; mro_itr++)
1023 /* Skip ourselves. */
1024 for ( mro_itr-- ; mro_itr > klass->mro ; mro_itr--)
1026 _dich_copy_all(klass, *mro_itr);
1030 /* Mark which classes we implement */
1032 const Eo_Class **extn_itr;
1034 for (extn_itr = klass->extensions ; *extn_itr ; extn_itr++)
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);
1042 _dich_func_set(klass, klass->base_id + klass->desc->ops.count,
1043 _eo_class_isa_func);
1047 _dich_func_set(klass,
1048 klass->parent->base_id + klass->parent->desc->ops.count,
1049 _eo_class_isa_func);
1053 _eo_class_constructor(klass);
1060 eo_class_free(klass);
1065 eo_isa(const Eo *obj, const Eo_Class *klass)
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);
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));
1078 eo_parent_set(Eo *obj, const Eo *parent)
1080 EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
1082 EO_MAGIC_RETURN_VAL(parent, EO_EINA_MAGIC, EINA_FALSE);
1084 if (obj->parent == parent)
1089 if (eo_composite_is(obj))
1091 eo_composite_detach(obj, obj->parent);
1096 obj->parent->children =
1097 eina_inlist_remove(obj->parent->children, EINA_INLIST_GET(obj));
1098 eo_xunref(obj, obj->parent);
1101 obj->parent = (Eo *) parent;
1104 obj->parent->children =
1105 eina_inlist_append(obj->parent->children, EINA_INLIST_GET(obj));
1106 eo_xref(obj, obj->parent);
1115 eo_add_internal(const Eo_Class *klass, Eo *parent, ...)
1118 EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, NULL);
1120 if (parent) EO_MAGIC_RETURN_VAL(parent, EO_EINA_MAGIC, NULL);
1122 if (EINA_UNLIKELY(klass->desc->type != EO_CLASS_TYPE_REGULAR))
1124 ERR("Class '%s' is not instantiate-able. Aborting.", klass->desc->name);
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);
1135 eo_parent_set(obj, parent);
1137 _eo_condtor_reset(obj);
1141 /* Run the relevant do stuff. */
1144 va_start(p_list, parent);
1145 do_err = !_eo_dov_internal(obj, EO_OP_TYPE_REGULAR, p_list);
1149 if (EINA_UNLIKELY(do_err))
1151 ERR("Object of class '%s' - One of the object constructors have failed.", klass->desc->name);
1155 if (!obj->condtor_done)
1157 ERR("Object of class '%s' - Not all of the object constructors have been executed.", klass->desc->name);
1166 /* Unref twice, once for the ref above, and once for the basic object ref. */
1181 eo_xref_internal(Eo *obj, const Eo *ref_obj, const char *file, int line)
1183 EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, obj);
1188 Eo_Xref_Node *xref = calloc(1, sizeof(*xref));
1189 xref->ref_obj = ref_obj;
1193 obj->xrefs = eina_inlist_prepend(obj->xrefs, EINA_INLIST_GET(xref));
1204 eo_xunref(Eo *obj, const Eo *ref_obj)
1206 EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1208 Eo_Xref_Node *xref = NULL;
1209 EINA_INLIST_FOREACH(obj->xrefs, xref)
1211 if (xref->ref_obj == ref_obj)
1217 obj->xrefs = eina_inlist_remove(obj->xrefs, EINA_INLIST_GET(xref));
1222 ERR("ref_obj (%p) does not reference obj (%p). Aborting unref.", ref_obj, obj);
1239 eo_ref(const Eo *_obj)
1241 Eo *obj = (Eo *) _obj;
1242 EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, obj);
1244 return _eo_ref(obj);
1248 _eo_del_internal(Eo *obj)
1251 /* We need that for the event callbacks that may ref/unref. */
1254 eo_do(obj, eo_event_callback_call(EO_EV_DEL, NULL, NULL));
1256 const Eo_Class *klass = eo_class_get(obj);
1258 _eo_condtor_reset(obj);
1260 do_err = eo_do(obj, eo_destructor());
1261 if (EINA_UNLIKELY(!do_err))
1263 ERR("Object of class '%s' - One of the object destructors have failed.", klass->desc->name);
1266 if (!obj->condtor_done)
1268 ERR("Object of class '%s' - Not all of the object destructors have been executed.", klass->desc->name);
1270 /*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */
1273 Eina_List *itr, *itr_n;
1275 EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)
1277 eo_composite_detach(emb_obj, obj);
1281 while (obj->children)
1283 eo_parent_set(EINA_INLIST_CONTAINER_GET(obj->children, Eo), NULL);
1286 obj->del = EINA_TRUE;
1293 EINA_MAGIC_SET(obj, EO_FREED_EINA_MAGIC);
1301 if (obj->refcount == 0)
1305 ERR("Object %p already deleted.", obj);
1309 _eo_del_internal(obj);
1312 /* If for some reason it's not empty, clear it. */
1315 ERR("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.");
1316 Eina_Inlist *nitr = obj->xrefs->next;
1317 free(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node));
1322 if (!obj->manual_free)
1325 _eo_ref(obj); /* If we manual free, we keep a phantom ref. */
1327 else if (obj->refcount < 0)
1329 ERR("Obj:%p. Refcount (%d) < 0. Too many unrefs.", obj, obj->refcount);
1335 eo_unref(const Eo *_obj)
1337 Eo *obj = (Eo *) _obj;
1338 EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1344 eo_del(const Eo *obj)
1346 eo_parent_set((Eo *) obj, NULL);
1351 eo_ref_get(const Eo *obj)
1353 EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, 0);
1355 return obj->refcount;
1359 eo_parent_get(const Eo *obj)
1361 EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, NULL);
1367 eo_error_set_internal(const Eo *obj, const char *file, int line)
1369 EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1371 ERR("Error with obj '%p' at %s:%d", obj, file, line);
1373 ((Eo *) obj)->do_error = EINA_TRUE;
1377 _eo_condtor_done(Eo *obj)
1379 if (obj->condtor_done)
1381 ERR("Object %p is already constructed at this point.", obj);
1385 obj->condtor_done = EINA_TRUE;
1389 _eo_condtor_reset(Eo *obj)
1391 obj->condtor_done = EINA_FALSE;
1394 static inline void *
1395 _eo_data_get(const Eo *obj, const Eo_Class *klass)
1397 if (EINA_LIKELY(klass->desc->data_size > 0))
1399 if (EINA_UNLIKELY(klass->desc->type == EO_CLASS_TYPE_MIXIN))
1401 Eo_Extension_Data_Offset *doff_itr =
1402 eo_class_get(obj)->extn_data_off;
1407 while (doff_itr->klass)
1409 if (doff_itr->klass == klass)
1410 return ((char *) obj) + EO_ALIGN_SIZE(sizeof(*obj)) +
1417 return ((char *) obj) + EO_ALIGN_SIZE(sizeof(*obj)) +
1426 eo_data_get(const Eo *obj, const Eo_Class *klass)
1429 EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, NULL);
1430 EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, NULL);
1433 if (!_eo_class_mro_has(obj->klass, klass))
1435 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);
1440 ret = _eo_data_get(obj, klass);
1443 if (!ret && (klass->desc->data_size == 0))
1445 ERR("Tried getting data of class '%s', but it has none..", klass->desc->name);
1455 const char *log_dom = "eo";
1456 if (_eo_init_count++ > 0)
1462 _eo_classes_last_id = EO_CLASS_IDS_FIRST - 1;
1463 _eo_ops_last_id = EO_OP_IDS_FIRST;
1464 _eo_log_dom = eina_log_domain_register(log_dom, EINA_COLOR_LIGHTBLUE);
1465 if (_eo_log_dom < 0)
1467 EINA_LOG_ERR("Could not register log domain: %s", log_dom);
1471 if (!eina_lock_new(&_eo_class_creation_lock))
1473 EINA_LOG_ERR("Could not init lock.");
1477 eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR);
1478 eina_magic_string_static_set(EO_FREED_EINA_MAGIC,
1479 EO_FREED_EINA_MAGIC_STR);
1480 eina_magic_string_static_set(EO_CLASS_EINA_MAGIC,
1481 EO_CLASS_EINA_MAGIC_STR);
1484 /* Call it just for coverage purposes. Ugly I know, but I like it better than
1485 * casting everywhere else. */
1486 _eo_class_isa_func(NULL, NULL, NULL);
1496 Eo_Class **cls_itr = _eo_classes;
1498 if (--_eo_init_count > 0)
1501 for (i = 0 ; i < _eo_classes_last_id ; i++, cls_itr++)
1504 eo_class_free(*cls_itr);
1510 eina_lock_free(&_eo_class_creation_lock);
1512 eina_log_domain_unregister(_eo_log_dom);
1520 eo_composite_attach(Eo *comp_obj, Eo *parent)
1522 EO_MAGIC_RETURN(comp_obj, EO_EINA_MAGIC);
1523 EO_MAGIC_RETURN(parent, EO_EINA_MAGIC);
1525 comp_obj->composite = EINA_TRUE;
1526 eo_parent_set(comp_obj, parent);
1527 parent->composite_objects = eina_list_prepend(parent->composite_objects, comp_obj);
1531 eo_composite_detach(Eo *comp_obj, Eo *parent)
1533 EO_MAGIC_RETURN(comp_obj, EO_EINA_MAGIC);
1534 EO_MAGIC_RETURN(parent, EO_EINA_MAGIC);
1536 comp_obj->composite = EINA_FALSE;
1537 parent->composite_objects = eina_list_remove(parent->composite_objects, comp_obj);
1538 eo_parent_set(comp_obj, NULL);
1542 eo_composite_is(const Eo *comp_obj)
1544 EO_MAGIC_RETURN_VAL(comp_obj, EO_EINA_MAGIC, EINA_FALSE);
1546 return comp_obj->composite;
1550 eo_destructed_is(const Eo *obj)
1552 EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
1558 eo_manual_free_set(Eo *obj, Eina_Bool manual_free)
1560 EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1561 obj->manual_free = manual_free;
1565 eo_manual_free(Eo *obj)
1567 EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
1569 if (EINA_FALSE == obj->manual_free)
1571 ERR("Tried to manually free the object %p while the option has not been set; see eo_manual_free_set for more information.", obj);
1577 ERR("Tried deleting the object %p while still referenced(%d).", obj, eo_ref_get(obj));