eo2: implement class function support
This commit is contained in:
parent
28d66a9858
commit
7be0748b34
|
@ -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)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
107
src/lib/eo/eo.c
107
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue