summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2016-09-28 13:25:26 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2016-09-28 13:38:46 +0900
commit0f929f5546559f1cacfce6adafbecde6df20ff15 (patch)
tree1ef6ba7a590c3a65c0bdaec35c93f41545d48ce0
parent0cbb5a42f3b08f8d536afef7bc8a72a14c93db3c (diff)
downloadefl-0f929f5546559f1cacfce6adafbecde6df20ff15.tar.gz
eo id and shared domain objects - do locking properly and better
so there were a few issues. one we had a spinlokc on the eoid table for shared objects AND then had a mutex for accessing those objects (released on return from any eo function). BUT this missed some funcs like eo_ref, eo_unref and so on in eo.c ... oops. so fixed. but then i realized there was a race condition. we locked the eoid table then unlocked with our pointer THEN locked the sharted object mutex ... then unlocked it. that was a race condtion gap. so we should share the same lock anyway - if it's a shared object, grab the shared object mutex then do a lookup and if the lookup does not fail, KEEP the lock until it is released by the return from eo function or by some special macro/funcs that released a matching lock. since its a recursive lock this is all fine. as its also a universal single lock for all objects we just need the eoid to know if it's shared and needs locking based on the domain bits. so now do this locking properly with just a single mutex, not both a spinlock and mutex and keep the lock around until totally done with the object. this plugs the race condition holes and goes from 1 spinlock lock and unlock then a mutex lock and unlokc to just a single mutex lock and unlock. this means shared objects are actually truly safe across threads and only have the overhead of a single recursive mutex to lock and unlock in every api call.
-rw-r--r--src/lib/eo/Eo.h1
-rw-r--r--src/lib/eo/eo.c250
-rw-r--r--src/lib/eo/eo_base_class.c50
-rw-r--r--src/lib/eo/eo_private.h1
-rw-r--r--src/lib/eo/eo_ptr_indirection.c31
-rw-r--r--src/lib/eo/eo_ptr_indirection.h6
-rw-r--r--src/lib/eo/eo_ptr_indirection.x32
7 files changed, 217 insertions, 154 deletions
diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index d47787140f..c5b4e75ec5 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -691,7 +691,6 @@ typedef struct _Efl_Object_Op_Call_Data
_Eo_Object *obj;
void *func;
void *data;
- void *lock_data;
void *extn1; // for the future to avoid ABI issues
void *extn2; // for the future to avoid ABI issues
void *extn3; // for the future to avoid ABI issues
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index f2e9f318ff..ab52194968 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -335,8 +335,6 @@ _efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Da
const op_type_funcs *func;
Eina_Bool is_obj;
Eina_Bool is_override = EINA_FALSE;
- Eo_Id_Data *data;
- Efl_Id_Domain domain = 0;
if (((Eo_Id) eo_id) & MASK_SUPER_TAG)
{
@@ -351,14 +349,12 @@ _efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Da
return EINA_FALSE;
call->eo_id = eo_id;
- call->lock_data = NULL;
is_obj = _eo_is_a_obj(eo_id);
if (is_obj)
{
EO_OBJ_POINTER_RETURN_VAL(eo_id, _obj, EINA_FALSE);
- domain = ((Eo_Id)eo_id >> SHIFT_DOMAIN) & MASK_DOMAIN;
obj = _obj;
klass = _obj->klass;
@@ -376,14 +372,6 @@ _efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Da
is_override = _obj_is_override(obj) && (cur_klass == NULL);
call->obj = obj;
- if (EINA_UNLIKELY(domain == EFL_ID_DOMAIN_SHARED))
- {
- // YES this is a goto with a label to return. this is a
- // micro-optimization to move infrequent code out of the
- // hot path of the function
- goto ok_lock;
- }
-ok_lock_back:
_efl_ref(_obj);
}
else
@@ -515,8 +503,7 @@ err_func_src:
ERR("in %s:%d: you called a pure virtual func '%s' (%d) of class '%s'.",
file, line, func_name, cache->op, klass->desc->name);
err:
- if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED)) return EINA_FALSE;
- eina_lock_take(&(data->tables[EFL_ID_DOMAIN_SHARED]->obj_lock));
+ if (is_obj) _eo_obj_pointer_done((Eo_Id)eo_id);
return EINA_FALSE;
// yes - special "move out of hot path" code blobs with goto's for
@@ -539,13 +526,6 @@ ok_klass:
}
goto ok_klass_back;
-ok_lock:
- {
- data = call->lock_data = _eo_table_data_get();
- eina_lock_take(&(data->tables[EFL_ID_DOMAIN_SHARED]->obj_lock));
- }
- goto ok_lock_back;
-
return EINA_FALSE;
}
@@ -555,13 +535,32 @@ _efl_object_call_end(Efl_Object_Op_Call_Data *call)
if (EINA_LIKELY(!!call->obj))
{
_efl_unref(call->obj);
- if (EINA_LIKELY(!call->lock_data)) return;
-
- Eo_Id_Data *data = call->lock_data;
- eina_lock_release(&(data->tables[EFL_ID_DOMAIN_SHARED]->obj_lock));
+ if (call->obj) _eo_obj_pointer_done((Eo_Id)call->eo_id);
}
}
+/*
+EAPI void
+_efl_shared_lock(const Eo *eo_id)
+{
+#ifdef HAVE_EO_ID
+ Efl_Id_Domain domain = ((Eo_Id)eo_id >> SHIFT_DOMAIN) & MASK_DOMAIN;
+ if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED)) return;
+ eina_lock_take(&(_eo_table_data_shared_data->obj_lock));
+#endif
+}
+
+EAPI void
+_efl_shared_unlock(const Eo *eo_id)
+{
+#ifdef HAVE_EO_ID
+ Efl_Id_Domain domain = ((Eo_Id)eo_id >> SHIFT_DOMAIN) & MASK_DOMAIN;
+ if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED)) return;
+ eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
+#endif
+}
+*/
+
static inline Eina_Bool
_eo_api_func_equal(const void *api_func1, const void *api_func2)
{
@@ -748,6 +747,7 @@ _efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, E
if (EINA_UNLIKELY(klass->desc->type != EFL_CLASS_TYPE_REGULAR))
{
ERR("in %s:%d: Class '%s' is not instantiate-able. Aborting.", file, line, klass->desc->name);
+ if (parent_id) EO_OBJ_DONE(parent_id);
return NULL;
}
@@ -791,6 +791,7 @@ _efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, E
/* We have two refs at this point. */
_efl_unref(obj);
efl_del((Eo *) obj->header.id);
+ if (parent_id) EO_OBJ_DONE(parent_id);
return NULL;
}
else if (eo_id != _eo_obj_id_get(obj))
@@ -801,6 +802,7 @@ _efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, E
efl_del((Eo *) obj->header.id);
_efl_ref(new_obj);
+ EO_OBJ_DONE(eo_id);
}
if (is_fallback)
@@ -808,6 +810,7 @@ _efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, E
fptr->obj = eo_id;
}
+ if (parent_id) EO_OBJ_DONE(parent_id);
return eo_id;
}
@@ -844,12 +847,13 @@ _efl_add_internal_end(Eo *eo_id, Eo *finalized_id)
obj->finalized = EINA_TRUE;
_efl_unref(obj);
-
+ EO_OBJ_DONE(eo_id);
return (Eo *)eo_id;
cleanup:
_efl_unref(obj);
efl_del((Eo *) obj->header.id);
+ EO_OBJ_DONE(eo_id);
return NULL;
}
@@ -877,6 +881,8 @@ _efl_add_end(Eo *eo_id, Eina_Bool is_ref, Eina_Bool is_fallback)
EAPI const Efl_Class *
efl_class_get(const Eo *eo_id)
{
+ const Efl_Class *klass;
+
if (_eo_is_a_class(eo_id))
{
EO_CLASS_POINTER_RETURN_VAL(eo_id, _klass, NULL);
@@ -884,8 +890,9 @@ efl_class_get(const Eo *eo_id)
}
EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, NULL);
-
- return _eo_class_id_get(obj->klass);
+ klass = _eo_class_id_get(obj->klass);
+ EO_OBJ_DONE(eo_id);
+ return klass;
}
EAPI const char *
@@ -902,8 +909,8 @@ efl_class_name_get(const Efl_Class *eo_id)
{
EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, NULL);
klass = obj->klass;
+ EO_OBJ_DONE(eo_id);
}
-
return klass->desc->name;
}
@@ -1403,36 +1410,41 @@ efl_object_override(Eo *eo_id, const Efl_Object_Ops *ops)
EO_CLASS_POINTER_RETURN_VAL(EFL_OBJECT_OVERRIDE_CLASS, klass, EINA_FALSE);
Eo_Vtable *previous = obj->vtable;
- if (!ops)
+ if (ops)
{
- if (obj->vtable != &obj->klass->vtable)
+ if (obj->vtable == &obj->klass->vtable)
{
- free(obj->vtable);
- obj->vtable = (Eo_Vtable *) &obj->klass->vtable;
+ obj->vtable = calloc(1, sizeof(*obj->vtable));
+ _vtable_init(obj->vtable, previous->size);
+ _vtable_copy_all(obj->vtable, previous);
+ if (!_eo_class_funcs_set(obj->vtable, ops, obj->klass,
+ klass, 0, EINA_TRUE))
+ goto err;
+ goto done;
}
- return EINA_TRUE;
- }
-
- if (obj->vtable == &obj->klass->vtable)
- {
- obj->vtable = calloc(1, sizeof(*obj->vtable));
- _vtable_init(obj->vtable, previous->size);
- _vtable_copy_all(obj->vtable, previous);
+ else goto err_already;
}
else
{
- ERR("Function table already overridden, not allowed to override again. "
- "Call with NULL to reset the function table first.");
- return EINA_FALSE;
- }
-
- if (!_eo_class_funcs_set(obj->vtable, ops, obj->klass, klass, 0, EINA_TRUE))
- {
- ERR("Failed to override functions for %p", eo_id);
- return EINA_FALSE;
+ if (obj->vtable != &obj->klass->vtable)
+ {
+ free(obj->vtable);
+ obj->vtable = (Eo_Vtable *) &obj->klass->vtable;
+ }
}
-
+done:
+ EO_OBJ_DONE(eo_id);
return EINA_TRUE;
+
+err_already:
+ ERR("Function table already overridden, not allowed to override again. "
+ "Call with NULL to reset the function table first.");
+ goto err_done;
+err:
+ ERR("Failed to override functions for %p", eo_id);
+err_done:
+ EO_OBJ_DONE(eo_id);
+ return EINA_FALSE;
}
EAPI Eina_Bool
@@ -1471,7 +1483,7 @@ efl_isa(const Eo *eo_id, const Efl_Class *klass_id)
}
else
{
- eina_spinlock_take(&(tdata->lock));
+ eina_lock_take(&(_eo_table_data_shared_data->obj_lock));
if ((tdata->cache.isa_id == eo_id) &&
(tdata->cache.klass == klass_id))
@@ -1479,15 +1491,12 @@ efl_isa(const Eo *eo_id, const Efl_Class *klass_id)
isa = tdata->cache.isa;
goto shared_ok;
}
- eina_spinlock_release(&(tdata->lock));
EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, EINA_FALSE);
EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, EINA_FALSE);
const op_type_funcs *func = _vtable_func_get
(obj->vtable, klass->base_id + klass->ops_count);
- eina_spinlock_take(&(tdata->lock));
-
// Caching the result as we do a lot of serial efl_isa due to evas_object_image using it.
tdata->cache.isa_id = eo_id;
tdata->cache.klass = klass_id;
@@ -1495,7 +1504,7 @@ efl_isa(const Eo *eo_id, const Efl_Class *klass_id)
// _eo_class_isa_func.
isa = tdata->cache.isa = (func && (func->func == _eo_class_isa_func));
shared_ok:
- eina_spinlock_release(&(tdata->lock));
+ eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
}
return isa;
}
@@ -1514,6 +1523,7 @@ efl_xref_internal(const char *file, int line, Eo *obj_id, const Eo *ref_obj_id)
xref->line = line;
obj->xrefs = eina_inlist_prepend(obj->xrefs, EINA_INLIST_GET(xref));
+ EO_OBJ_DONE(obj_id);
#else
(void) ref_obj_id;
(void) file;
@@ -1543,8 +1553,10 @@ efl_xunref(Eo *obj_id, const Eo *ref_obj_id)
else
{
ERR("ref_obj (%p) does not reference obj (%p). Aborting unref.", ref_obj_id, obj_id);
+ EO_OBJ_DONE(obj_id);
return;
}
+ EO_OBJ_DONE(obj_id);
#else
(void) ref_obj_id;
#endif
@@ -1558,9 +1570,8 @@ efl_ref(const Eo *obj_id)
++(obj->user_refcount);
if (EINA_UNLIKELY(obj->user_refcount == 1))
- {
- _efl_ref(obj);
- }
+ _efl_ref(obj);
+ EO_OBJ_DONE(obj_id);
return (Eo *)obj_id;
}
@@ -1575,27 +1586,32 @@ efl_unref(const Eo *obj_id)
if (obj->user_refcount < 0)
{
ERR("Obj:%p. User refcount (%d) < 0. Too many unrefs.", obj, obj->user_refcount);
+ EO_OBJ_DONE(obj_id);
return;
}
-
_efl_unref(obj);
}
+ EO_OBJ_DONE(obj_id);
}
EAPI int
efl_ref_get(const Eo *obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, 0);
-
- return obj->user_refcount;
+ int ref;
+ ref = obj->user_refcount;
+ EO_OBJ_DONE(obj_id);
+ return ref;
}
EAPI int
___efl_ref2_get(const Eo *obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, 0);
-
- return obj->refcount;
+ int ref;
+ ref = obj->refcount;
+ EO_OBJ_DONE(obj_id);
+ return ref;
}
EAPI void
@@ -1603,6 +1619,7 @@ ___efl_ref2_reset(const Eo *obj_id)
{
EO_OBJ_POINTER_RETURN(obj_id, obj);
obj->refcount = 0;
+ EO_OBJ_DONE(obj_id);
}
@@ -1610,16 +1627,18 @@ EAPI void
efl_del_intercept_set(Eo *obj_id, Efl_Del_Intercept del_intercept_func)
{
EO_OBJ_POINTER_RETURN(obj_id, obj);
-
obj->del_intercept = del_intercept_func;
+ EO_OBJ_DONE(obj_id);
}
EAPI Efl_Del_Intercept
efl_del_intercept_get(const Eo *obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
-
- return obj->del_intercept;
+ Efl_Del_Intercept func;
+ func = obj->del_intercept;
+ EO_OBJ_DONE(obj_id);
+ return func;
}
void
@@ -1629,10 +1648,11 @@ _eo_condtor_done(Eo *obj_id)
if (obj->condtor_done)
{
ERR("Object %p is already constructed at this point.", obj);
+ EO_OBJ_DONE(obj_id);
return;
}
-
obj->condtor_done = EINA_TRUE;
+ EO_OBJ_DONE(obj_id);
}
static inline void *
@@ -1755,52 +1775,52 @@ efl_data_scope_get(const Eo *obj_id, const Efl_Class *klass_id)
if (!_eo_class_mro_has(obj->klass, klass))
{
ERR("Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter.", klass->desc->name, obj->klass->desc->name);
+ EO_OBJ_DONE(obj_id);
return NULL;
}
#endif
ret = _efl_data_scope_safe_get(obj, klass);
-
#ifdef EO_DEBUG
if (!ret && (klass->desc->data_size == 0))
- {
- ERR("Tried getting data of class '%s', but it has none.", klass->desc->name);
- }
+ ERR("Tried getting data of class '%s', but it has none.", klass->desc->name);
#endif
-
+ EO_OBJ_DONE(obj_id);
return ret;
}
EAPI void *
efl_data_xref_internal(const char *file, int line, const Eo *obj_id, const Efl_Class *klass_id, const Eo *ref_obj_id)
{
- void *ret;
- EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
- EO_OBJ_POINTER_RETURN_VAL(ref_obj_id, ref_obj, NULL);
+ void *ret = NULL;
_Efl_Class *klass = NULL;
- if (klass_id)
+ EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
+ EO_OBJ_POINTER(ref_obj_id, ref_obj);
+ if (ref_obj)
{
- EO_CLASS_POINTER_RETURN_VAL(klass_id, klass2, NULL);
- klass = klass2;
-
-#ifdef EO_DEBUG
- if (!_eo_class_mro_has(obj->klass, klass))
+ if (klass_id)
{
- ERR("Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter.", klass->desc->name, obj->klass->desc->name);
- return NULL;
- }
+ EO_CLASS_POINTER_RETURN_VAL(klass_id, klass2, NULL);
+ klass = klass2;
+#ifdef EO_DEBUG
+ if (!_eo_class_mro_has(obj->klass, klass))
+ {
+ ERR("Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter.", klass->desc->name, obj->klass->desc->name);
+ EO_OBJ_DONE(obj_id);
+ EO_OBJ_DONE(ref_obj_id);
+ return NULL;
+ }
#endif
- }
-
- ret = _efl_data_xref_internal(file, line, obj, klass, ref_obj);
+ }
+ ret = _efl_data_xref_internal(file, line, obj, klass, ref_obj);
#ifdef EO_DEBUG
- if (klass && !ret && (klass->desc->data_size == 0))
- {
- ERR("Tried getting data of class '%s', but it has none.", klass->desc->name);
- }
+ if (klass && !ret && (klass->desc->data_size == 0))
+ ERR("Tried getting data of class '%s', but it has none.", klass->desc->name);
#endif
-
+ EO_OBJ_DONE(ref_obj_id);
+ }
+ EO_OBJ_DONE(obj_id);
return ret;
}
@@ -1808,8 +1828,13 @@ EAPI void
efl_data_xunref_internal(const Eo *obj_id, void *data, const Eo *ref_obj_id)
{
EO_OBJ_POINTER_RETURN(obj_id, obj);
- EO_OBJ_POINTER_RETURN(ref_obj_id, ref_obj);
- _efl_data_xunref_internal(obj, data, ref_obj);
+ EO_OBJ_POINTER(ref_obj_id, ref_obj);
+ if (ref_obj)
+ {
+ _efl_data_xunref_internal(obj, data, ref_obj);
+ EO_OBJ_DONE(ref_obj_id);
+ }
+ EO_OBJ_DONE(obj_id);
}
static void
@@ -1880,6 +1905,7 @@ efl_object_init(void)
EINA_LOG_ERR("Could not allocate shared table data");
return EINA_FALSE;
}
+ _eo_table_data_shared_data = _eo_table_data_shared->tables[EFL_ID_DOMAIN_SHARED];
// specially force eoid data to be creanted so we can switch it to domain 0
Eo_Id_Data *data = _eo_table_data_new(EFL_ID_DOMAIN_MAIN);
@@ -1953,6 +1979,7 @@ efl_object_shutdown(void)
{
_eo_free_ids_tables(_eo_table_data_shared);
_eo_table_data_shared = NULL;
+ _eo_table_data_shared_data = NULL;
}
eina_log_domain_unregister(_eo_log_dom);
@@ -2117,9 +2144,11 @@ efl_compatible(const Eo *obj, const Eo *obj_target)
EAPI Eina_Bool
efl_destructed_is(const Eo *obj_id)
{
+ Eina_Bool is;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE);
-
- return obj->destructed;
+ is = obj->destructed;
+ EO_OBJ_DONE(obj_id);
+ return is;
}
EAPI void
@@ -2127,6 +2156,7 @@ efl_manual_free_set(Eo *obj_id, Eina_Bool manual_free)
{
EO_OBJ_POINTER_RETURN(obj_id, obj);
obj->manual_free = manual_free;
+ EO_OBJ_DONE(obj_id);
}
EAPI Eina_Bool
@@ -2134,21 +2164,21 @@ efl_manual_free(Eo *obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE);
- if (EINA_FALSE == obj->manual_free)
- {
- ERR("Tried to manually free the object %p while the option has not been set; see efl_manual_free_set for more information.", obj);
- return EINA_FALSE;
- }
-
- if (!obj->destructed)
- {
- ERR("Tried deleting the object %p while still referenced(%d).", obj_id, obj->refcount);
- return EINA_FALSE;
- }
-
+ if (obj->manual_free == EINA_FALSE) goto err_manual_free;
+ if (!obj->destructed) goto err_not_destructed;
_eo_free(obj);
-
+ EO_OBJ_DONE(obj_id);
return EINA_TRUE;
+
+err_manual_free:
+ ERR("Tried to manually free the object %p while the option has not been set; see efl_manual_free_set for more information.", obj);
+ goto err;
+err_not_destructed:
+ ERR("Tried deleting the object %p while still referenced(%d).", obj_id, obj->refcount);
+ goto err;
+err:
+ EO_OBJ_DONE(obj_id);
+ return EINA_FALSE;
}
EAPI int
diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c
index 1398142f2f..8203bde1d5 100644
--- a/src/lib/eo/eo_base_class.c
+++ b/src/lib/eo/eo_base_class.c
@@ -592,6 +592,7 @@ _efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo *parent_id)
{
pd->parent = NULL;
}
+ EO_OBJ_DONE(obj);
}
EOLIAN static Eo *
@@ -603,9 +604,11 @@ _efl_object_parent_get(Eo *obj EINA_UNUSED, Efl_Object_Data *pd)
EOLIAN static Eina_Bool
_efl_object_finalized_get(Eo *obj_id, Efl_Object_Data *pd EINA_UNUSED)
{
+ Eina_Bool finalized;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE);
-
- return obj->finalized;
+ finalized = obj->finalized;
+ EO_OBJ_DONE(obj);
+ return finalized;
}
EOLIAN static Efl_Object *
@@ -679,7 +682,11 @@ _efl_object_children_iterator_new(Eo *obj_id, Efl_Object_Data *pd)
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
- if (!pd->children) return NULL;
+ if (!pd->children)
+ {
+ EO_OBJ_DONE(obj_id);
+ return NULL;
+ }
klass = (_Efl_Class *) obj->klass;
@@ -706,6 +713,7 @@ _efl_object_children_iterator_new(Eo *obj_id, Efl_Object_Data *pd)
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_efl_children_iterator_container);
it->iterator.free = FUNC_ITERATOR_FREE(_efl_children_iterator_free);
+ EO_OBJ_DONE(obj_id);
return (Eina_Iterator *)it;
}
@@ -1443,8 +1451,12 @@ EOLIAN static Eina_Bool
_efl_object_composite_attach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo *comp_obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
- EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, EINA_FALSE);
-
+ EO_OBJ_POINTER(parent_id, parent);
+ if (!parent)
+ {
+ EO_OBJ_DONE(comp_obj_id);
+ return EINA_FALSE;
+ }
Efl_Object_Data *comp_pd = efl_data_scope_get(comp_obj_id, EFL_OBJECT_CLASS);
/* Don't composite if we already have a composite object of this type */
{
@@ -1454,14 +1466,16 @@ _efl_object_composite_attach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo
{
EO_OBJ_POINTER_RETURN_VAL(emb_obj_id, emb_obj, EINA_FALSE);
if (emb_obj->klass == comp_obj->klass)
- return EINA_FALSE;
+ {
+ EO_OBJ_DONE(parent_id);
+ EO_OBJ_DONE(comp_obj_id);
+ return EINA_FALSE;
+ }
}
}
if (efl_composite_part_is(comp_obj_id))
- {
- efl_composite_detach(comp_pd->ext->composite_parent, comp_obj_id);
- }
+ efl_composite_detach(comp_pd->ext->composite_parent, comp_obj_id);
/* Set the parent comp on the child. */
_efl_object_extension_need(comp_pd);
@@ -1469,6 +1483,8 @@ _efl_object_composite_attach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo
parent->composite_objects = eina_list_prepend(parent->composite_objects, comp_obj_id);
+ EO_OBJ_DONE(parent_id);
+ EO_OBJ_DONE(comp_obj_id);
return EINA_TRUE;
}
@@ -1476,10 +1492,19 @@ EOLIAN static Eina_Bool
_efl_object_composite_detach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo *comp_obj_id)
{
EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
- EO_OBJ_POINTER_RETURN_VAL(parent_id, parent, EINA_FALSE);
+ EO_OBJ_POINTER(parent_id, parent);
+ if (!parent)
+ {
+ EO_OBJ_DONE(comp_obj_id);
+ return EINA_FALSE;
+ }
if (!efl_composite_part_is(comp_obj_id))
- return EINA_FALSE;
+ {
+ EO_OBJ_DONE(parent_id);
+ EO_OBJ_DONE(comp_obj_id);
+ return EINA_FALSE;
+ }
parent->composite_objects = eina_list_remove(parent->composite_objects, comp_obj_id);
/* Clear the comp parent on the child. */
@@ -1490,6 +1515,8 @@ _efl_object_composite_detach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo
_efl_object_extension_noneed(comp_pd);
}
+ EO_OBJ_DONE(parent_id);
+ EO_OBJ_DONE(comp_obj_id);
return EINA_TRUE;
}
@@ -1635,6 +1662,7 @@ _efl_object_destructor(Eo *obj, Efl_Object_Data *pd)
{
efl_composite_detach(obj, emb_obj_id);
}
+ EO_OBJ_DONE(obj);
}
if (pd->ext && pd->ext->composite_parent)
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index 1cbddf2ccf..54975fffb7 100644
--- a/src/lib/eo/eo_private.h
+++ b/src/lib/eo/eo_private.h
@@ -208,6 +208,7 @@ Eo *_eo_header_id_get(const Eo_Header *header)
/* Retrieves the pointer to the object from the id */
_Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id);
+void _eo_obj_pointer_done(const Eo_Id obj_id);
static inline
Efl_Class *_eo_class_id_get(const _Efl_Class *klass)
diff --git a/src/lib/eo/eo_ptr_indirection.c b/src/lib/eo/eo_ptr_indirection.c
index 0f9b3df7f0..e891bfb671 100644
--- a/src/lib/eo/eo_ptr_indirection.c
+++ b/src/lib/eo/eo_ptr_indirection.c
@@ -8,8 +8,9 @@ extern Eina_Thread _efl_object_main_thread;
//////////////////////////////////////////////////////////////////////////
-Eina_TLS _eo_table_data;
-Eo_Id_Data *_eo_table_data_shared = NULL;
+Eina_TLS _eo_table_data;
+Eo_Id_Data *_eo_table_data_shared = NULL;
+Eo_Id_Table_Data *_eo_table_data_shared_data = NULL;
//////////////////////////////////////////////////////////////////////////
@@ -119,11 +120,11 @@ _eo_obj_pointer_get(const Eo_Id obj_id)
}
else
{
- eina_spinlock_take(&(tdata->lock));
+ eina_lock_take(&(_eo_table_data_shared_data->obj_lock));
if (obj_id == tdata->cache.id)
{
ptr = tdata->cache.object;
- goto shared_ok;
+ return ptr;
}
// get tag bit to check later down below - pipelining
@@ -147,22 +148,22 @@ _eo_obj_pointer_get(const Eo_Id obj_id)
tdata->cache.object = entry->ptr;
tdata->cache.id = obj_id;
ptr = entry->ptr;
- goto shared_ok;
+ // yes we return keeping the lock locked. thats why
+ // you must call _eo_obj_pointer_done() wrapped
+ // by EO_OBJ_DONE() to release
+ return ptr;
}
}
}
goto err_shared;
-shared_ok:
- eina_spinlock_release(&(tdata->lock));
- return ptr;
}
err_shared_null:
- eina_spinlock_release(&(tdata->lock));
+ eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
err_null:
DBG("obj_id is NULL. Possibly unintended access?");
return NULL;
err_shared:
- eina_spinlock_release(&(tdata->lock));
+ eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
err:
_eo_obj_pointer_invalid(obj_id, data, domain);
return NULL;
@@ -170,3 +171,13 @@ err:
return (_Eo_Object *) obj_id;
#endif
}
+
+void
+_eo_obj_pointer_done(const Eo_Id obj_id)
+{
+#ifdef HAVE_EO_ID
+ Efl_Id_Domain domain = (obj_id >> SHIFT_DOMAIN) & MASK_DOMAIN;
+ if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED)) return;
+ eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
+#endif
+}
diff --git a/src/lib/eo/eo_ptr_indirection.h b/src/lib/eo/eo_ptr_indirection.h
index 4b6a1e952c..2d2c28c9f1 100644
--- a/src/lib/eo/eo_ptr_indirection.h
+++ b/src/lib/eo/eo_ptr_indirection.h
@@ -53,6 +53,9 @@ void _eo_pointer_error(const char *msg);
} \
} while (0)
+#define EO_OBJ_DONE(obj_id) \
+ _eo_obj_pointer_done((Eo_Id)obj_id)
+
#else
#define EO_OBJ_POINTER(obj_id, obj) \
@@ -97,6 +100,8 @@ void _eo_pointer_error(const char *msg);
EO_MAGIC_RETURN((Eo_Header *) klass, EO_CLASS_EINA_MAGIC); \
} while (0)
+#define EO_OBJ_DONE(obj_id)
+
#endif
#ifdef EFL_DEBUG
@@ -108,6 +113,7 @@ extern Eina_TLS _eo_table_data;
#include "eo_ptr_indirection.x"
extern Eo_Id_Data *_eo_table_data_shared;
+extern Eo_Id_Table_Data *_eo_table_data_shared_data;
#endif
diff --git a/src/lib/eo/eo_ptr_indirection.x b/src/lib/eo/eo_ptr_indirection.x
index 7529ba2926..de4251ee4d 100644
--- a/src/lib/eo/eo_ptr_indirection.x
+++ b/src/lib/eo/eo_ptr_indirection.x
@@ -269,8 +269,6 @@ struct _Eo_Id_Table_Data
cache;
/* Next generation to use when assigning a new entry to a Eo pointer */
Generation_Counter generation;
- /* Optional lock around objects and eoid table - only used if shared */
- Eina_Spinlock lock;
/* Optional lock around all objects in eoid table - only used if shared */
Eina_Lock obj_lock;
/* are we shared so we need lock/unlock? */
@@ -285,8 +283,9 @@ struct _Eo_Id_Data
unsigned char domain_stack[255 - (sizeof(void *) * 4) - 2];
};
-extern Eina_TLS _eo_table_data;
-extern Eo_Id_Data *_eo_table_data_shared;
+extern Eina_TLS _eo_table_data;
+extern Eo_Id_Data *_eo_table_data_shared;
+extern Eo_Id_Table_Data *_eo_table_data_shared_data;
static inline Eo_Id_Table_Data *
_eo_table_data_table_new(Efl_Id_Domain domain)
@@ -297,14 +296,8 @@ _eo_table_data_table_new(Efl_Id_Domain domain)
if (!tdata) return NULL;
if (domain == EFL_ID_DOMAIN_SHARED)
{
- if (!eina_spinlock_new(&(tdata->lock)))
- {
- free(tdata);
- return NULL;
- }
if (!eina_lock_recursive_new(&(tdata->obj_lock)))
{
- eina_spinlock_free(&(tdata->lock));
free(tdata);
return NULL;
}
@@ -326,19 +319,14 @@ _eo_table_data_new(Efl_Id_Domain domain)
data->tables[data->local_domain] =
_eo_table_data_table_new(data->local_domain);
if (domain != EFL_ID_DOMAIN_SHARED)
- data->tables[EFL_ID_DOMAIN_SHARED] =
- _eo_table_data_shared->tables[EFL_ID_DOMAIN_SHARED];
+ data->tables[EFL_ID_DOMAIN_SHARED] = _eo_table_data_shared_data;
return data;
}
static void
_eo_table_data_table_free(Eo_Id_Table_Data *tdata)
{
- if (tdata->shared)
- {
- eina_spinlock_free(&(tdata->lock));
- eina_lock_free(&(tdata->obj_lock));
- }
+ if (tdata->shared) eina_lock_free(&(tdata->obj_lock));
free(tdata);
}
@@ -538,7 +526,7 @@ _eo_id_allocate(const _Eo_Object *obj, const Eo *parent_id)
}
else
{
- eina_spinlock_take(&(tdata->lock));
+ eina_lock_take(&(_eo_table_data_shared_data->obj_lock));
if (tdata->current_table)
entry = _get_available_entry(tdata->current_table);
@@ -564,7 +552,7 @@ _eo_id_allocate(const _Eo_Object *obj, const Eo *parent_id)
EFL_ID_DOMAIN_SHARED,
entry->generation);
shared_err:
- eina_spinlock_release(&(tdata->lock));
+ eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
}
return id;
#else
@@ -643,7 +631,7 @@ _eo_id_release(const Eo_Id obj_id)
}
else
{
- eina_spinlock_take(&(tdata->lock));
+ eina_lock_take(&(_eo_table_data_shared_data->obj_lock));
// Check the validity of the entry
if (tdata->eo_ids_tables[mid_table_id] && (table = TABLE_FROM_IDS))
{
@@ -687,11 +675,11 @@ _eo_id_release(const Eo_Id obj_id)
tdata->cache.klass = NULL;;
tdata->cache.isa = EINA_FALSE;
}
- eina_spinlock_release(&(tdata->lock));
+ eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
return;
}
}
- eina_spinlock_release(&(tdata->lock));
+ eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
}
ERR("obj_id %p is not pointing to a valid object. Maybe it has already been freed.", (void *)obj_id);
#else