1 #include "altmlookup.h"
5 mhashtable_t mlookup; //Global hash table
7 // Creates a machine lookup table with size =" size"
8 unsigned int mhashCreate(unsigned int size, double loadfactor) {
9 mhashlistnode_t *nodes;
10 // Allocate space for the hash table
11 if((nodes = calloc(size, sizeof(mhashlistnode_t))) == NULL) {
12 printf("Calloc error %s %d\n", __FILE__, __LINE__);
16 mlookup.table = nodes;
18 mlookup.threshold=size*loadfactor;
19 mlookup.mask = size -1;
20 mlookup.numelements = 0; // Initial number of elements in the hash
21 mlookup.loadfactor = loadfactor;
23 for(i=0; i<NUMLOCKS; i++)
24 mlookup.larray[i].lock=RW_LOCK_BIAS;
25 //Initialize the pthread_mutex variable
29 // Assign to keys to bins inside hash table
30 unsigned int mhashFunction(unsigned int key) {
31 return ( key & mlookup.mask) >>1;
34 // Insert value and key mapping into the hash table
35 void mhashInsert(unsigned int key, void *val) {
36 mhashlistnode_t *node;
38 if (mlookup.numelements > mlookup.threshold) {
40 unsigned int newsize = mlookup.size << 1;
44 unsigned int keyindex=key>>1;
45 volatile unsigned int * lockptr=&mlookup.larray[keyindex&LOCKMASK].lock;
46 while(!write_trylock(lockptr)) {
50 mhashlistnode_t * ptr = &mlookup.table[keyindex&mlookup.mask];
51 atomic_inc(&mlookup.numelements);
56 } else { // Insert in the beginning of linked list
57 node = calloc(1, sizeof(mhashlistnode_t));
60 node->next = ptr->next;
63 write_unlock(lockptr);
66 // Return val for a given key in the hash table
67 void *mhashSearch(unsigned int key) {
70 unsigned int keyindex=key>>1;
71 volatile unsigned int * lockptr=&mlookup.larray[keyindex&LOCKMASK].lock;
73 while(!read_trylock(lockptr)) {
77 mhashlistnode_t *node = &mlookup.table[keyindex&mlookup.mask];
80 if(node->key == key) {
91 // Remove an entry from the hash table
92 unsigned int mhashRemove(unsigned int key) {
94 mhashlistnode_t *prev;
95 mhashlistnode_t *ptr, *node;
97 unsigned int keyindex=key>>1;
98 volatile unsigned int * lockptr=&mlookup.larray[keyindex&LOCKMASK].lock;
100 while(!write_trylock(lockptr)) {
104 mhashlistnode_t *curr = &mlookup.table[keyindex&mlookup.mask];
106 for (; curr != NULL; curr = curr->next) {
107 if (curr->key == key) {
108 atomic_dec(&(mlookup.numelements));
109 if ((curr == &ptr[index]) && (curr->next == NULL)) {
112 } else if ((curr == &ptr[index]) && (curr->next != NULL)) {
113 curr->key = curr->next->key;
114 curr->val = curr->next->val;
116 curr->next = curr->next->next;
119 prev->next = curr->next;
122 write_unlock(lockptr);
127 write_unlock(lockptr);
132 void mhashResize(unsigned int newsize) {
133 mhashlistnode_t *node, *curr;
135 unsigned int i,index;
138 for(i=0; i<NUMLOCKS; i++) {
139 volatile unsigned int * lockptr=&mlookup.larray[i].lock;
141 while(!write_trylock(lockptr)) {
146 if (mlookup.numelements < mlookup.threshold) {
147 //release lock and return
148 for(i=0; i<NUMLOCKS; i++) {
149 volatile unsigned int * lockptr=&mlookup.larray[i].lock;
150 write_unlock(lockptr);
155 mhashlistnode_t * ptr = mlookup.table;
156 unsigned int oldsize = mlookup.size;
158 if((node = calloc(newsize, sizeof(mhashlistnode_t))) == NULL) {
159 printf("Calloc error %s %d\n", __FILE__, __LINE__);
163 mlookup.table = node;
164 mlookup.size = newsize;
165 mlookup.threshold=newsize*mlookup.loadfactor;
166 mask=mlookup.mask = newsize -1;
168 for(i = 0; i < oldsize; i++) {
173 mhashlistnode_t *tmp,*next;
175 if ((key=curr->key) == 0) {
179 index = (key >> 1) & mask;
180 tmp=&mlookup.table[index];
189 NOTE: Add this case if you change this...
190 This case currently never happens because of the way things rehash....
192 mhashlistnode_t *newnode = calloc(1, sizeof(mhashlistnode_t));
193 newnode->key = curr->key;
194 newnode->val = curr->val;
195 newnode->next = tmp->next;
199 curr->next=tmp->next;
208 for(i=0; i<NUMLOCKS; i++) {
209 volatile unsigned int * lockptr=&mlookup.larray[i].lock;
210 write_unlock(lockptr);
215 unsigned int *mhashGetKeys(unsigned int *numKeys) {
218 mhashlistnode_t *curr;
220 pthread_mutex_lock(&mlookup.locktable);
222 *numKeys = mlookup.numelements;
223 keys = calloc(*numKeys, sizeof(unsigned int));
226 for (i = 0; i < mlookup.size; i++) {
227 if (mlookup.table[i].key != 0) {
228 curr = &mlookup.table[i];
229 while (curr != NULL) {
230 keys[keyindex++] = curr->key;
236 if (keyindex != *numKeys)
237 printf("mhashGetKeys(): WARNING: incorrect mlookup.numelements value!\n");
239 pthread_mutex_unlock(&mlookup.locktable);