diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index 9724663beb..6e05e63a40 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -615,13 +615,15 @@ EAPI Eina_Bool eo_shutdown(void); // to fetch internal function and object data at once typedef struct _Eo2_Op_Call_Data { - Eo *obj_id; - void *func; - void *data; + Eo *obj_id; + Eo_Class *klass_id; + void *func; + void *data; } Eo2_Op_Call_Data; // to pass the internal function call to EO2_FUNC_BODY (as Func parameter) #define EO2_FUNC_CALL(...) _func_(call.obj_id, call.data, __VA_ARGS__) +#define EO2_CLASS_FUNC_CALL(...) _func_(call.klass_id, __VA_ARGS__) // cache OP id, get real fct and object data then do the call #define _EO2_FUNC_COMMON(Name, Ret, Func, DefRet) \ @@ -632,6 +634,14 @@ typedef struct _Eo2_Op_Call_Data __##Name##_func _func_ = (__##Name##_func) call.func; \ return Func; \ +#define _EO2_CLASS_FUNC_COMMON(Name, Ret, Func, DefRet, Class) \ + static Eo_Op op = EO_NOOP; \ + if ( op == EO_NOOP ) op = eo2_api_op_id_get((void*)Name, Class); \ + Eo2_Op_Call_Data call; \ + if (!eo2_call_resolve(op, &call)) return DefRet; \ + __##Name##_func _func_ = (__##Name##_func) call.func; \ + return Func; \ + // to define an EAPI function #define EO2_FUNC_BODY(Name, Ret, DefRet) \ Ret \ @@ -653,6 +663,27 @@ typedef struct _Eo2_Op_Call_Data #define EO2_VOID_FUNC_BODYV(Name, Func, ...) EO2_FUNC_BODYV(Name, void, Func, , __VA_ARGS__) +// to define a EAPI class function +#define EO2_CLASS_FUNC_BODY(Name, Ret, DefRet, Class) \ + Ret \ + Name(void) \ + { \ + typedef Ret (*__##Name##_func)(Eo_Class *); \ + _EO2_CLASS_FUNC_COMMON(Name, Ret, _func_(call.klass_id), DefRet, Class) \ + } + +#define EO2_VOID_CLASS_FUNC_BODY(Name, Class) EO2_CLASS_FUNC_BODY(Name, void, , Class) + +#define EO2_CLASS_FUNC_BODYV(Name, Ret, Func, DefRet, Class, ...) \ + Ret \ + Name(__VA_ARGS__) \ + { \ + typedef Ret (*__##Name##_func)(Eo_Class *, __VA_ARGS__); \ + _EO2_CLASS_FUNC_COMMON(Name, Ret, Func, DefRet, Class) \ + } + +#define EO2_VOID_CLASS_FUNC_BODYV(Name, Func, Class, ...) EO2_CLASS_FUNC_BODYV(Name, void, Func, , Class, __VA_ARGS__) + // OP ID of an overriding function #define EO2_OP_OVERRIDE ((Eo_Op) -1) #define EO2_OP_VIRTUAL ((Eo_Op) -2) @@ -660,6 +691,7 @@ typedef struct _Eo2_Op_Call_Data #define EO2_OP_FUNC(_private, _api, _doc) {_private, _api, EO_NOOP, EO_OP_TYPE_REGULAR, _doc} #define EO2_OP_CLASS_FUNC(_private, _api, _doc) {_private, _api, EO_NOOP, EO_OP_TYPE_CLASS, _doc} #define EO2_OP_FUNC_OVERRIDE(_private, _api) {_private, _api, EO2_OP_OVERRIDE, EO_OP_TYPE_REGULAR, NULL} +#define EO2_OP_CLASS_FUNC_OVERRIDE(_private, _api) {_private, _api, EO2_OP_OVERRIDE, EO_OP_TYPE_CLASS, NULL} #define EO2_OP_FUNC_VIRTUAL(_api, _doc) {NULL, _api, EO2_OP_VIRTUAL, EO_OP_TYPE_REGULAR, _doc} #define EO2_OP_SENTINEL { NULL, NULL, 0, EO_OP_TYPE_INVALID, NULL} @@ -672,13 +704,16 @@ EAPI Eina_Bool eo2_call_resolve_internal(const Eo_Class *klass, Eo_Op op, Eo2_Op // start of eo2_do barrier, gets the object pointer and ref it, put it on the stask EAPI Eina_Bool eo2_do_start(Eo *obj_id, Eina_Bool do_super); +EAPI Eina_Bool eo2_class_do_start(const Eo_Class *klass_id, Eina_Bool do_super); // end of the eo2_do barrier, unref the obj, move the stack pointer EAPI void eo2_do_end(Eo **ojb); +EAPI void eo2_class_do_end(const Eo_Class **klass); EAPI int eo2_call_stack_depth(); #define EO2_DO_CLEANUP __attribute__((cleanup(eo2_do_end))) +#define EO2_CLASS_DO_CLEANUP __attribute__((cleanup(eo2_class_do_end))) // eo object method calls batch, #define eo2_do(objid, ...) \ @@ -705,11 +740,28 @@ EAPI int eo2_call_stack_depth(); } \ } while (0) -// FIXME -#define eo2_class_do(clsid, ...) \ - do \ - { \ - do { __VA_ARGS__ ; } while (0); \ +#define eo2_class_do(clsid, ...) \ + do \ + { \ + const Eo_Class *_clsid_ = clsid; \ + if (eo2_class_do_start(_clsid_, EINA_FALSE)) \ + { \ + const Eo_Class *_id_clean_ EO2_CLASS_DO_CLEANUP = _clsid_; \ + __VA_ARGS__; \ + (void) _id_clean_; \ + } \ + } while (0) + +#define eo2_class_super_do(clsid, ...) \ + do \ + { \ + const Eo_Class *_clsid_ = clsid; \ + if (eo2_class_do_start(_clsid_, EINA_TRUE)) \ + { \ + const Eo_Class *_id_clean_ EO2_CLASS_DO_CLEANUP = _clsid_; \ + __VA_ARGS__; \ + (void) _id_clean_; \ + } \ } while (0) /*****************************************************************************/ diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index 79523f9f0d..33485a5eb9 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -280,7 +280,7 @@ typedef struct _Eo2_Stack_Frame { Eo *obj_id; _Eo *obj; - const _Eo_Class *cur_klass; + const _Eo_Class *klass; void *obj_data; } Eo2_Stack_Frame; @@ -311,7 +311,7 @@ EAPI Eina_Bool eo2_do_start(Eo *obj_id, Eina_Bool do_super) { _Eo * obj; - const _Eo_Class *cur_klass; + const _Eo_Class *klass; Eo2_Stack_Frame *fptr; fptr = eo2_call_stack.frame_ptr; @@ -319,9 +319,9 @@ eo2_do_start(Eo *obj_id, Eina_Bool do_super) { obj = fptr->obj; if (do_super) - cur_klass = _eo2_kls_itr_next(obj->klass, fptr->cur_klass); + klass = _eo2_kls_itr_next(obj->klass, fptr->klass); else - cur_klass = fptr->cur_klass; + klass = fptr->klass; eo2_call_stack.frame_ptr++; } else @@ -329,9 +329,9 @@ eo2_do_start(Eo *obj_id, Eina_Bool do_super) obj = _eo_obj_pointer_get((Eo_Id)obj_id); if (!obj) return EINA_FALSE; if (do_super) - cur_klass = _eo2_kls_itr_next(obj->klass, obj->klass); + klass = _eo2_kls_itr_next(obj->klass, obj->klass); else - cur_klass = obj->klass; + klass = obj->klass; if (fptr == NULL) eo2_call_stack.frame_ptr = &eo2_call_stack.stack[0]; else @@ -347,24 +347,65 @@ eo2_do_start(Eo *obj_id, Eina_Bool do_super) fptr->obj = obj; fptr->obj_id = obj_id; - fptr->cur_klass = cur_klass; + fptr->klass = klass; fptr->obj_data = EO2_INVALID_DATA; return EINA_TRUE; } -EAPI void -eo2_do_end(Eo **objid EINA_UNUSED) +EAPI Eina_Bool +eo2_class_do_start(const Eo_Class *klass_id, Eina_Bool do_super EINA_UNUSED) +{ + Eo2_Stack_Frame *fptr; + const _Eo_Class *klass; + + fptr = eo2_call_stack.frame_ptr; + if ((fptr != NULL) && (fptr->klass->class_id == (Eo_Class_Id) klass_id)) + { + if (do_super) + klass = _eo2_kls_itr_next(fptr->klass, fptr->klass); + else + klass = fptr->klass; + eo2_call_stack.frame_ptr++; + } + else + { + klass = _eo_class_pointer_get(klass_id); + EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE); + if (do_super) + klass = _eo2_kls_itr_next(klass, klass); + if (fptr == NULL) + eo2_call_stack.frame_ptr = &eo2_call_stack.stack[0]; + else + eo2_call_stack.frame_ptr++; + } + + fptr = eo2_call_stack.frame_ptr; + + if ((fptr - eo2_call_stack.stack) >= EO2_CALL_STACK_DEPTH) + ERR("eo2 call stack overflow !!!"); + + fptr->obj = NULL; + fptr->obj_id = NULL; + fptr->klass = klass; + fptr->obj_data = EO2_INVALID_DATA; + + return EINA_TRUE; +} + +static inline void +_eo2_do_end(Eina_Bool obj_do) { Eo2_Stack_Frame *fptr; fptr = eo2_call_stack.frame_ptr; - _eo_unref(fptr->obj); + if(obj_do) + _eo_unref(fptr->obj); fptr->obj = NULL; fptr->obj_id = NULL; - fptr->cur_klass = NULL; + fptr->klass = NULL; fptr->obj_data = EO2_INVALID_DATA; if (fptr == &eo2_call_stack.stack[0]) @@ -373,6 +414,18 @@ eo2_do_end(Eo **objid EINA_UNUSED) eo2_call_stack.frame_ptr--; } +EAPI void +eo2_do_end(Eo **obj_id EINA_UNUSED) +{ + _eo2_do_end(EINA_TRUE); +} + +EAPI void +eo2_class_do_end(const Eo_Class **klass_id EINA_UNUSED) +{ + _eo2_do_end(EINA_FALSE); +} + EAPI Eina_Bool eo2_call_resolve_internal(const Eo_Class *klass_id, Eo_Op op, Eo2_Op_Call_Data *call) { @@ -385,12 +438,17 @@ eo2_call_resolve_internal(const Eo_Class *klass_id, Eo_Op op, Eo2_Op_Call_Data * obj = fptr->obj; if (klass_id) - klass = _eo_class_pointer_get(klass_id); + { + klass = _eo_class_pointer_get(klass_id); + EO_MAGIC_RETURN_VAL(klass, EO_CLASS_EINA_MAGIC, EINA_FALSE); + } else - klass = fptr->cur_klass; + { + klass = fptr->klass; + if (!klass) + return EINA_FALSE; + } - if (!klass) - return EINA_FALSE; func = _dich_func_get(klass, op); if (EINA_LIKELY(func != NULL)) @@ -400,18 +458,24 @@ eo2_call_resolve_internal(const Eo_Class *klass_id, Eo_Op op, Eo2_Op_Call_Data * ERR("you called a pure virtual func"); return EINA_FALSE; } + call->klass_id = (Eo_Class *) klass->class_id; call->obj_id = fptr->obj_id; call->func = func->func; - if (func->src == obj->klass) + if (obj) { - if (fptr->obj_data == EO2_INVALID_DATA) - fptr->obj_data = _eo_data_scope_get(obj, func->src); + if (func->src == obj->klass) + { + if (fptr->obj_data == EO2_INVALID_DATA) + fptr->obj_data = _eo_data_scope_get(obj, func->src); - call->data = fptr->obj_data; + call->data = fptr->obj_data; + } + else + call->data = _eo_data_scope_get(obj, func->src); } else - call->data = _eo_data_scope_get(obj, func->src); + call->data = NULL; return EINA_TRUE; } @@ -497,6 +561,7 @@ _eo2_class_funcs_set(_Eo_Class *klass) qsort((void*)op_descs, klass->desc->ops.count, sizeof(Eo2_Op_Description), eo2_api_funcs_cmp); op_id = klass->base_id; + /* printf("elaborate class '%s' \n", klass->desc->name); */ for (op_desc = op_descs; op_desc->op_type != EO_OP_TYPE_INVALID; op_desc++) { if(op_desc->api_func == NULL) @@ -534,7 +599,7 @@ _eo2_class_funcs_set(_Eo_Class *klass) klass->desc->name, (unsigned long) (op_desc - op_descs)); } - /* printf("%d %p %p %s\n", op_desc->op, op_desc->api_func, op_desc->func, op_desc->doc); */ + /* printf(" %d %p %p %s\n", op_desc->op, op_desc->api_func, op_desc->func, op_desc->doc); */ _dich_func_set(klass, op_desc->op, op_desc->func); } }