Tommy Multi Indexing

Tommy provides only partial iterator support with the "foreach" functions.

If you need real iterators you have to insert all the objects also in a tommy_list, and use the list as iterator.

This technique allows to keep track of the insertion order with the list, and provides more search possibilities using different data structures for different search keys.

See the next example, for a objects inserted in a tommy_list, and in two tommy_hashdyn using different keys.

struct object {
// data fields
int value_0;
int value_1;
// for containers
tommy_node list_node; // node for the list
tommy_node hash_node_0; // node for the first hash
tommy_node hash_node_1; // node for the second hash
// search function for value_1
int search_1(const void* arg, const void* obj)
return *(const int*)arg != ((const struct object*)obj)->value_1;
// initializes the hash tables and the list
// creates an object and inserts it
struct object* obj = malloc(sizeof(struct object));
obj->value_0 = ...;
obj->value_1 = ...;
// inserts in the first hash table
tommy_hashdyn_insert(&hash_0, &obj->hash_node_0, obj, tommy_inthash_u32(obj->value_0));
// inserts in the second hash table
tommy_hashdyn_insert(&hash_1, &obj->hash_node_1, obj, tommy_inthash_u32(obj->value_1));
// inserts in the list
tommy_list_insert_tail(&list, &obj->list_node, obj);
// searches an object by value_1 and deletes it
int value_to_find = ...;
struct object* obj = tommy_hashdyn_search(&hash_1, search_1, &value_to_find, tommy_inthash_u32(value_to_find));
if (obj) {
// if found removes all the references
tommy_hashdyn_remove_existing(&hash_0, &obj->hash_node_0);
tommy_hashdyn_remove_existing(&hash_1, &obj->hash_node_1);
tommy_list_remove_existing(&list, &obj->list_node);
// complex iterator logic
tommy_node* i = tommy_list_head(&list);
while (i != 0) {
// get the object
struct object* obj = i->data;
// go to the next element
i = i->next;
// go to the prev element
i = i->prev;
// deallocates the objects iterating the list
tommy_list_foreach(&list, free);
// deallocates the hash tables