forked from enlightenment/efl
eo - make eoid table access threadsafe - was missing a lock around it
this now makes at least eoid deref and ojbect access safe across threads. the downside is that oeid lookup goes from 2% to ~5% of cpu. ugh.
This commit is contained in:
parent
b3993b684e
commit
90acc0216b
|
@ -1794,6 +1794,11 @@ efl_object_init(void)
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!eina_spinlock_new(&_eoid_lock))
|
||||||
|
{
|
||||||
|
EINA_LOG_ERR("Could not init lock.");
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
if (!eina_spinlock_new(&_efl_class_creation_lock))
|
if (!eina_spinlock_new(&_efl_class_creation_lock))
|
||||||
{
|
{
|
||||||
EINA_LOG_ERR("Could not init lock.");
|
EINA_LOG_ERR("Could not init lock.");
|
||||||
|
@ -1875,6 +1880,8 @@ efl_object_shutdown(void)
|
||||||
|
|
||||||
_eo_free_ids_tables();
|
_eo_free_ids_tables();
|
||||||
|
|
||||||
|
eina_spinlock_free(&_eoid_lock);
|
||||||
|
|
||||||
eina_log_domain_unregister(_eo_log_dom);
|
eina_log_domain_unregister(_eo_log_dom);
|
||||||
_eo_log_dom = -1;
|
_eo_log_dom = -1;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
static int event_freeze_count = 0;
|
static int event_freeze_count = 0;
|
||||||
|
|
||||||
|
Eina_Spinlock _eoid_lock;
|
||||||
_Eo_Object *cached_object = NULL;
|
_Eo_Object *cached_object = NULL;
|
||||||
Eo_Id cached_id = 0;
|
Eo_Id cached_id = 0;
|
||||||
|
|
||||||
|
|
|
@ -271,51 +271,70 @@ extern Generation_Counter _eo_generation_counter;
|
||||||
|
|
||||||
extern _Eo_Object *cached_object;
|
extern _Eo_Object *cached_object;
|
||||||
extern Eo_Id cached_id;
|
extern Eo_Id cached_id;
|
||||||
|
extern Eina_Spinlock _eoid_lock;
|
||||||
|
|
||||||
static inline _Eo_Object *
|
static inline _Eo_Object *
|
||||||
_eo_obj_pointer_get(const Eo_Id obj_id)
|
_eo_obj_pointer_get(const Eo_Id obj_id)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_EO_ID
|
#ifdef HAVE_EO_ID
|
||||||
_Eo_Id_Entry *entry;
|
_Eo_Id_Entry *entry;
|
||||||
|
_Eo_Object *ptr;
|
||||||
Generation_Counter generation;
|
Generation_Counter generation;
|
||||||
Table_Index mid_table_id, table_id, entry_id;
|
Table_Index mid_table_id, table_id, entry_id;
|
||||||
|
Eo_Id tag_bit;
|
||||||
|
|
||||||
// NULL objects will just be sensibly ignored. not worth complaining
|
// NULL objects will just be sensibly ignored. not worth complaining
|
||||||
// every single time.
|
// every single time.
|
||||||
|
|
||||||
|
eina_spinlock_take(&_eoid_lock);
|
||||||
|
if (obj_id == cached_id)
|
||||||
|
{
|
||||||
|
ptr = cached_object;
|
||||||
|
eina_spinlock_release(&_eoid_lock);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get tag bit to check later down below - pipelining
|
||||||
|
tag_bit = (obj_id) & MASK_OBJ_TAG;
|
||||||
if (!obj_id)
|
if (!obj_id)
|
||||||
{
|
{
|
||||||
|
eina_spinlock_release(&_eoid_lock);
|
||||||
DBG("obj_id is NULL. Possibly unintended access?");
|
DBG("obj_id is NULL. Possibly unintended access?");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (!(obj_id & MASK_OBJ_TAG))
|
else if (!tag_bit)
|
||||||
{
|
{
|
||||||
|
eina_spinlock_release(&_eoid_lock);
|
||||||
DBG("obj_id is not a valid object id.");
|
DBG("obj_id is not a valid object id.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (obj_id == cached_id)
|
|
||||||
{
|
|
||||||
return cached_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
EO_DECOMPOSE_ID(obj_id, mid_table_id, table_id, entry_id, generation);
|
EO_DECOMPOSE_ID(obj_id, mid_table_id, table_id, entry_id, generation);
|
||||||
|
|
||||||
/* Check the validity of the entry */
|
/* Check the validity of the entry */
|
||||||
if (_eo_ids_tables[mid_table_id] && TABLE_FROM_IDS)
|
if (_eo_ids_tables[mid_table_id])
|
||||||
{
|
{
|
||||||
entry = &(TABLE_FROM_IDS->entries[entry_id]);
|
_Eo_Ids_Table *tab = TABLE_FROM_IDS;
|
||||||
if (entry && entry->active && (entry->generation == generation))
|
|
||||||
|
if (tab)
|
||||||
|
{
|
||||||
|
entry = &(tab->entries[entry_id]);
|
||||||
|
if (entry->active && (entry->generation == generation))
|
||||||
{
|
{
|
||||||
// Cache the result of that lookup
|
// Cache the result of that lookup
|
||||||
cached_object = entry->ptr;
|
cached_object = entry->ptr;
|
||||||
cached_id = obj_id;
|
cached_id = obj_id;
|
||||||
|
ptr = cached_object;
|
||||||
return entry->ptr;
|
eina_spinlock_release(&_eoid_lock);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR("obj_id %p is not pointing to a valid object. Maybe it has already been freed.",
|
ERR("obj_id %p is not pointing to a valid object. Maybe it has already been freed.",
|
||||||
(void *)obj_id);
|
(void *)obj_id);
|
||||||
|
|
||||||
|
eina_spinlock_release(&_eoid_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
#else
|
#else
|
||||||
return (_Eo_Object *) obj_id;
|
return (_Eo_Object *) obj_id;
|
||||||
|
@ -416,6 +435,7 @@ _eo_id_allocate(const _Eo_Object *obj)
|
||||||
#ifdef HAVE_EO_ID
|
#ifdef HAVE_EO_ID
|
||||||
_Eo_Id_Entry *entry = NULL;
|
_Eo_Id_Entry *entry = NULL;
|
||||||
|
|
||||||
|
eina_spinlock_take(&_eoid_lock);
|
||||||
if (_current_table)
|
if (_current_table)
|
||||||
entry = _get_available_entry(_current_table);
|
entry = _get_available_entry(_current_table);
|
||||||
|
|
||||||
|
@ -425,7 +445,10 @@ _eo_id_allocate(const _Eo_Object *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_current_table || !entry)
|
if (!_current_table || !entry)
|
||||||
|
{
|
||||||
|
eina_spinlock_release(&_eoid_lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* [1;max-1] thus we never generate an Eo_Id equal to 0 */
|
/* [1;max-1] thus we never generate an Eo_Id equal to 0 */
|
||||||
_eo_generation_counter++;
|
_eo_generation_counter++;
|
||||||
|
@ -436,6 +459,7 @@ _eo_id_allocate(const _Eo_Object *obj)
|
||||||
entry->active = 1;
|
entry->active = 1;
|
||||||
entry->generation = _eo_generation_counter;
|
entry->generation = _eo_generation_counter;
|
||||||
PROTECT(_current_table);
|
PROTECT(_current_table);
|
||||||
|
eina_spinlock_release(&_eoid_lock);
|
||||||
return EO_COMPOSE_FINAL_ID(_current_table->partial_id,
|
return EO_COMPOSE_FINAL_ID(_current_table->partial_id,
|
||||||
(entry - _current_table->entries),
|
(entry - _current_table->entries),
|
||||||
entry->generation);
|
entry->generation);
|
||||||
|
@ -457,6 +481,7 @@ _eo_id_release(const Eo_Id obj_id)
|
||||||
Table_Index mid_table_id, table_id, entry_id;
|
Table_Index mid_table_id, table_id, entry_id;
|
||||||
EO_DECOMPOSE_ID(obj_id, mid_table_id, table_id, entry_id, generation);
|
EO_DECOMPOSE_ID(obj_id, mid_table_id, table_id, entry_id, generation);
|
||||||
|
|
||||||
|
eina_spinlock_take(&_eoid_lock);
|
||||||
/* Check the validity of the entry */
|
/* Check the validity of the entry */
|
||||||
if (_eo_ids_tables[mid_table_id] && (table = TABLE_FROM_IDS))
|
if (_eo_ids_tables[mid_table_id] && (table = TABLE_FROM_IDS))
|
||||||
{
|
{
|
||||||
|
@ -494,13 +519,18 @@ _eo_id_release(const Eo_Id obj_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case an object is destroyed, wipe out the cache
|
// In case an object is destroyed, wipe out the cache
|
||||||
|
if (cached_id == obj_id)
|
||||||
|
{
|
||||||
cached_id = 0;
|
cached_id = 0;
|
||||||
cached_object = NULL;
|
cached_object = NULL;
|
||||||
|
}
|
||||||
cached_isa_id = NULL;
|
cached_isa_id = NULL;
|
||||||
|
|
||||||
|
eina_spinlock_release(&_eoid_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
eina_spinlock_release(&_eoid_lock);
|
||||||
|
|
||||||
ERR("obj_id %p is not pointing to a valid object. Maybe it has already been freed.", (void *)obj_id);
|
ERR("obj_id %p is not pointing to a valid object. Maybe it has already been freed.", (void *)obj_id);
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Reference in New Issue