fix mutex_trylock bug
[c11tester.git] / hashtable.h
index 16744bb45f39e89a165bf12a804c96cad466123b..b7cac67410c287004e9861d14db91c4afc0367dd 100644 (file)
@@ -62,7 +62,7 @@ inline bool default_equals(_Key key1, _Key key2) {
  * @tparam _free   Provide your own 'free' for the table, or default to
  *                 snapshotting.
  */
-template<typename _Key, typename _Val, typename _KeyInt, int _Shift = 0, void * (* _malloc)(size_t) = snapshot_malloc, void * (* _calloc)(size_t, size_t) = snapshot_calloc, void (*_free)(void *) = snapshot_free, unsigned int (*hash_function)(_Key) = default_hash_function<_Key, _Shift, _KeyInt>, bool (*equals)(_Key, _Key) = default_equals<_Key> >
+template<typename _Key, typename _Val, typename _KeyInt, int _Shift = 0, void * (*_malloc)(size_t) = snapshot_malloc, void * (*_calloc)(size_t, size_t) = snapshot_calloc, void (*_free)(void *) = snapshot_free, unsigned int (*hash_function)(_Key) = default_hash_function<_Key, _Shift, _KeyInt>, bool (*equals)(_Key, _Key) = default_equals<_Key> >
 class HashTable {
 public:
        /**
@@ -81,7 +81,7 @@ public:
                capacitymask = initialcapacity - 1;
 
                threshold = (unsigned int)(initialcapacity * loadfactor);
-               size = 0;                                                       // Initial number of elements in the hash
+               size = 0;       // Initial number of elements in the hash
        }
 
        /** @brief Hash table destructor */
@@ -182,24 +182,38 @@ public:
                        resize(capacity << 1);
 
                struct hashlistnode<_Key, _Val> *search;
+               struct hashlistnode<_Key, _Val> *first = NULL;
 
-               unsigned int index = hash_function(key);
+               unsigned int index = hash_function(key) & capacitymask;
+               unsigned int oindex = index;
                do {
-                       index &= capacitymask;
                        search = &table[index];
                        if (!search->key) {
                                //key is null, probably done
-                               break;
+                               if (!search->val)
+                                       break;
+                               if (first == NULL)
+                                       first = search;
                        }
                        if (equals(search->key, key)) {
                                search->val = val;
                                return;
                        }
-                       index++;
+                       index = (index + 1) & capacitymask;
+                       if (index == oindex) {
+                               if (first == NULL)
+                                       exit(-1);
+                               break;
+                       }
                } while (true);
 
-               search->key = key;
-               search->val = val;
+               if (first != NULL) {
+                       first->key = key;
+                       first->val = val;
+               } else {
+                       search->key = key;
+                       search->val = val;
+               }
                size++;
        }
 
@@ -220,7 +234,7 @@ public:
                }
 
                unsigned int oindex = hash_function(key) & capacitymask;
-               unsigned int index=oindex;
+               unsigned int index = oindex;
                do {
                        search = &table[index];
                        if (!search->key) {
@@ -244,6 +258,7 @@ public:
         */
        _Val remove(_Key key) {
                struct hashlistnode<_Key, _Val> *search;
+               struct hashlistnode<_Key, _Val> *replace;
 
                /* HashTable cannot handle 0 as a key */
                if (!key) {
@@ -266,14 +281,40 @@ public:
                        if (!search->key) {
                                if (!search->val)
                                        break;
-                       } else
-                       if (equals(search->key, key)) {
-                               _Val v=search->val;
-                               //empty out this bin
-                               search->val=(_Val) 1;
-                               search->key=0;
-                               size--;
-                               return v;
+                       } else {
+                               // The case where an item is found
+                               if (equals(search->key, key)) {
+                                       unsigned int j = index;
+                                       _Val v = search->val;
+                                       size--;
+
+                                       // Idea: keep bins contiguous
+                                       while (true) {
+                                               search->val = 0;
+                                               search->key = 0;
+
+                                               while (true) {
+                                                       j = (j + 1) & capacitymask;
+                                                       replace = &table[j];
+
+                                                       if (!replace->key && !replace->val) {
+                                                               return v;
+                                                       }
+
+                                                       unsigned int hash = hash_function(replace->key) & capacitymask;
+                                                       if (index <= j && index < hash && hash <= j)
+                                                               continue;
+                                                       else if (index > j && (index < hash || hash <= j) )
+                                                               continue;
+                                                       else
+                                                               break;
+                                               }
+
+                                               table[index] = table[j];
+                                               index = j;
+                                               search = &table[index];
+                                       }
+                               }
                        }
                        index++;
                } while (true);
@@ -284,6 +325,9 @@ public:
                return size;
        }
 
+       bool isEmpty() {
+               return size == 0;
+       }
 
        /**
         * @brief Check whether the table contains a value for the given key
@@ -327,7 +371,7 @@ public:
                        exit(EXIT_FAILURE);
                }
 
-               table = newtable;                                                                                       // Update the global hashtable upon resize()
+               table = newtable;       // Update the global hashtable upon resize()
                capacity = newsize;
                capacitymask = newsize - 1;
 
@@ -353,7 +397,7 @@ public:
                        search->val = bin->val;
                }
 
-               _free(oldtable);                                                                                                // Free the memory of the old hash table
+               _free(oldtable);        // Free the memory of the old hash table
        }
        double getLoadFactor() {return loadfactor;}
        unsigned int getCapacity() {return capacity;}
@@ -367,4 +411,4 @@ private:
        double loadfactor;
 };
 
-#endif/* __HASHTABLE_H__ */
+#endif /* __HASHTABLE_H__ */