forked from enlightenment/efl
Eo: Migrate to the new syntax (Eo 4).
The syntax is described in: https://phab.enlightenment.org/w/eo/ Summary: eo_do(obj, a_set(1)) -> a_set(obj, 1) eo_do_super(obj, CLASS, a_set(1)) -> a_set(eo_super(obj, CLASS), 1) eo_do_*_ret() set of functions are no longer needed. This is the first step, the next step would be to also fix up eo_add() which currently still uses the old syntax and is not 100% portable. @feature
This commit is contained in:
parent
a6347f88fd
commit
fc88037977
136
src/lib/eo/Eo.h
136
src/lib/eo/Eo.h
|
@ -99,6 +99,8 @@ extern "C" {
|
|||
* @{
|
||||
*/
|
||||
|
||||
typedef struct _Eo_Object _Eo_Object;
|
||||
|
||||
/**
|
||||
* @typedef Eo
|
||||
* The basic Object type.
|
||||
|
@ -452,7 +454,8 @@ EAPI Eina_Bool eo_shutdown(void);
|
|||
// to fetch internal function and object data at once
|
||||
typedef struct _Eo_Op_Call_Data
|
||||
{
|
||||
Eo *obj;
|
||||
Eo *eo_id;
|
||||
_Eo_Object *obj;
|
||||
void *func;
|
||||
void *data;
|
||||
} Eo_Op_Call_Data;
|
||||
|
@ -497,7 +500,7 @@ typedef struct _Eo_Call_Cache
|
|||
#endif
|
||||
|
||||
// cache OP id, get real fct and object data then do the call
|
||||
#define EO_FUNC_COMMON_OP(Name, DefRet) \
|
||||
#define EO_FUNC_COMMON_OP(Obj, Name, DefRet) \
|
||||
static Eo_Call_Cache ___cache; /* static 0 by default */ \
|
||||
Eo_Op_Call_Data ___call; \
|
||||
if (EINA_UNLIKELY(___cache.op == EO_NOOP)) \
|
||||
|
@ -505,51 +508,65 @@ typedef struct _Eo_Call_Cache
|
|||
___cache.op = _eo_api_op_id_get(EO_FUNC_COMMON_OP_FUNC(Name)); \
|
||||
if (___cache.op == EO_NOOP) return DefRet; \
|
||||
} \
|
||||
if (!_eo_call_resolve(#Name, &___call, &___cache, \
|
||||
if (!_eo_call_resolve((Eo *) Obj, #Name, &___call, &___cache, \
|
||||
__FILE__, __LINE__)) return DefRet; \
|
||||
_Eo_##Name##_func _func_ = (_Eo_##Name##_func) ___call.func; \
|
||||
|
||||
// to define an EAPI function
|
||||
#define EO_FUNC_BODY(Name, Ret, DefRet) \
|
||||
#define _EO_FUNC_BODY(Name, ObjType, Ret, DefRet) \
|
||||
Ret \
|
||||
Name(void) \
|
||||
Name(ObjType obj) \
|
||||
{ \
|
||||
typedef Ret (*_Eo_##Name##_func)(Eo *, void *obj_data); \
|
||||
Ret _r; \
|
||||
EO_FUNC_COMMON_OP(Name, DefRet); \
|
||||
_r = _func_(___call.obj, ___call.data); \
|
||||
EO_FUNC_COMMON_OP(obj, Name, DefRet); \
|
||||
_r = _func_(___call.eo_id, ___call.data); \
|
||||
_eo_call_end(&___call); \
|
||||
return _r; \
|
||||
}
|
||||
|
||||
#define EO_VOID_FUNC_BODY(Name) \
|
||||
#define _EO_VOID_FUNC_BODY(Name, ObjType) \
|
||||
void \
|
||||
Name(void) \
|
||||
Name(ObjType obj) \
|
||||
{ \
|
||||
typedef void (*_Eo_##Name##_func)(Eo *, void *obj_data); \
|
||||
EO_FUNC_COMMON_OP(Name, ); \
|
||||
_func_(___call.obj, ___call.data); \
|
||||
EO_FUNC_COMMON_OP(obj, Name, ); \
|
||||
_func_(___call.eo_id, ___call.data); \
|
||||
_eo_call_end(&___call); \
|
||||
}
|
||||
|
||||
#define EO_FUNC_BODYV(Name, Ret, DefRet, Arguments, ...) \
|
||||
#define _EO_FUNC_BODYV(Name, ObjType, Ret, DefRet, Arguments, ...) \
|
||||
Ret \
|
||||
Name(__VA_ARGS__) \
|
||||
Name(ObjType obj, __VA_ARGS__) \
|
||||
{ \
|
||||
typedef Ret (*_Eo_##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \
|
||||
Ret _r; \
|
||||
EO_FUNC_COMMON_OP(Name, DefRet); \
|
||||
_r = _func_(___call.obj, ___call.data, Arguments); \
|
||||
EO_FUNC_COMMON_OP(obj, Name, DefRet); \
|
||||
_r = _func_(___call.eo_id, ___call.data, Arguments); \
|
||||
_eo_call_end(&___call); \
|
||||
return _r; \
|
||||
}
|
||||
|
||||
#define EO_VOID_FUNC_BODYV(Name, Arguments, ...) \
|
||||
#define _EO_VOID_FUNC_BODYV(Name, ObjType, Arguments, ...) \
|
||||
void \
|
||||
Name(__VA_ARGS__) \
|
||||
Name(ObjType obj, __VA_ARGS__) \
|
||||
{ \
|
||||
typedef void (*_Eo_##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \
|
||||
EO_FUNC_COMMON_OP(Name, ); \
|
||||
_func_(___call.obj, ___call.data, Arguments); \
|
||||
EO_FUNC_COMMON_OP(obj, Name, ); \
|
||||
_func_(___call.eo_id, ___call.data, Arguments); \
|
||||
_eo_call_end(&___call); \
|
||||
}
|
||||
|
||||
#define EO_FUNC_BODY(Name, Ret, DefRet) _EO_FUNC_BODY(Name, Eo *, Ret, DefRet)
|
||||
#define EO_VOID_FUNC_BODY(Name) _EO_VOID_FUNC_BODY(Name, Eo *)
|
||||
#define EO_FUNC_BODYV(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, Eo *, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
#define EO_VOID_FUNC_BODYV(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, Eo *, EO_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
|
||||
#define EO_FUNC_BODY_CONST(Name, Ret, DefRet) _EO_FUNC_BODY(Name, const Eo *, Ret, DefRet)
|
||||
#define EO_VOID_FUNC_BODY_CONST(Name) _EO_VOID_FUNC_BODY(Name, const Eo *)
|
||||
#define EO_FUNC_BODYV_CONST(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, const Eo *, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
#define EO_VOID_FUNC_BODYV_CONST(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, const Eo *, EO_FUNC_CALL(Arguments), __VA_ARGS__)
|
||||
|
||||
#ifndef _WIN32
|
||||
# define _EO_OP_API_ENTRY(a) (void*)a
|
||||
#else
|
||||
|
@ -565,52 +582,15 @@ typedef struct _Eo_Call_Cache
|
|||
EAPI Eo_Op _eo_api_op_id_get(const void *api_func);
|
||||
|
||||
// gets the real function pointer and the object data
|
||||
EAPI Eina_Bool _eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *callcache, const char *file, int line);
|
||||
EAPI Eina_Bool _eo_call_resolve(Eo *obj, const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *callcache, const char *file, int line);
|
||||
|
||||
// start of eo_do barrier, gets the object pointer and ref it, put it on the stask
|
||||
EAPI Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, void *eo_stack);
|
||||
|
||||
// end of the eo_do barrier, unref the obj, move the stack pointer
|
||||
EAPI void _eo_do_end(void *eo_stack);
|
||||
// end of the eo call barrier, unref the obj
|
||||
EAPI void _eo_call_end(Eo_Op_Call_Data *call);
|
||||
|
||||
// end of the eo_add. Calls finalize among others
|
||||
EAPI Eo * _eo_add_end(void *eo_stack);
|
||||
EAPI Eo * _eo_add_end(Eo *obj);
|
||||
|
||||
// XXX: We cheat and make it const to indicate to the compiler that the value never changes
|
||||
EAPI EINA_CONST void *_eo_stack_get(void);
|
||||
|
||||
// eo object method calls batch,
|
||||
|
||||
#define _eo_do_common(eoid, clsid, is_super, ...) \
|
||||
do { \
|
||||
_eo_do_start(eoid, clsid, is_super, _eo_stack_get()); \
|
||||
__VA_ARGS__; \
|
||||
_eo_do_end(_eo_stack_get()); \
|
||||
} while (0)
|
||||
|
||||
#define _eo_do_common_ret(eoid, clsid, is_super, ret_tmp, func) \
|
||||
( \
|
||||
_eo_do_start(eoid, clsid, is_super, _eo_stack_get()), \
|
||||
ret_tmp = func, \
|
||||
_eo_do_end(_eo_stack_get()), \
|
||||
ret_tmp \
|
||||
)
|
||||
|
||||
|
||||
#define eo_do(eoid, ...) _eo_do_common(eoid, NULL, EINA_FALSE, __VA_ARGS__)
|
||||
|
||||
#define eo_do_super(eoid, clsid, func) _eo_do_common(eoid, clsid, EINA_TRUE, func)
|
||||
|
||||
#define eo_do_ret(eoid, ret_tmp, func) _eo_do_common_ret(eoid, NULL, EINA_FALSE, ret_tmp, func)
|
||||
|
||||
#define eo_do_super_ret(eoid, clsid, ret_tmp, func) _eo_do_common_ret(eoid, clsid, EINA_TRUE, ret_tmp, func)
|
||||
|
||||
#define eo_do_part(eoid, part_func, ...) \
|
||||
do { \
|
||||
Eo *__eo_part = eoid; \
|
||||
eo_do(eoid, __eo_part = part_func); \
|
||||
eo_do(__eo_part, __VA_ARGS__); \
|
||||
} while (0)
|
||||
EAPI Eo *eo_super(const Eo *obj, const Eo_Class *cur_klass);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
@ -624,12 +604,11 @@ EAPI EINA_CONST void *_eo_stack_get(void);
|
|||
EAPI const Eo_Class *eo_class_get(const Eo *obj);
|
||||
|
||||
#define _eo_add_common(klass, parent, is_ref, ...) \
|
||||
( \
|
||||
_eo_do_start(_eo_add_internal_start(__FILE__, __LINE__, klass, parent, is_ref), \
|
||||
klass, EINA_FALSE, _eo_stack_get()) \
|
||||
, ##__VA_ARGS__, \
|
||||
(Eo *) _eo_add_end(_eo_stack_get()) \
|
||||
)
|
||||
({ \
|
||||
Eo * const eoid = _eo_add_internal_start(__FILE__, __LINE__, klass, parent, is_ref); \
|
||||
__VA_ARGS__; \
|
||||
(Eo *) _eo_add_end(eoid); \
|
||||
})
|
||||
|
||||
/**
|
||||
* @def eo_add
|
||||
|
@ -900,16 +879,12 @@ typedef void (*eo_key_data_free_func)(void *);
|
|||
* @brief Reference a pointer to an Eo object
|
||||
* @param wref the pointer to use for the weak ref
|
||||
*
|
||||
* Same as eo_wref_add() with the difference that it call eo_do() itself. Checking
|
||||
* for *wref NULL and making sure that you pass the right pointer to both side of
|
||||
* eo_do().
|
||||
*
|
||||
* @see eo_weak_unref
|
||||
* @see eo_wref_add
|
||||
*/
|
||||
#define eo_weak_ref(wref) \
|
||||
do { \
|
||||
if (*wref) eo_do(*wref, eo_wref_add(wref)); \
|
||||
if (*wref) eo_wref_add(*wref, wref); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
|
@ -917,17 +892,13 @@ typedef void (*eo_key_data_free_func)(void *);
|
|||
* @brief Unreference a pointer to an Eo object
|
||||
* @param wref the pointer to use for the weak unref
|
||||
*
|
||||
* Same as eo_wref_del() with the difference that it call eo_do() itself. Checking
|
||||
* for *wref NULL and making sure that you pass the right pointer to both side of
|
||||
* eo_do().
|
||||
*
|
||||
* @see eo_weak_ref
|
||||
* @see eo_wref_del
|
||||
* @see eo_wref_del_safe
|
||||
*/
|
||||
#define eo_weak_unref(wref) \
|
||||
do { \
|
||||
if (*wref) eo_do(*wref, eo_wref_del(wref)); \
|
||||
if (*wref) eo_wref_del(*wref, wref); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
|
@ -935,9 +906,6 @@ typedef void (*eo_key_data_free_func)(void *);
|
|||
* @brief Delete the weak reference passed.
|
||||
* @param wref the weak reference to free.
|
||||
*
|
||||
* Same as eo_wref_del(), with the different that it's not called from eo_do()
|
||||
* so you don't need to check if *wref is not NULL.
|
||||
*
|
||||
* @see #eo_wref_del
|
||||
*/
|
||||
#define eo_wref_del_safe(wref) eo_weak_unref(wref)
|
||||
|
@ -1018,8 +986,8 @@ EAPI const Eo_Event_Description *eo_base_legacy_only_event_description_get(const
|
|||
*
|
||||
* @see eo_event_callback_priority_add()
|
||||
*/
|
||||
#define eo_event_callback_add(desc, cb, data) \
|
||||
eo_event_callback_priority_add(desc, \
|
||||
#define eo_event_callback_add(obj, desc, cb, data) \
|
||||
eo_event_callback_priority_add(obj, desc, \
|
||||
EO_CALLBACK_PRIORITY_DEFAULT, cb, data)
|
||||
|
||||
/**
|
||||
|
@ -1032,8 +1000,8 @@ EAPI const Eo_Event_Description *eo_base_legacy_only_event_description_get(const
|
|||
*
|
||||
* @see eo_event_callback_array_priority_add()
|
||||
*/
|
||||
#define eo_event_callback_array_add(array, data) \
|
||||
eo_event_callback_array_priority_add(array, \
|
||||
#define eo_event_callback_array_add(obj, array, data) \
|
||||
eo_event_callback_array_priority_add(obj, array, \
|
||||
EO_CALLBACK_PRIORITY_DEFAULT, data)
|
||||
|
||||
/**
|
||||
|
|
422
src/lib/eo/eo.c
422
src/lib/eo/eo.c
|
@ -249,288 +249,69 @@ _eo_kls_itr_next(const _Eo_Class *orig_kls, const _Eo_Class *cur_klass, Eo_Op op
|
|||
|
||||
/************************************ EO ************************************/
|
||||
|
||||
// 1024 entries == 16k or 32k (32 or 64bit) for eo call stack. that's 1023
|
||||
// imbricated/recursive calls it can handle before barfing. i'd say that's ok
|
||||
#define EO_CALL_STACK_DEPTH_MIN 1024
|
||||
#define EO_CALL_STACK_SHRINK_DROP (EO_CALL_STACK_DEPTH_MIN >> 1)
|
||||
static const Eo_Class *_super_class = NULL;
|
||||
static Eina_Spinlock _super_class_lock;
|
||||
|
||||
typedef struct _Eo_Stack_Frame
|
||||
EAPI Eo *
|
||||
eo_super(const Eo *obj, const Eo_Class *cur_klass)
|
||||
{
|
||||
union {
|
||||
_Eo_Object *obj;
|
||||
const _Eo_Class *kls;
|
||||
} o;
|
||||
const _Eo_Class *cur_klass;
|
||||
Eina_Bool is_obj : 1;
|
||||
} Eo_Stack_Frame;
|
||||
/* FIXME: Switch to atomic operations intead of lock. */
|
||||
eina_spinlock_take(&_super_class_lock);
|
||||
_super_class = cur_klass;
|
||||
|
||||
#define EO_CALL_STACK_SIZE (EO_CALL_STACK_DEPTH_MIN * sizeof(Eo_Stack_Frame))
|
||||
|
||||
static Eina_TLS _eo_call_stack_key = 0;
|
||||
|
||||
typedef struct _Eo_Call_Stack {
|
||||
Eo_Stack_Frame *frames;
|
||||
Eo_Stack_Frame *frame_ptr;
|
||||
Eo_Stack_Frame *last_frame;
|
||||
Eo_Stack_Frame *shrink_frame;
|
||||
} Eo_Call_Stack;
|
||||
|
||||
#define MEM_PAGE_SIZE 4096
|
||||
|
||||
static void *
|
||||
_eo_call_stack_mem_alloc(size_t size)
|
||||
{
|
||||
#ifdef HAVE_MMAP
|
||||
// allocate eo call stack via mmped anon segment if on linux - more
|
||||
// secure and safe. also gives page aligned memory allowing madvise
|
||||
void *ptr;
|
||||
size_t newsize;
|
||||
newsize = MEM_PAGE_SIZE * ((size + MEM_PAGE_SIZE - 1) /
|
||||
MEM_PAGE_SIZE);
|
||||
ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (ptr == MAP_FAILED)
|
||||
{
|
||||
ERR("eo call stack mmap failed.");
|
||||
return NULL;
|
||||
}
|
||||
return ptr;
|
||||
#else
|
||||
//in regular cases just use malloc
|
||||
return calloc(1, size);
|
||||
#endif
|
||||
return (Eo *) ((Eo_Id) obj | MASK_SUPER_TAG);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
static void
|
||||
_eo_call_stack_mem_resize(void **ptr EINA_UNUSED, size_t newsize, size_t size)
|
||||
EAPI Eina_Bool
|
||||
_eo_call_resolve(Eo *eo_id, const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *cache, const char *file, int line)
|
||||
{
|
||||
if (newsize > size)
|
||||
const _Eo_Class *klass, *inputklass, *main_klass;
|
||||
const _Eo_Class *cur_klass = NULL;
|
||||
_Eo_Object *obj = NULL;
|
||||
const op_type_funcs *func;
|
||||
Eina_Bool is_obj;
|
||||
|
||||
if (((Eo_Id) eo_id) & MASK_SUPER_TAG)
|
||||
{
|
||||
CRI("eo call stack overflow, abort.");
|
||||
abort();
|
||||
}
|
||||
return; // Do nothing, code for actual implementation in history. See commit message for details.
|
||||
#else
|
||||
static void
|
||||
_eo_call_stack_mem_resize(void **ptr, size_t newsize, size_t size EINA_UNUSED)
|
||||
{
|
||||
*ptr = realloc(*ptr, newsize);
|
||||
if (!*ptr)
|
||||
{
|
||||
CRI("eo call stack resize failed, abort.");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
const Eo_Class *tmp = _super_class;
|
||||
_super_class = NULL;
|
||||
eina_spinlock_release(&_super_class_lock);
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
static void
|
||||
_eo_call_stack_mem_free(void *ptr, size_t size)
|
||||
{
|
||||
// free mmaped memory
|
||||
munmap(ptr, size);
|
||||
#else
|
||||
static void
|
||||
_eo_call_stack_mem_free(void *ptr, size_t size EINA_UNUSED)
|
||||
{
|
||||
// free regular memory
|
||||
free(ptr);
|
||||
#endif
|
||||
}
|
||||
eo_id = (Eo *) ((Eo_Id) eo_id & ~MASK_SUPER_TAG);
|
||||
|
||||
static Eo_Call_Stack *
|
||||
_eo_call_stack_create()
|
||||
{
|
||||
Eo_Call_Stack *stack;
|
||||
|
||||
stack = calloc(1, sizeof(Eo_Call_Stack));
|
||||
if (!stack)
|
||||
return NULL;
|
||||
|
||||
stack->frames = _eo_call_stack_mem_alloc(EO_CALL_STACK_SIZE);
|
||||
if (!stack->frames)
|
||||
{
|
||||
free(stack);
|
||||
return NULL;
|
||||
cur_klass = _eo_class_pointer_get(tmp);
|
||||
if (!cur_klass)
|
||||
{
|
||||
ERR("Invalid super class found. Aborting.");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// first frame is never used
|
||||
stack->frame_ptr = stack->frames;
|
||||
stack->last_frame = &stack->frames[EO_CALL_STACK_DEPTH_MIN - 1];
|
||||
stack->shrink_frame = stack->frames;
|
||||
if (EINA_UNLIKELY(!eo_id))
|
||||
return EINA_FALSE;
|
||||
|
||||
return stack;
|
||||
}
|
||||
call->eo_id = eo_id;
|
||||
|
||||
static void
|
||||
_eo_call_stack_free(void *ptr)
|
||||
{
|
||||
Eo_Call_Stack *stack = (Eo_Call_Stack *) ptr;
|
||||
is_obj = _eo_is_a_obj(eo_id);
|
||||
|
||||
if (!stack) return;
|
||||
|
||||
if (stack->frames)
|
||||
_eo_call_stack_mem_free(stack->frames, EO_CALL_STACK_SIZE);
|
||||
|
||||
free(stack);
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREAD_SPECIFIER
|
||||
static __thread Eo_Call_Stack *_eo_thread_stack = NULL;
|
||||
|
||||
#define _EO_CALL_STACK_GET() ((_eo_thread_stack) ? _eo_thread_stack : (_eo_thread_stack = _eo_call_stack_create()))
|
||||
|
||||
#else
|
||||
|
||||
static Eo_Call_Stack *main_loop_stack = NULL;
|
||||
|
||||
#define _EO_CALL_STACK_GET() ((EINA_LIKELY(eina_main_loop_is())) ? main_loop_stack : _eo_call_stack_get_thread())
|
||||
|
||||
static inline Eo_Call_Stack *
|
||||
_eo_call_stack_get_thread(void)
|
||||
{
|
||||
Eo_Call_Stack *stack = eina_tls_get(_eo_call_stack_key);
|
||||
|
||||
if (stack) return stack;
|
||||
|
||||
stack = _eo_call_stack_create();
|
||||
eina_tls_set(_eo_call_stack_key, stack);
|
||||
|
||||
return stack;
|
||||
}
|
||||
#endif
|
||||
|
||||
EAPI EINA_CONST void *
|
||||
_eo_stack_get(void)
|
||||
{
|
||||
return _EO_CALL_STACK_GET();
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eo_call_stack_resize(Eo_Call_Stack *stack, Eina_Bool grow)
|
||||
{
|
||||
size_t sz, next_sz;
|
||||
int frame_offset;
|
||||
|
||||
sz = stack->last_frame - stack->frames + 1;
|
||||
if (grow)
|
||||
next_sz = sz * 2;
|
||||
else
|
||||
next_sz = sz / 2;
|
||||
frame_offset = stack->frame_ptr - stack->frames;
|
||||
|
||||
_eo_call_stack_mem_resize((void **)&(stack->frames),
|
||||
next_sz * sizeof(Eo_Stack_Frame),
|
||||
sz * sizeof(Eo_Stack_Frame));
|
||||
|
||||
stack->frame_ptr = &stack->frames[frame_offset];
|
||||
stack->last_frame = &stack->frames[next_sz - 1];
|
||||
|
||||
if (next_sz == EO_CALL_STACK_DEPTH_MIN)
|
||||
frame_offset = 0;
|
||||
else
|
||||
{
|
||||
if (grow)
|
||||
frame_offset = sz - EO_CALL_STACK_SHRINK_DROP;
|
||||
else
|
||||
frame_offset = (next_sz / 2) - EO_CALL_STACK_SHRINK_DROP;
|
||||
}
|
||||
stack->shrink_frame = &stack->frames[frame_offset];
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eo_do_internal(const Eo *eo_id, const Eo_Class *cur_klass_id,
|
||||
Eina_Bool is_super, Eo_Stack_Frame *fptr)
|
||||
{
|
||||
fptr->is_obj = _eo_is_a_obj(eo_id);
|
||||
|
||||
/* If we are already in the same object context, we inherit info from it. */
|
||||
if (fptr->is_obj)
|
||||
if (is_obj)
|
||||
{
|
||||
EO_OBJ_POINTER_RETURN_VAL(eo_id, _obj, EINA_FALSE);
|
||||
fptr->o.obj = _obj;
|
||||
obj = _obj;
|
||||
klass = _obj->klass;
|
||||
call->obj = obj;
|
||||
_eo_ref(_obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
EO_CLASS_POINTER_RETURN_VAL(eo_id, _klass, EINA_FALSE);
|
||||
fptr->o.kls = _klass;
|
||||
klass = _klass;
|
||||
call->obj = NULL;
|
||||
call->data = NULL;
|
||||
}
|
||||
|
||||
if (is_super)
|
||||
{
|
||||
EO_CLASS_POINTER_RETURN_VAL(cur_klass_id, cur_klass, EINA_FALSE);
|
||||
fptr->cur_klass = cur_klass;
|
||||
}
|
||||
else
|
||||
{
|
||||
fptr->cur_klass = NULL;
|
||||
}
|
||||
inputklass = main_klass = klass;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eo_do_start(const Eo *eo_id, const Eo_Class *cur_klass_id, Eina_Bool is_super, void *eo_stack)
|
||||
{
|
||||
Eina_Bool ret = EINA_TRUE;
|
||||
Eo_Stack_Frame *fptr;
|
||||
Eo_Call_Stack *stack = eo_stack;
|
||||
|
||||
if (stack->frame_ptr == stack->last_frame)
|
||||
_eo_call_stack_resize(stack, EINA_TRUE);
|
||||
|
||||
fptr = stack->frame_ptr;
|
||||
|
||||
fptr++;
|
||||
|
||||
if (!_eo_do_internal(eo_id, cur_klass_id, is_super, fptr))
|
||||
{
|
||||
fptr->o.obj = NULL;
|
||||
fptr->cur_klass = NULL;
|
||||
|
||||
ret = EINA_FALSE;
|
||||
}
|
||||
|
||||
stack->frame_ptr++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
_eo_do_end(void *eo_stack)
|
||||
{
|
||||
Eo_Stack_Frame *fptr;
|
||||
Eo_Call_Stack *stack = eo_stack;
|
||||
|
||||
fptr = stack->frame_ptr;
|
||||
|
||||
if (fptr->is_obj && fptr->o.obj)
|
||||
_eo_unref(fptr->o.obj);
|
||||
|
||||
stack->frame_ptr--;
|
||||
|
||||
if (fptr == stack->shrink_frame)
|
||||
_eo_call_stack_resize(stack, EINA_FALSE);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *cache, const char *file, int line)
|
||||
{
|
||||
Eo_Stack_Frame *fptr;
|
||||
const _Eo_Class *klass, *inputklass;
|
||||
const op_type_funcs *func;
|
||||
Eina_Bool is_obj;
|
||||
|
||||
fptr = _EO_CALL_STACK_GET()->frame_ptr;
|
||||
|
||||
if (EINA_UNLIKELY(!fptr->o.obj))
|
||||
return EINA_FALSE;
|
||||
|
||||
is_obj = fptr->is_obj;
|
||||
|
||||
inputklass = klass = (is_obj) ? fptr->o.obj->klass : fptr->o.kls;
|
||||
|
||||
if (!cache->op)
|
||||
{
|
||||
|
@ -542,9 +323,9 @@ _eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *ca
|
|||
}
|
||||
|
||||
/* If we have a current class, we need to itr to the next. */
|
||||
if (fptr->cur_klass)
|
||||
if (cur_klass)
|
||||
{
|
||||
func = _eo_kls_itr_next(klass, fptr->cur_klass, cache->op);
|
||||
func = _eo_kls_itr_next(klass, cur_klass, cache->op);
|
||||
|
||||
if (!func)
|
||||
goto end;
|
||||
|
@ -568,13 +349,7 @@ _eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *ca
|
|||
call->func = func->func;
|
||||
if (is_obj)
|
||||
{
|
||||
call->obj = (Eo *) fptr->o.obj->header.id;
|
||||
call->data = (char *)fptr->o.obj + cache->off[i].off;
|
||||
}
|
||||
else
|
||||
{
|
||||
call->obj = _eo_class_id_get(inputklass);
|
||||
call->data = NULL;
|
||||
call->data = (char *) obj + cache->off[i].off;
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
@ -593,17 +368,11 @@ _eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *ca
|
|||
|
||||
if (is_obj)
|
||||
{
|
||||
call->obj = (Eo *) fptr->o.obj->header.id;
|
||||
call->data = _eo_data_scope_get(fptr->o.obj, func->src);
|
||||
}
|
||||
else
|
||||
{
|
||||
call->obj = _eo_class_id_get(klass);
|
||||
call->data = NULL;
|
||||
call->data = _eo_data_scope_get(obj, func->src);
|
||||
}
|
||||
|
||||
# if EO_CALL_CACHE_SIZE > 0
|
||||
if (!fptr->cur_klass)
|
||||
if (!cur_klass)
|
||||
{
|
||||
# if EO_CALL_CACHE_SIZE > 1
|
||||
const int slot = cache->next_slot;
|
||||
|
@ -612,7 +381,7 @@ _eo_call_resolve(const char *func_name, Eo_Op_Call_Data *call, Eo_Call_Cache *ca
|
|||
# endif
|
||||
cache->index[slot].klass = (const void *)inputklass;
|
||||
cache->entry[slot].func = (const void *)func;
|
||||
cache->off[slot].off = (int)((long)((char *)call->data - (char *)fptr->o.obj));
|
||||
cache->off[slot].off = (int)((long)((char *)call->data - (char *)obj));
|
||||
# if EO_CALL_CACHE_SIZE > 1
|
||||
cache->next_slot = (slot + 1) % EO_CALL_CACHE_SIZE;
|
||||
# endif
|
||||
|
@ -636,7 +405,7 @@ end:
|
|||
{
|
||||
Eina_List *itr;
|
||||
Eo *emb_obj_id;
|
||||
EINA_LIST_FOREACH(((_Eo_Object *) fptr->o.obj)->composite_objects, itr, emb_obj_id)
|
||||
EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj_id)
|
||||
{
|
||||
_Eo_Object *emb_obj = _eo_obj_pointer_get((Eo_Id)emb_obj_id);
|
||||
|
||||
|
@ -649,7 +418,8 @@ end:
|
|||
|
||||
if (EINA_LIKELY(func->func && func->src))
|
||||
{
|
||||
call->obj = _eo_id_get(emb_obj);
|
||||
call->eo_id = _eo_id_get(emb_obj);
|
||||
call->obj = obj; /* FIXME-eo4: Hack, we retain the previous object so we unref it... */
|
||||
call->func = func->func;
|
||||
call->data = _eo_data_scope_get(emb_obj, func->src);
|
||||
|
||||
|
@ -659,15 +429,12 @@ end:
|
|||
}
|
||||
|
||||
{
|
||||
const _Eo_Class *main_klass;
|
||||
main_klass = (is_obj) ? fptr->o.obj->klass : fptr->o.kls;
|
||||
|
||||
/* If it's a do_super call. */
|
||||
if (fptr->cur_klass)
|
||||
if (cur_klass)
|
||||
{
|
||||
ERR("in %s:%d: func '%s' (%d) could not be resolved for class '%s' for super of '%s'.",
|
||||
file, line, func_name, cache->op, main_klass->desc->name,
|
||||
fptr->cur_klass->desc->name);
|
||||
cur_klass->desc->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -679,6 +446,15 @@ end:
|
|||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
_eo_call_end(Eo_Op_Call_Data *call)
|
||||
{
|
||||
if (EINA_LIKELY(!!call->obj))
|
||||
{
|
||||
_eo_unref(call->obj);
|
||||
}
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eo_api_func_equal(const void *api_func1, const void *api_func2)
|
||||
{
|
||||
|
@ -882,20 +658,19 @@ _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo
|
|||
|
||||
_eo_ref(obj);
|
||||
|
||||
eo_do(eo_id, eo_parent_set(parent_id));
|
||||
eo_parent_set(eo_id, parent_id);
|
||||
|
||||
/* If there's a parent. Ref. Eo_add should return an object with either a
|
||||
* parent ref, or with the lack of, just a ref. */
|
||||
{
|
||||
Eo *parent_tmp;
|
||||
if (ref && eo_do_ret(eo_id, parent_tmp, eo_parent_get()))
|
||||
if (ref && eo_parent_get(eo_id))
|
||||
{
|
||||
_eo_ref(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/* eo_id can change here. Freeing is done on the resolved object. */
|
||||
eo_do(eo_id, eo_id = eo_constructor());
|
||||
eo_id = eo_constructor(eo_id);
|
||||
if (!eo_id)
|
||||
{
|
||||
ERR("Object of class '%s' - Error while constructing object",
|
||||
|
@ -909,28 +684,20 @@ _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo
|
|||
}
|
||||
|
||||
static Eo *
|
||||
_eo_add_internal_end(Eo *eo_id, Eo_Call_Stack *stack)
|
||||
_eo_add_internal_end(Eo *eo_id, Eo *finalized_id)
|
||||
{
|
||||
Eo_Stack_Frame *fptr;
|
||||
EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, NULL);
|
||||
|
||||
fptr = stack->frame_ptr;
|
||||
|
||||
if (EINA_UNLIKELY(!fptr->o.obj))
|
||||
if (!obj->condtor_done)
|
||||
{
|
||||
ERR("Corrupt call stack, shouldn't happen, please report!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!fptr->o.obj->condtor_done)
|
||||
{
|
||||
const _Eo_Class *klass = fptr->o.obj->klass;
|
||||
const _Eo_Class *klass = obj->klass;
|
||||
|
||||
ERR("Object of class '%s' - Not all of the object constructors have been executed.",
|
||||
klass->desc->name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!eo_id)
|
||||
if (!finalized_id)
|
||||
{
|
||||
// XXX: Given EFL usage of objects, construction is a perfectly valid thing
|
||||
// to do. we shouldn't complain about it as handling a NULL obj creation is
|
||||
|
@ -946,24 +713,24 @@ _eo_add_internal_end(Eo *eo_id, Eo_Call_Stack *stack)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
fptr->o.obj->finalized = EINA_TRUE;
|
||||
obj->finalized = EINA_TRUE;
|
||||
|
||||
_eo_unref(fptr->o.obj);
|
||||
_eo_unref(obj);
|
||||
|
||||
return (Eo *)eo_id;
|
||||
|
||||
cleanup:
|
||||
_eo_unref(fptr->o.obj);
|
||||
eo_del((Eo *) fptr->o.obj->header.id);
|
||||
_eo_unref(obj);
|
||||
eo_del((Eo *) obj->header.id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EAPI Eo *
|
||||
_eo_add_end(void *eo_stack)
|
||||
_eo_add_end(Eo *eo_id)
|
||||
{
|
||||
Eo *ret = eo_finalize();
|
||||
ret = _eo_add_internal_end(ret, eo_stack);
|
||||
_eo_do_end(eo_stack);
|
||||
Eo *ret = eo_finalize(eo_id);
|
||||
ret = _eo_add_internal_end(eo_id, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1552,10 +1319,9 @@ eo_unref(const Eo *obj_id)
|
|||
EAPI void
|
||||
eo_del(const Eo *obj)
|
||||
{
|
||||
Eo *parent_tmp;
|
||||
if (eo_do_ret(obj, parent_tmp, eo_parent_get()))
|
||||
if (eo_parent_get((Eo *) obj))
|
||||
{
|
||||
eo_do(obj, eo_parent_set(NULL));
|
||||
eo_parent_set((Eo *) obj, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1800,6 +1566,12 @@ eo_init(void)
|
|||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
if (!eina_spinlock_new(&_super_class_lock))
|
||||
{
|
||||
EINA_LOG_ERR("Could not init lock.");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR);
|
||||
eina_magic_string_static_set(EO_FREED_EINA_MAGIC,
|
||||
EO_FREED_EINA_MAGIC_STR);
|
||||
|
@ -1825,27 +1597,6 @@ eo_init(void)
|
|||
/* bootstrap EO_CLASS_CLASS */
|
||||
(void) EO_ABSTRACT_CLASS_CLASS;
|
||||
|
||||
if (_eo_call_stack_key != 0)
|
||||
WRN("_eo_call_stack_key already set, this should not happen.");
|
||||
else
|
||||
{
|
||||
if (!eina_tls_cb_new(&_eo_call_stack_key, _eo_call_stack_free))
|
||||
{
|
||||
EINA_LOG_ERR("Could not create TLS key for call stack.");
|
||||
return EINA_FALSE;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HAVE_THREAD_SPECIFIER
|
||||
main_loop_stack = _eo_call_stack_create();
|
||||
if (!main_loop_stack)
|
||||
{
|
||||
EINA_LOG_ERR("Could not alloc eo call stack.");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1873,15 +1624,10 @@ eo_shutdown(void)
|
|||
|
||||
eina_hash_free(_ops_storage);
|
||||
|
||||
eina_spinlock_free(&_super_class_lock);
|
||||
eina_spinlock_free(&_ops_storage_lock);
|
||||
eina_spinlock_free(&_eo_class_creation_lock);
|
||||
|
||||
if (_eo_call_stack_key != 0)
|
||||
{
|
||||
eina_tls_free(_eo_call_stack_key);
|
||||
_eo_call_stack_key = 0;
|
||||
}
|
||||
|
||||
_eo_free_ids_tables();
|
||||
|
||||
eina_log_domain_unregister(_eo_log_dom);
|
||||
|
|
|
@ -61,7 +61,6 @@ extern int _eo_log_dom;
|
|||
|
||||
typedef uintptr_t Eo_Id;
|
||||
typedef struct _Eo_Class _Eo_Class;
|
||||
typedef struct _Eo_Object _Eo_Object;
|
||||
typedef struct _Eo_Header Eo_Header;
|
||||
|
||||
/* Retrieves the pointer to the object from the id */
|
||||
|
@ -214,11 +213,11 @@ _eo_del_internal(const char *file, int line, _Eo_Object *obj)
|
|||
|
||||
const _Eo_Class *klass = obj->klass;
|
||||
|
||||
eo_do(_eo_id_get(obj), eo_event_callback_call(EO_BASE_EVENT_DEL, NULL));
|
||||
eo_event_callback_call(_eo_id_get(obj), EO_BASE_EVENT_DEL, NULL);
|
||||
|
||||
_eo_condtor_reset(obj);
|
||||
|
||||
eo_do(_eo_id_get(obj), eo_destructor());
|
||||
eo_destructor(_eo_id_get(obj));
|
||||
|
||||
if (!obj->condtor_done)
|
||||
{
|
||||
|
@ -232,7 +231,7 @@ _eo_del_internal(const char *file, int line, _Eo_Object *obj)
|
|||
Eo *emb_obj;
|
||||
EINA_LIST_FOREACH_SAFE(obj->composite_objects, itr, itr_n, emb_obj)
|
||||
{
|
||||
eo_do(_eo_id_get(obj), eo_composite_detach(emb_obj));
|
||||
eo_composite_detach(_eo_id_get(obj), emb_obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,14 +57,14 @@
|
|||
* it to the fifo.
|
||||
*/
|
||||
|
||||
/* most significant bit is kept to tag Eo_Id with 1 */
|
||||
#if SIZEOF_UINTPTR_T == 4
|
||||
/* 32 bits */
|
||||
# define BITS_MID_TABLE_ID 5
|
||||
# define BITS_TABLE_ID 5
|
||||
# define BITS_ENTRY_ID 12
|
||||
# define BITS_GENERATION_COUNTER 9
|
||||
# define REF_TAG_SHIFT 31
|
||||
# define BITS_GENERATION_COUNTER 8
|
||||
# define REF_TAG_SHIFT 30
|
||||
# define SUPER_TAG_SHIF 31
|
||||
# define DROPPED_TABLES 0
|
||||
# define DROPPED_ENTRIES 4
|
||||
typedef int16_t Table_Index;
|
||||
|
@ -74,8 +74,9 @@ typedef uint16_t Generation_Counter;
|
|||
# define BITS_MID_TABLE_ID 11
|
||||
# define BITS_TABLE_ID 11
|
||||
# define BITS_ENTRY_ID 12
|
||||
# define BITS_GENERATION_COUNTER 29
|
||||
# define REF_TAG_SHIFT 63
|
||||
# define BITS_GENERATION_COUNTER 28
|
||||
# define REF_TAG_SHIFT 62
|
||||
# define SUPER_TAG_SHIFT 63
|
||||
# define DROPPED_TABLES 2
|
||||
# define DROPPED_ENTRIES 3
|
||||
typedef int16_t Table_Index;
|
||||
|
@ -101,6 +102,15 @@ typedef uint32_t Generation_Counter;
|
|||
#define MASK_ENTRY_ID ((1 << BITS_ENTRY_ID) - 1)
|
||||
#define MASK_GENERATIONS (MAX_GENERATIONS - 1)
|
||||
#define MASK_OBJ_TAG (((Eo_Id) 1) << (REF_TAG_SHIFT))
|
||||
/* When we have EO_ID use the highest bit.
|
||||
When we don't have EO_ID, we can repurpose the lowest bit, because allocation
|
||||
is at least 8 byte aligned.
|
||||
XXX: If this is ever not the case, we need to allocate from a mempool and ensure it, or find another trick. */
|
||||
#ifdef HAVE_EO_ID
|
||||
# define MASK_SUPER_TAG (((Eo_Id) 1) << (SUPER_TAG_SHIFT))
|
||||
#else
|
||||
# define MASK_SUPER_TAG ((Eo_Id) 1)
|
||||
#endif
|
||||
|
||||
/* This only applies to classes. Used to artificially enlarge the class ids
|
||||
* to reduce the likelihood of a clash with normal integers. */
|
||||
|
@ -417,7 +427,6 @@ _eo_id_allocate(const _Eo_Object *obj)
|
|||
(entry - _current_table->entries),
|
||||
entry->generation);
|
||||
#else
|
||||
Eo_Id ret = 0x1;
|
||||
(void) obj;
|
||||
return MASK_OBJ_TAG;
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue