forked from enlightenment/efl
eo: introduce function definitions with fallback
there can be cases where the call to such a function is never going to be directed to the actual implementation. In those cases the FallackCall will be called.
This commit is contained in:
parent
d7a2993d47
commit
8e4d0d70e9
|
@ -1218,7 +1218,7 @@ typedef struct _Efl_Object_Call_Cache
|
|||
goto __##Name##_op_create; /* yes a goto - see below */ \
|
||||
__##Name##_op_create_done: \
|
||||
if (!_efl_object_call_resolve((Eo *) Obj, #Name, &___call, &___cache, \
|
||||
__FILE__, __LINE__)) return DefRet; \
|
||||
__FILE__, __LINE__)) goto __##Name##_failed; \
|
||||
_func_ = (_Eo_##Name##_func) ___call.func;
|
||||
|
||||
// yes this looks ugly with gotos BUT it moves rare "init" handling code
|
||||
|
@ -1229,20 +1229,22 @@ typedef struct _Efl_Object_Call_Cache
|
|||
// used instructions that are skipepd by and if so moving those away out
|
||||
// of the cacheline that was already fetched should yield better cache
|
||||
// hits.
|
||||
#define EFL_FUNC_COMMON_OP_END(Obj, Name, DefRet) \
|
||||
#define EFL_FUNC_COMMON_OP_END(Obj, Name, DefRet, ErrorCase) \
|
||||
__##Name##_op_create: \
|
||||
if (EINA_UNLIKELY(___cache.op != EFL_NOOP)) memset(&___cache, 0, sizeof(___cache)); \
|
||||
___cache.op = _efl_object_op_api_id_get(EFL_FUNC_COMMON_OP_FUNC(Name), Obj, #Name, __FILE__, __LINE__); \
|
||||
if (___cache.op == EFL_NOOP) return DefRet; \
|
||||
if (___cache.op == EFL_NOOP) goto __##Name##_failed; \
|
||||
___cache.generation = _efl_object_init_generation; \
|
||||
goto __##Name##_op_create_done;
|
||||
|
||||
goto __##Name##_op_create_done; \
|
||||
__##Name##_failed: \
|
||||
ErrorCase \
|
||||
return DefRet;
|
||||
#define _EFL_OBJECT_API_BEFORE_HOOK
|
||||
#define _EFL_OBJECT_API_AFTER_HOOK
|
||||
#define _EFL_OBJECT_API_CALL_HOOK(x) x
|
||||
|
||||
// to define an EAPI function
|
||||
#define _EFL_OBJECT_FUNC_BODY(Name, ObjType, Ret, DefRet) \
|
||||
#define _EFL_OBJECT_FUNC_BODY(Name, ObjType, Ret, DefRet, ErrorCase) \
|
||||
Ret \
|
||||
Name(ObjType obj) \
|
||||
{ \
|
||||
|
@ -1254,10 +1256,10 @@ __##Name##_op_create: \
|
|||
_efl_object_call_end(&___call); \
|
||||
_EFL_OBJECT_API_AFTER_HOOK \
|
||||
return _r; \
|
||||
EFL_FUNC_COMMON_OP_END(obj, Name, DefRet); \
|
||||
EFL_FUNC_COMMON_OP_END(obj, Name, DefRet, ErrorCase); \
|
||||
}
|
||||
|
||||
#define _EFL_OBJECT_VOID_FUNC_BODY(Name, ObjType) \
|
||||
#define _EFL_OBJECT_VOID_FUNC_BODY(Name, ObjType, ErrorCase) \
|
||||
void \
|
||||
Name(ObjType obj) \
|
||||
{ \
|
||||
|
@ -1268,10 +1270,10 @@ __##Name##_op_create: \
|
|||
_efl_object_call_end(&___call); \
|
||||
_EFL_OBJECT_API_AFTER_HOOK \
|
||||
return; \
|
||||
EFL_FUNC_COMMON_OP_END(obj, Name, ); \
|
||||
EFL_FUNC_COMMON_OP_END(obj, Name, , ErrorCase); \
|
||||
}
|
||||
|
||||
#define _EFL_OBJECT_FUNC_BODYV(Name, ObjType, Ret, DefRet, Arguments, ...) \
|
||||
#define _EFL_OBJECT_FUNC_BODYV(Name, ObjType, Ret, DefRet, ErrorCase, Arguments, ...) \
|
||||
Ret \
|
||||
Name(ObjType obj, __VA_ARGS__) \
|
||||
{ \
|
||||
|
@ -1283,10 +1285,10 @@ __##Name##_op_create: \
|
|||
_efl_object_call_end(&___call); \
|
||||
_EFL_OBJECT_API_AFTER_HOOK \
|
||||
return _r; \
|
||||
EFL_FUNC_COMMON_OP_END(obj, Name, DefRet); \
|
||||
EFL_FUNC_COMMON_OP_END(obj, Name, DefRet, ErrorCase); \
|
||||
}
|
||||
|
||||
#define _EFL_OBJECT_VOID_FUNC_BODYV(Name, ObjType, Arguments, ...) \
|
||||
#define _EFL_OBJECT_VOID_FUNC_BODYV(Name, ObjType, ErrorCase, Arguments, ...) \
|
||||
void \
|
||||
Name(ObjType obj, __VA_ARGS__) \
|
||||
{ \
|
||||
|
@ -1297,18 +1299,31 @@ __##Name##_op_create: \
|
|||
_efl_object_call_end(&___call); \
|
||||
_EFL_OBJECT_API_AFTER_HOOK \
|
||||
return; \
|
||||
EFL_FUNC_COMMON_OP_END(obj, Name, ); \
|
||||
EFL_FUNC_COMMON_OP_END(obj, Name, , ErrorCase); \
|
||||
}
|
||||
|
||||
#define EFL_FUNC_BODY(Name, Ret, DefRet) _EFL_OBJECT_FUNC_BODY(Name, Eo *, Ret, DefRet)
|
||||
#define EFL_VOID_FUNC_BODY(Name) _EFL_OBJECT_VOID_FUNC_BODY(Name, Eo *)
|
||||
#define EFL_FUNC_BODYV(Name, Ret, DefRet, Arguments, ...) _EFL_OBJECT_FUNC_BODYV(Name, Eo *, Ret, DefRet, EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
#define EFL_VOID_FUNC_BODYV(Name, Arguments, ...) _EFL_OBJECT_VOID_FUNC_BODYV(Name, Eo *, EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
#define EFL_FUNC_BODY(Name, Ret, DefRet) _EFL_OBJECT_FUNC_BODY(Name, Eo *, Ret, DefRet, )
|
||||
#define EFL_VOID_FUNC_BODY(Name) _EFL_OBJECT_VOID_FUNC_BODY(Name, Eo *, )
|
||||
#define EFL_FUNC_BODYV(Name, Ret, DefRet, Arguments, ...) _EFL_OBJECT_FUNC_BODYV(Name, Eo *, Ret, DefRet, , EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
#define EFL_VOID_FUNC_BODYV(Name, Arguments, ...) _EFL_OBJECT_VOID_FUNC_BODYV(Name, Eo *, , EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
|
||||
#define EFL_FUNC_BODY_CONST(Name, Ret, DefRet) _EFL_OBJECT_FUNC_BODY(Name, const Eo *, Ret, DefRet)
|
||||
#define EFL_VOID_FUNC_BODY_CONST(Name) _EFL_OBJECT_VOID_FUNC_BODY(Name, const Eo *)
|
||||
#define EFL_FUNC_BODYV_CONST(Name, Ret, DefRet, Arguments, ...) _EFL_OBJECT_FUNC_BODYV(Name, const Eo *, Ret, DefRet, EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
#define EFL_VOID_FUNC_BODYV_CONST(Name, Arguments, ...) _EFL_OBJECT_VOID_FUNC_BODYV(Name, const Eo *, EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
#define EFL_FUNC_BODY_CONST(Name, Ret, DefRet) _EFL_OBJECT_FUNC_BODY(Name, const Eo *, Ret, DefRet, )
|
||||
#define EFL_VOID_FUNC_BODY_CONST(Name) _EFL_OBJECT_VOID_FUNC_BODY(Name, const Eo *, )
|
||||
#define EFL_FUNC_BODYV_CONST(Name, Ret, DefRet, Arguments, ...) _EFL_OBJECT_FUNC_BODYV(Name, const Eo *, Ret, DefRet, , EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
#define EFL_VOID_FUNC_BODYV_CONST(Name, Arguments, ...) _EFL_OBJECT_VOID_FUNC_BODYV(Name, const Eo *, , EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
|
||||
// the following macros are also taking a FallbackCall the call you specify there will be called once the call cannot be redirected to a object,
|
||||
// which means eo will be the deepest scope this call will ever get.
|
||||
|
||||
#define EFL_FUNC_BODY_FALLBACK(Name, Ret, DefRet, FallbackCall) _EFL_OBJECT_FUNC_BODY(Name, Eo *, Ret, DefRet, FallbackCall)
|
||||
#define EFL_VOID_FUNC_BODY_FALLBACK(Name, FallbackCall) _EFL_OBJECT_VOID_FUNC_BODY(Name, Eo *, FallbackCall)
|
||||
#define EFL_FUNC_BODYV_FALLBACK(Name, Ret, DefRet, FallbackCall, Arguments, ...) _EFL_OBJECT_FUNC_BODYV(Name, Eo *, Ret, DefRet, FallbackCall, EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
#define EFL_VOID_FUNC_BODYV_FALLBACK(Name, FallbackCall, Arguments, ...) _EFL_OBJECT_VOID_FUNC_BODYV(Name, Eo *, FallbackCall, EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
|
||||
#define EFL_FUNC_BODY_CONST_FALLBACK(Name, Ret, DefRet, FallbackCall) _EFL_OBJECT_FUNC_BODY(Name, const Eo *, Ret, DefRet, FallbackCall)
|
||||
#define EFL_VOID_FUNC_BODY_CONST_FALLBACK(Name, FallbackCall) _EFL_OBJECT_VOID_FUNC_BODY(Name, const Eo *, FallbackCall)
|
||||
#define EFL_FUNC_BODYV_CONST_FALLBACK(Name, Ret, DefRet, FallbackCall, Arguments, ...) _EFL_OBJECT_FUNC_BODYV(Name, const Eo *, Ret, DefRet, FallbackCall, EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
#define EFL_VOID_FUNC_BODYV_CONST_FALLBACK(Name, FallbackCall, Arguments, ...) _EFL_OBJECT_VOID_FUNC_BODYV(Name, const Eo *, FallbackCall, EFL_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
|
||||
#ifndef _WIN32
|
||||
# define _EFL_OBJECT_OP_API_ENTRY(a) (void*)a
|
||||
|
|
|
@ -66,9 +66,72 @@ START_TEST(eo_op_not_found_in_super)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
//the fallback code that will be called
|
||||
|
||||
static Eina_Bool fallback_called;
|
||||
|
||||
static void
|
||||
test_func(void)
|
||||
{
|
||||
fallback_called = EINA_TRUE;
|
||||
}
|
||||
|
||||
//implementation of the test function
|
||||
|
||||
EAPI void simple_error_test(Eo *obj);
|
||||
EFL_VOID_FUNC_BODY_FALLBACK(simple_error_test, test_func(););
|
||||
static void
|
||||
_test(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//create a new class to call those things on
|
||||
|
||||
static Eina_Bool
|
||||
_errorcase_class_initializer(Efl_Class *klass)
|
||||
{
|
||||
EFL_OPS_DEFINE(ops,
|
||||
EFL_OBJECT_OP_FUNC(simple_error_test, _test),
|
||||
);
|
||||
|
||||
return efl_class_functions_set(klass, &ops, NULL);
|
||||
}
|
||||
|
||||
static const Efl_Class_Description errorcase_class_desc = {
|
||||
EO_VERSION,
|
||||
"Simple errorcase",
|
||||
EFL_CLASS_TYPE_REGULAR,
|
||||
0,
|
||||
_errorcase_class_initializer,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
EFL_DEFINE_CLASS(simple_errorcase_class_get, &errorcase_class_desc, EO_CLASS, NULL)
|
||||
|
||||
START_TEST(eo_fallbackcall_execute)
|
||||
{
|
||||
efl_object_init();
|
||||
|
||||
Eo *obj = efl_add(SIMPLE_CLASS, NULL);
|
||||
|
||||
fallback_called = EINA_FALSE;
|
||||
simple_error_test(NULL);
|
||||
ck_assert_int_eq(fallback_called, 1);
|
||||
|
||||
fallback_called = EINA_FALSE;
|
||||
simple_error_test(obj);
|
||||
ck_assert_int_eq(fallback_called, 1);
|
||||
|
||||
efl_object_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void eo_test_call_errors(TCase *tc)
|
||||
{
|
||||
tcase_add_test(tc, eo_pure_virtual_fct_call);
|
||||
tcase_add_test(tc, eo_api_not_implemented_call);
|
||||
tcase_add_test(tc, eo_op_not_found_in_super);
|
||||
tcase_add_test(tc, eo_fallbackcall_execute);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue