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:
Tom Hacohen 2015-11-09 11:45:04 +00:00
parent a6347f88fd
commit fc88037977
4 changed files with 154 additions and 432 deletions

View File

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

View File

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

View File

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

View File

@ -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