diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index e5fa687eee..457e3ca6ad 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -614,48 +614,40 @@ EAPI Eina_Bool eo_shutdown(void); EAPI void eo2_class_funcs_set(Eo_Class *klass_id); -// opaque type used to pass object pointer to EAPI calls -typedef struct _Eo_Internal _Eo; - // to fetch internal function and object data at once typedef struct _Eo2_Op_Call_Data { - void *func; - void *data; + Eo *obj_id; + void *func; + void *data; } Eo2_Op_Call_Data; -// EAPI function declaration first argument -#define eo2_a _Eo *obj, Eo *objid -// EAPI function call first argument -#define eo2_o _obj_, _objid_ - // to pass the internal function call to EO2_FUNC_BODY (as Func parameter) -#define EO2_FUNC_CALL(...) _func_(objid, call.data, __VA_ARGS__) +#define EO2_FUNC_CALL(...) _func_(call.obj_id, call.data, __VA_ARGS__) // cache OP id, get real fct and object data then do the call #define _EO2_FUNC_COMMON(Name, Ret, Func, DefRet) \ static Eo_Op op = EO_NOOP; \ - if ( op == EO_NOOP ) op = eo2_get_op_id(obj, (void*)Name); \ + if ( op == EO_NOOP ) op = eo2_get_op_id((void*)Name); \ Eo2_Op_Call_Data call; \ - if (!eo2_call_resolve(obj, op, &call)) return DefRet; \ + if (!eo2_call_resolve(op, &call)) return DefRet; \ __##Name##_func _func_ = (__##Name##_func) call.func; \ return Func; \ -/* XXX: Essential, because we need to adjust objid for comp objects. */ // to define an EAPI function #define EO2_FUNC_BODY(Name, Ret, DefRet) \ Ret \ - Name(_Eo *obj, Eo *objid) \ + Name() \ { \ typedef Ret (*__##Name##_func)(Eo *, void *obj_data); \ - _EO2_FUNC_COMMON(Name, Ret, _func_(objid, call.data), DefRet) \ + _EO2_FUNC_COMMON(Name, Ret, _func_(call.obj_id, call.data), DefRet)\ } #define EO2_VOID_FUNC_BODY(Name) EO2_FUNC_BODY(Name, void, ) #define EO2_FUNC_BODYV(Name, Ret, Func, DefRet, ...) \ Ret \ - Name(_Eo *obj, Eo *objid, __VA_ARGS__) \ + Name(__VA_ARGS__) \ { \ typedef Ret (*__##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \ _EO2_FUNC_COMMON(Name, Ret, Func, DefRet) \ @@ -670,21 +662,17 @@ typedef struct _Eo2_Op_Call_Data #define EO2_OP_SENTINEL { NULL, NULL, 0, EO_OP_TYPE_INVALID, NULL} // returns the OP id corresponding to the given api_func -EAPI Eo_Op eo2_get_op_id(_Eo *obj, void *api_func); +EAPI Eo_Op eo2_get_op_id(void *api_func); // gets the real function pointer and the object data -#define eo2_call_resolve(obj_id, op, call) eo2_call_resolve_internal(obj_id, NULL, op, call) -EAPI Eina_Bool eo2_call_resolve_internal(_Eo *obj, const Eo_Class *klass, Eo_Op op, Eo2_Op_Call_Data *call); +#define eo2_call_resolve(op, call) eo2_call_resolve_internal(NULL, op, call) +EAPI Eina_Bool eo2_call_resolve_internal(const Eo_Class *klass, Eo_Op op, Eo2_Op_Call_Data *call); -// start of eo2_do barrier, gets the object pointer and ref it -EAPI _Eo * eo2_do_start(Eo *obj_id); +// 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); -// end of the eo2_do barrier, unref the obj -EAPI void eo2_do_end(_Eo *obj); - -// optional helper -#define eo2_call(api_func) api_func(eo2_o) -#define eo2_callv(api_func, ...) api_func(eo2_o, __VA_ARGS__) +// end of the eo2_do barrier, unref the obj, move the stack pointer +EAPI void eo2_do_end(); // eo object method calls batch, // DO NOT use return statement in it, use break if necessary @@ -692,11 +680,9 @@ EAPI void eo2_do_end(_Eo *obj); do \ { \ Eo *_objid_ = objid; \ - _Eo *_obj_ = eo2_do_start(_objid_); \ - if (!_obj_) break; \ + if (!eo2_do_start(_objid_)) break; \ do { __VA_ARGS__ ; } while (0); \ - eo2_do_end(_obj_); \ - _obj_ = NULL; \ + eo2_do_end(); \ } while (0) // FIXME diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index 906183a9e2..d21b5f3788 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -257,25 +257,77 @@ _eo_kls_itr_func_get(const _Eo_Class *cur_klass, Eo_Op op) /************************************ EO2 ************************************/ -EAPI _Eo * +// FIXME: per thread stack, grow/shrink +#define EO2_INVALID_DATA (void *) -1 +#define EO2_CALL_STACK_SIZE 5 +typedef struct _Eo2_Stack_Frame +{ + Eo *obj_id; + _Eo *obj; + void *obj_data; + +} Eo2_Stack_Frame; + +typedef struct _Eo2_Call_Stack { + Eo2_Stack_Frame stack[EO2_CALL_STACK_SIZE]; + Eo2_Stack_Frame *frame_ptr; +} Eo2_Call_Stack; + +static Eo2_Call_Stack eo2_call_stack = { + { + { NULL, NULL, EO2_INVALID_DATA }, + { NULL, NULL, EO2_INVALID_DATA }, + { NULL, NULL, EO2_INVALID_DATA }, + { NULL, NULL, EO2_INVALID_DATA }, + { NULL, NULL, EO2_INVALID_DATA }, + }, + NULL }; + +EAPI Eina_Bool eo2_do_start(Eo *obj_id) { - EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL); + EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE); _eo_ref(obj); - return obj; + + if (eo2_call_stack.frame_ptr == NULL) + eo2_call_stack.frame_ptr = &eo2_call_stack.stack[0]; + else + eo2_call_stack.frame_ptr++; + + if (eo2_call_stack.frame_ptr->obj_id != NULL) + ERR("eo2 call stack is not clear, you must have used a return statement in a eo2_do macro"); + + if ((eo2_call_stack.frame_ptr - eo2_call_stack.stack) >= EO2_CALL_STACK_SIZE) + ERR("eo2 call stack overflow !!!"); + + eo2_call_stack.frame_ptr->obj = obj; + eo2_call_stack.frame_ptr->obj_id = obj_id; + eo2_call_stack.frame_ptr->obj_data = EO2_INVALID_DATA; + + return EINA_TRUE; } EAPI void -eo2_do_end(_Eo *obj) +eo2_do_end() { - _eo_unref(obj); + _eo_unref(eo2_call_stack.frame_ptr->obj); + + eo2_call_stack.frame_ptr->obj = NULL; + eo2_call_stack.frame_ptr->obj_id = NULL; + eo2_call_stack.frame_ptr->obj_data = EO2_INVALID_DATA; + + if (eo2_call_stack.frame_ptr == &eo2_call_stack.stack[0]) + eo2_call_stack.frame_ptr = NULL; + else + eo2_call_stack.frame_ptr--; } EAPI Eina_Bool -eo2_call_resolve_internal(_Eo *obj, const Eo_Class *klass_id, Eo_Op op, Eo2_Op_Call_Data *call) +eo2_call_resolve_internal(const Eo_Class *klass_id, Eo_Op op, Eo2_Op_Call_Data *call) { const _Eo_Class *klass; const op_type_funcs *func; + const _Eo * obj = eo2_call_stack.frame_ptr->obj; if (klass_id) klass = _eo_class_pointer_get(klass_id); @@ -285,8 +337,19 @@ eo2_call_resolve_internal(_Eo *obj, const Eo_Class *klass_id, Eo_Op op, Eo2_Op_C func = _eo_kls_itr_func_get(klass, op); if (EINA_LIKELY(func != NULL)) { + call->obj_id = eo2_call_stack.frame_ptr->obj_id; call->func = func->func; - call->data = _eo_data_scope_get(obj, func->src); + + if (func->src == obj->klass) + { + if (eo2_call_stack.frame_ptr->obj_data == EO2_INVALID_DATA) + eo2_call_stack.frame_ptr->obj_data = _eo_data_scope_get(obj, func->src); + + call->data = eo2_call_stack.frame_ptr->obj_data; + } + else + call->data = _eo_data_scope_get(obj, func->src); + return EINA_TRUE; } @@ -297,11 +360,12 @@ eo2_call_resolve_internal(_Eo *obj, const Eo_Class *klass_id, Eo_Op op, Eo2_Op_C EAPI Eo_Op -eo2_get_op_id(_Eo *obj, void *api_func) +eo2_get_op_id(void *api_func) { int imin, imax, imid; Eo2_Op_Description *op_desc; Eo2_Op_Description *op_descs; + const _Eo * obj = eo2_call_stack.frame_ptr->obj; imin = 0; imax = obj->klass->desc->ops.count - 1; diff --git a/src/lib/eo/eo2_base_class.h b/src/lib/eo/eo2_base_class.h index c4400b8827..ff40eb51aa 100644 --- a/src/lib/eo/eo2_base_class.h +++ b/src/lib/eo/eo2_base_class.h @@ -10,66 +10,66 @@ /* #include "eo_private.h" */ EAPI void -data_set(eo2_a, const char *key, const void *data, eo_base_data_free_func free_func); +data_set(const char *key, const void *data, eo_base_data_free_func free_func); EAPI void -data_get(eo2_a, const char *key); +data_get(const char *key); EAPI void -data_del(eo2_a, const char *key); +data_del(const char *key); EAPI void -wref_add(eo2_a, Eo **wref); +wref_add(Eo **wref); EAPI void -wref_del(eo2_a, Eo **wref); +wref_del(Eo **wref); EAPI void -ev_cb_priority_add(eo2_a, const Eo_Event_Description *desc, +ev_cb_priority_add(const Eo_Event_Description *desc, Eo_Callback_Priority priority, Eo_Event_Cb func, const void *user_data); EAPI void -ev_cb_del(eo2_a, const Eo_Event_Description *desc, Eo_Event_Cb func, +ev_cb_del(const Eo_Event_Description *desc, Eo_Event_Cb func, const void *user_data); EAPI void -ev_cb_array_priority_add(eo2_a, const Eo_Callback_Array_Item *array, +ev_cb_array_priority_add(const Eo_Callback_Array_Item *array, Eo_Callback_Priority priority, const void *user_data); EAPI void -ev_cb_array_del(eo2_a, const Eo_Callback_Array_Item *array, +ev_cb_array_del(const Eo_Callback_Array_Item *array, const void *user_data); EAPI Eina_Bool -ev_cb_call(eo2_a, const Eo_Event_Description *desc, void *event_info); +ev_cb_call(const Eo_Event_Description *desc, void *event_info); EAPI void -ev_cb_forwarder_add(eo2_a, const Eo_Event_Description *desc, Eo *new_obj); +ev_cb_forwarder_add(const Eo_Event_Description *desc, Eo *new_obj); EAPI void -ev_cb_forwarder_del(eo2_a, const Eo_Event_Description *desc, Eo *new_obj); +ev_cb_forwarder_del(const Eo_Event_Description *desc, Eo *new_obj); EAPI void -ev_freeze(eo2_a); +ev_freeze(); EAPI void -ev_thaw(eo2_a); +ev_thaw(); EAPI int -ev_freeze_get(eo2_a); +ev_freeze_get(); EAPI void -ev_global_freeze(eo2_a); +ev_global_freeze(); EAPI void -ev_global_thaw(eo2_a); +ev_global_thaw(); EAPI int -ev_global_freeze_get(eo2_a); +ev_global_freeze_get(); EAPI void -dbg_info_get(eo2_a); +dbg_info_get(); EAPI void eo2_dbg_info_free(Eo_Dbg_Info *info); diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h index a985556b70..621bab43cd 100644 --- a/src/lib/eo/eo_private.h +++ b/src/lib/eo/eo_private.h @@ -60,6 +60,7 @@ typedef uintptr_t Eo_Id; typedef struct _Eo_Class _Eo_Class; typedef struct _Eo_Object _Eo_Object; typedef struct _Eo_Base Eo_Base; +typedef struct _Eo_Internal _Eo; /* Retrieves the pointer to the object from the id */ static inline _Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id);