2013-04-18 04:19:02 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "eo_ptr_indirection.h"
|
|
|
|
|
2016-09-16 13:49:32 -07:00
|
|
|
extern Eina_Thread _efl_object_main_thread;
|
|
|
|
|
2016-09-07 01:53:33 -07:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2013-05-05 06:08:55 -07:00
|
|
|
|
2016-09-27 21:25:26 -07:00
|
|
|
Eina_TLS _eo_table_data;
|
|
|
|
Eo_Id_Data *_eo_table_data_shared = NULL;
|
|
|
|
Eo_Id_Table_Data *_eo_table_data_shared_data = NULL;
|
2013-04-18 04:19:02 -07:00
|
|
|
|
2016-09-07 01:53:33 -07:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2015-12-29 02:42:05 -08:00
|
|
|
|
|
|
|
void
|
|
|
|
_eo_pointer_error(const char *msg)
|
|
|
|
{
|
|
|
|
ERR("%s", msg);
|
|
|
|
}
|
2016-09-09 02:44:21 -07:00
|
|
|
|
2016-09-16 02:51:22 -07:00
|
|
|
#ifdef HAVE_EO_ID
|
|
|
|
static void
|
|
|
|
_eo_obj_pointer_invalid(const Eo_Id obj_id,
|
|
|
|
Eo_Id_Data *data,
|
|
|
|
unsigned char domain)
|
|
|
|
{
|
2016-09-16 13:49:32 -07:00
|
|
|
Eina_Thread thread = eina_thread_self();
|
|
|
|
const char *tself = "main";
|
2016-09-16 02:51:22 -07:00
|
|
|
const char *type = "object";
|
2016-09-16 13:49:32 -07:00
|
|
|
char tbuf[128];
|
2016-09-16 02:51:22 -07:00
|
|
|
if (obj_id & ((Eo_Id)1 << (REF_TAG_SHIFT - 1))) type = "class";
|
2016-09-16 13:49:32 -07:00
|
|
|
if (thread != _efl_object_main_thread)
|
|
|
|
{
|
|
|
|
snprintf(tbuf, sizeof(tbuf), "%p", (void *)thread);
|
|
|
|
tself = tbuf;
|
|
|
|
}
|
2016-09-16 02:51:22 -07:00
|
|
|
ERR("EOID %p is not a valid %s. "
|
|
|
|
"EOID domain=%i, current_domain=%i, local_domain=%i. "
|
|
|
|
"EOID generation=%lx, id=%lx, ref=%i, super=%i. "
|
2016-09-16 13:49:32 -07:00
|
|
|
"Thread self=%s. "
|
2016-09-16 02:51:22 -07:00
|
|
|
"Available domains [%s %s %s %s]. "
|
|
|
|
"Maybe it has been deleted or does not belong to your thread?",
|
|
|
|
|
|
|
|
(void *)obj_id,
|
|
|
|
type,
|
|
|
|
(int)domain,
|
|
|
|
(int)data->domain_stack[data->stack_top],
|
|
|
|
(int)data->local_domain,
|
|
|
|
(unsigned long)(obj_id & MASK_GENERATIONS),
|
|
|
|
(unsigned long)(obj_id >> SHIFT_ENTRY_ID) & (MAX_ENTRY_ID | MAX_TABLE_ID | MAX_MID_TABLE_ID),
|
|
|
|
(int)(obj_id >> REF_TAG_SHIFT) & 0x1,
|
|
|
|
(int)(obj_id >> SUPER_TAG_SHIFT) & 0x1,
|
2016-09-16 13:49:32 -07:00
|
|
|
tself,
|
2016-09-16 02:51:22 -07:00
|
|
|
(data->tables[0]) ? "0" : " ",
|
|
|
|
(data->tables[1]) ? "1" : " ",
|
|
|
|
(data->tables[2]) ? "2" : " ",
|
|
|
|
(data->tables[3]) ? "3" : " "
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-09 02:44:21 -07:00
|
|
|
_Eo_Object *
|
|
|
|
_eo_obj_pointer_get(const Eo_Id obj_id)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_EO_ID
|
|
|
|
_Eo_Id_Entry *entry;
|
|
|
|
_Eo_Object *ptr;
|
|
|
|
Generation_Counter generation;
|
|
|
|
Table_Index mid_table_id, table_id, entry_id;
|
|
|
|
Eo_Id tag_bit;
|
|
|
|
Eo_Id_Data *data;
|
|
|
|
Eo_Id_Table_Data *tdata;
|
|
|
|
unsigned char domain;
|
|
|
|
|
|
|
|
// NULL objects will just be sensibly ignored. not worth complaining
|
|
|
|
// every single time.
|
|
|
|
|
|
|
|
domain = (obj_id >> SHIFT_DOMAIN) & MASK_DOMAIN;
|
|
|
|
data = _eo_table_data_get();
|
|
|
|
tdata = _eo_table_data_table_get(data, domain);
|
2016-09-25 17:16:21 -07:00
|
|
|
if (!tdata) goto err;
|
2016-09-09 02:44:21 -07:00
|
|
|
|
|
|
|
|
|
|
|
if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED))
|
|
|
|
{
|
|
|
|
if (obj_id == tdata->cache.id)
|
|
|
|
{
|
|
|
|
ptr = tdata->cache.object;
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get tag bit to check later down below - pipelining
|
|
|
|
tag_bit = (obj_id) & MASK_OBJ_TAG;
|
|
|
|
if (!obj_id) goto err_null;
|
2016-09-25 17:16:21 -07:00
|
|
|
else if (!tag_bit) goto err;
|
2016-09-09 02:44:21 -07:00
|
|
|
|
|
|
|
EO_DECOMPOSE_ID(obj_id, mid_table_id, table_id, entry_id, generation);
|
|
|
|
|
|
|
|
// Check the validity of the entry
|
|
|
|
if (tdata->eo_ids_tables[mid_table_id])
|
|
|
|
{
|
|
|
|
_Eo_Ids_Table *tab = TABLE_FROM_IDS;
|
|
|
|
|
|
|
|
if (tab)
|
|
|
|
{
|
|
|
|
entry = &(tab->entries[entry_id]);
|
|
|
|
if (entry->active && (entry->generation == generation))
|
|
|
|
{
|
|
|
|
// Cache the result of that lookup
|
|
|
|
tdata->cache.object = entry->ptr;
|
|
|
|
tdata->cache.id = obj_id;
|
|
|
|
ptr = entry->ptr;
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-09-27 21:25:26 -07:00
|
|
|
eina_lock_take(&(_eo_table_data_shared_data->obj_lock));
|
2016-09-09 02:44:21 -07:00
|
|
|
if (obj_id == tdata->cache.id)
|
|
|
|
{
|
|
|
|
ptr = tdata->cache.object;
|
2016-09-27 21:25:26 -07:00
|
|
|
return ptr;
|
2016-09-09 02:44:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// get tag bit to check later down below - pipelining
|
|
|
|
tag_bit = (obj_id) & MASK_OBJ_TAG;
|
2016-09-25 17:16:21 -07:00
|
|
|
if (!obj_id) goto err_shared_null;
|
|
|
|
else if (!tag_bit) goto err_shared;
|
2016-09-09 02:44:21 -07:00
|
|
|
|
|
|
|
EO_DECOMPOSE_ID(obj_id, mid_table_id, table_id, entry_id, generation);
|
|
|
|
|
|
|
|
// Check the validity of the entry
|
|
|
|
if (tdata->eo_ids_tables[mid_table_id])
|
|
|
|
{
|
|
|
|
_Eo_Ids_Table *tab = TABLE_FROM_IDS;
|
|
|
|
|
|
|
|
if (tab)
|
|
|
|
{
|
|
|
|
entry = &(tab->entries[entry_id]);
|
|
|
|
if (entry->active && (entry->generation == generation))
|
|
|
|
{
|
|
|
|
// Cache the result of that lookup
|
|
|
|
tdata->cache.object = entry->ptr;
|
|
|
|
tdata->cache.id = obj_id;
|
|
|
|
ptr = entry->ptr;
|
2016-09-27 21:25:26 -07:00
|
|
|
// 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;
|
2016-09-09 02:44:21 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-25 17:16:21 -07:00
|
|
|
goto err_shared;
|
2016-09-09 02:44:21 -07:00
|
|
|
}
|
2016-09-25 17:16:21 -07:00
|
|
|
err_shared_null:
|
2016-09-27 21:25:26 -07:00
|
|
|
eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
|
2016-09-09 02:44:21 -07:00
|
|
|
err_null:
|
|
|
|
DBG("obj_id is NULL. Possibly unintended access?");
|
|
|
|
return NULL;
|
2016-09-25 17:16:21 -07:00
|
|
|
err_shared:
|
2016-09-27 21:25:26 -07:00
|
|
|
eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
|
2016-09-09 02:44:21 -07:00
|
|
|
err:
|
2016-09-16 02:51:22 -07:00
|
|
|
_eo_obj_pointer_invalid(obj_id, data, domain);
|
2016-09-09 02:44:21 -07:00
|
|
|
return NULL;
|
|
|
|
#else
|
|
|
|
return (_Eo_Object *) obj_id;
|
|
|
|
#endif
|
|
|
|
}
|
2016-09-27 21:25:26 -07:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|