eo: Remove lock from efl_super

I've always really disliked this lock. If someone calls a non-eo
function by accident with efl_super() then you'll most likely end
up in a deadlock.

This adds the cur_klass pointer to the object itself, exploiting
the fact that we have 8 bytes of padding (on 64 bits, at least).

Also, this opens the door to efl_cast() which would be similar to
efl_super() except that only a dynamic cast is done, not a call
to the parent function.

make benchmark shows a performance improvement, surprisingly.

This is a bit experimental. See also the following commit (efl_cast)
This commit is contained in:
Jean-Philippe Andre 2017-04-18 19:57:53 +09:00
parent c9469e0b01
commit 85636658e0
2 changed files with 31 additions and 29 deletions

View File

@ -372,35 +372,44 @@ _eo_kls_itr_next(const _Efl_Class *orig_kls, const _Efl_Class *cur_klass, Efl_Ob
/************************************ EO ************************************/
static const _Efl_Class *_super_class = NULL;
static Eina_Spinlock _super_class_lock;
static EFL_FUNC_TLS _Efl_Class *_super_klass = NULL;
EAPI Eo *
efl_super(const Eo *obj, const Efl_Class *cur_klass)
efl_super(const Eo *eo_id, const Efl_Class *cur_klass)
{
EO_CLASS_POINTER_GOTO(cur_klass, klass, err);
EO_CLASS_POINTER_GOTO(cur_klass, super_klass, err);
#ifdef EO_DEBUG
if (EINA_UNLIKELY(!_eo_is_a_obj(obj) && !_eo_is_a_class(obj))) goto err_obj;
if (EINA_UNLIKELY(!efl_isa(obj, cur_klass))) goto err_obj_hierarchy;
if (EINA_UNLIKELY(!_eo_is_a_obj(eo_id) && !_eo_is_a_class(eo_id))) goto err_obj;
if (EINA_UNLIKELY(!efl_isa(eo_id, cur_klass))) goto err_obj_hierarchy;
#endif
/* FIXME: Switch to atomic operations intead of lock. */
eina_spinlock_take(&_super_class_lock);
_super_class = klass;
if (EINA_UNLIKELY(!_eo_is_a_obj(eo_id)))
goto do_klass;
EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, NULL);
obj->cur_klass = super_klass;
obj->super = EINA_TRUE;
EO_OBJ_DONE(eo_id);
return (Eo *) eo_id;
do_klass:
// efl_super(Class) is extremely rarely used, so TLS write is fine
_super_klass = super_klass;
return (Eo *) eo_id;
return (Eo *) ((Eo_Id) obj | MASK_SUPER_TAG);
err:
_EO_POINTER_ERR(cur_klass, "Class (%p) is an invalid ref.", cur_klass);
return NULL;
#ifdef EO_DEBUG
err_obj:
_EO_POINTER_ERR(obj, "Object (%p) is an invalid ref, class=%p (%s).", obj, cur_klass, efl_class_name_get(cur_klass));
_EO_POINTER_ERR(eo_id, "Object (%p) is an invalid ref, class=%p (%s).", eo_id, cur_klass, efl_class_name_get(cur_klass));
return NULL;
err_obj_hierarchy:
_EO_POINTER_ERR(obj, "Object (%p) class=%p (%s) is not an instance of class=%p (%s).", obj, efl_class_get(obj), efl_class_name_get(obj), cur_klass, efl_class_name_get(cur_klass));
#endif
_EO_POINTER_ERR(eo_id, "Object (%p) class=%p (%s) is not an instance of class=%p (%s).", eo_id, efl_class_get(eo_id), efl_class_name_get(eo_id), cur_klass, efl_class_name_get(cur_klass));
return NULL;
#endif
}
EAPI Eina_Bool
@ -414,15 +423,6 @@ _efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Da
Eina_Bool is_obj;
Eina_Bool is_override = EINA_FALSE;
if (((Eo_Id) eo_id) & MASK_SUPER_TAG)
{
cur_klass = _super_class;
_super_class = NULL;
eina_spinlock_release(&_super_class_lock);
eo_id = (Eo *) ((Eo_Id) eo_id & ~MASK_SUPER_TAG);
}
if (EINA_UNLIKELY(!eo_id)) return EINA_FALSE;
call->eo_id = eo_id;
@ -436,6 +436,11 @@ _efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Da
obj = _obj;
klass = _obj->klass;
vtable = EO_VTABLE(obj);
if (_obj->cur_klass)
{
cur_klass = _obj->cur_klass;
_obj->cur_klass = NULL;
}
if (_obj_is_override(obj) && cur_klass &&
(_eo_class_id_get(cur_klass) == EFL_OBJECT_OVERRIDE_CLASS))
@ -608,6 +613,8 @@ ok_klass:
EO_CLASS_POINTER_GOTO_PROXY(eo_id, _klass, err_klass);
klass = _klass;
vtable = &klass->vtable;
cur_klass = _super_klass;
if (cur_klass) _super_klass = NULL;
call->obj = NULL;
call->data = NULL;
}
@ -2101,12 +2108,6 @@ efl_object_init(void)
return EINA_FALSE;
}
if (!eina_spinlock_new(&_super_class_lock))
{
ERR("Could not init lock.");
return EINA_FALSE;
}
_eo_log_obj_init();
eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR);
@ -2198,7 +2199,6 @@ efl_object_shutdown(void)
eina_hash_free(_ops_storage);
eina_spinlock_free(&_super_class_lock);
eina_spinlock_free(&_ops_storage_lock);
eina_lock_free(&_efl_class_creation_lock);

View File

@ -107,6 +107,7 @@ struct _Eo_Object
#endif
const Efl_Object_Optional *opt; // eina cow
_Efl_Class *cur_klass;
short refcount;
short user_refcount;
@ -116,6 +117,7 @@ struct _Eo_Object
Eina_Bool condtor_done:1;
Eina_Bool finalized:1;
Eina_Bool super:1;
Eina_Bool del_triggered:1;
Eina_Bool destructed:1;