eo2: implement class function support

This commit is contained in:
Jérémy Zurcher 2013-07-30 15:02:35 +02:00 committed by Tom Hacohen
parent 28d66a9858
commit 7be0748b34
2 changed files with 146 additions and 29 deletions

View File

@ -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)
/*****************************************************************************/

View File

@ -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);
}
}