eo2: call stack Proof Of Concept
no grow/shrink or thread local storage
This commit is contained in:
parent
a645076979
commit
6a16edc888
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue