* occur when accessing with the old id.
*
* Each table is composed of:
- * - pointers to the objects
- * - generations assigned to the objects
- * - a boolean table indicating if an entry is active
+ * - entries composed of
+ * - a pointer to the object
+ * - a flag indicating if the entry is active
+ * - a generation assigned to the object
* - an index 'start' indicating which entry is the next one to use.
* - a queue that will help us to store the unused entries. It stores only the
* entries that have been used at least one time. The entries that have
return (void *)(((unsigned char *)ptr) + MEM_HEADER_SIZE);
#else
return malloc(size);
-#endif
+#endif
}
static void *
#endif
}
+/* Entry */
+typedef struct
+{
+ /* Pointer to the object */
+ _Eo *ptr;
+ /* Active flag */
+ unsigned int active : 1;
+ /* Generation */
+ unsigned int generation : BITS_FOR_GENERATION_COUNTER;
+} _Eo_Id_Entry;
+
/* Table */
typedef struct
{
- /* Pointers of objects stored in table */
- _Eo *ptrs[MAX_IDS_PER_TABLE];
- /* Generations */
- Table_Index generation[MAX_IDS_PER_TABLE];
- /* Active flags */
- char active[MAX_IDS_PER_TABLE >> 3];
+ /* Entries of the table holding real pointers and generations */
+ _Eo_Id_Entry entries[MAX_IDS_PER_TABLE];
/* Queue to handle free entries */
Eina_Trash *queue;
/* Indicates where start the "never used" entries */
/* Next generation to use when assigning a new entry to a Eo pointer */
Table_Index _eo_generation_counter;
-/* Internal macro for active flag manipulation */
-#define _ENTRY_ACTIVE_DO_OP(table, id_in_table, op) \
- (table)->active[(id_in_table) >> 3] op (1 << ((id_in_table) % 8))
-
-/* Macro that indicates if an entry is active */
-#define IS_ENTRY_ACTIVE(table, id_in_table) \
- (_ENTRY_ACTIVE_DO_OP(table, id_in_table, &))
-/* Macro that activates an entry */
-#define ACTIVATE_ENTRY(table, id_in_table) \
- _ENTRY_ACTIVE_DO_OP(table, id_in_table, |=)
-/* Macro that de-activates an entry */
-#define DEACTIVATE_ENTRY(table, id_in_table) \
- _ENTRY_ACTIVE_DO_OP(table, id_in_table, &=~)
-
/* Macro used to compose an Eo id */
#define EO_COMPOSE_ID(TABLE, INTER_TABLE, ENTRY, GENERATION) \
(Eo_Id)(((TABLE & (MAX_IDS_TABLES - 1)) << SHIFT_FOR_IDS_TABLE) | \
_eo_obj_pointer_get(const Eo_Id obj_id)
{
#ifdef HAVE_EO_ID
+ _Eo_Id_Entry *entry;
Table_Index table_id, int_table_id, entry_id, generation;
EO_DECOMPOSE_ID((Table_Index) obj_id, table_id, int_table_id, entry_id, generation);
/* Checking the validity of the entry */
- if (_eo_ids_tables[table_id] && ID_TABLE && IS_ENTRY_ACTIVE(ID_TABLE, entry_id) &&
- ID_TABLE->generation[entry_id] == generation)
- return ID_TABLE->ptrs[entry_id];
+ if (_eo_ids_tables[table_id] && ID_TABLE)
+ {
+ entry = &(ID_TABLE->entries[entry_id]);
+ if (entry && entry->active && (entry->generation == generation))
+ return entry->ptr;
+ }
ERR("obj_id %p is not pointing to a valid object. Maybe it has already been freed.",
(void *)obj_id);
_eo_id_allocate(const _Eo *obj)
{
#ifdef HAVE_EO_ID
- Eo_Id ret = 0;
+ _Eo_Id_Entry *entry = NULL;
for (Table_Index table_id = 1; table_id < MAX_IDS_TABLES; table_id++)
{
if (!_eo_ids_tables[table_id])
}
for (Table_Index int_table_id = 0; int_table_id < MAX_IDS_INTER_TABLES; int_table_id++)
{
- _Eo **ptr;
if (!ID_TABLE)
{
/* We allocate a new intermediate table */
ID_TABLE = _eo_id_mem_calloc(1, sizeof(_Eo_Ids_Table));
eina_trash_init(&(ID_TABLE->queue));
/* We select directly the first entry of the new table */
- ptr = &(ID_TABLE->ptrs[0]);
+ entry = &(ID_TABLE->entries[0]);
ID_TABLE->start = 1;
}
else
{
/* We try to pop from the queue an unused entry */
- ptr = (_Eo **)eina_trash_pop(&(ID_TABLE->queue));
+ entry = (_Eo_Id_Entry *)eina_trash_pop(&(ID_TABLE->queue));
}
- if (!ptr && ID_TABLE->start < MAX_IDS_PER_TABLE)
+ if (!entry && ID_TABLE->start < MAX_IDS_PER_TABLE)
{
/* No more unused entries in the trash but still empty entries in the table */
- ptr = &(ID_TABLE->ptrs[ID_TABLE->start]);
+ entry = &(ID_TABLE->entries[ID_TABLE->start]);
ID_TABLE->start++;
}
- if (ptr)
+ if (entry)
{
/* An entry was found - need to find the entry id and fill it */
- Table_Index id = ptr - ID_TABLE->ptrs;
- ID_TABLE->generation[id] = _eo_generation_counter;
- ACTIVATE_ENTRY(ID_TABLE, id);
- *ptr = (_Eo *)obj;
- ret = EO_COMPOSE_ID(table_id, int_table_id, id, _eo_generation_counter);
+ entry->ptr = (_Eo *)obj;
+ entry->active = 1;
+ entry->generation = _eo_generation_counter;
_eo_generation_counter++;
_eo_generation_counter %= MAX_GENERATIONS;
- return ret;
+ return EO_COMPOSE_ID(table_id, int_table_id,
+ (entry - ID_TABLE->entries),
+ entry->generation);
}
}
}
- return ret;
+ return 0;
#else
return (Eo_Id)obj;
#endif
_eo_id_release(const Eo_Id obj_id)
{
#ifdef HAVE_EO_ID
+ _Eo_Id_Entry *entry;
Table_Index table_id, int_table_id, entry_id, generation;
EO_DECOMPOSE_ID((Table_Index) obj_id, table_id, int_table_id, entry_id, generation);
/* Checking the validity of the entry */
- if (!_eo_ids_tables[table_id]) goto error;
- if (!ID_TABLE) goto error;
- if (ID_TABLE->generation[entry_id] != generation) goto error;
-
- /* Disable the entry */
- DEACTIVATE_ENTRY(ID_TABLE, entry_id);
- /* Push the entry into the queue */
- eina_trash_push(&(ID_TABLE->queue), &(ID_TABLE->ptrs[entry_id]));
-
- return;
+ if (_eo_ids_tables[table_id] && ID_TABLE)
+ {
+ entry = &(ID_TABLE->entries[entry_id]);
+ if (entry && entry->active && (entry->generation == generation))
+ {
+ /* Disable the entry */
+ entry->active = 0;
+ /* Push the entry into the queue */
+ eina_trash_push(&(ID_TABLE->queue), entry);
+ return;
+ }
+ }
-error:
ERR("obj_id %p is not pointing to a valid object. Maybe it has already been freed.", (void *)obj_id);
#else
(void) obj_id;
void
_eo_print()
{
+ _Eo_Id_Entry *entry;
unsigned long obj_number = 0;
for (Table_Index table_id = 0; table_id < MAX_IDS_TABLES; table_id++)
{
{
for (Table_Index entry_id = 0; entry_id < MAX_IDS_PER_TABLE; entry_id++)
{
- if (IS_ENTRY_ACTIVE(ID_TABLE, entry_id))
+ entry = &(ID_TABLE->entries[entry_id]);
+ if (entry->active)
{
printf("%ld: %p -> (%p, %p, %p, %p)\n", obj_number++,
- ID_TABLE->ptrs[entry_id],
+ entry->ptr,
(void *)table_id, (void *)int_table_id, (void *)entry_id,
- (void *)ID_TABLE->generation[entry_id]);
+ (void *)entry->generation);
}
}
}