724086d1ec255a2665777a7f1b6fc271306bc4d4
[IRC.git] / Robust / src / Runtime / DSTM / interface / clookup.c
1 #include "clookup.h"
2 #define INLINE    inline __attribute__((always_inline))
3
4 chashtable_t *chashCreate(unsigned int size, float loadfactor) {
5   chashtable_t *ctable;
6   chashlistnode_t *nodes;
7   int i;
8
9   if((ctable = calloc(1, sizeof(chashtable_t))) == NULL) {
10     printf("Calloc error %s %d\n", __FILE__, __LINE__);
11     return NULL;
12   }
13
14   // Allocate space for the hash table
15   if((nodes = calloc(size, sizeof(chashlistnode_t))) == NULL) {
16     printf("Calloc error %s %d\n", __FILE__, __LINE__);
17     free(ctable);
18     return NULL;
19   }
20
21   ctable->table = nodes;
22   ctable->size = size;
23   ctable->mask = (size << 1)-1;
24   ctable->numelements = 0; // Initial number of elements in the hash
25   ctable->loadfactor = loadfactor;
26
27   return ctable;
28 }
29
30 //Finds the right bin in the hash table
31 static INLINE unsigned int chashFunction(chashtable_t *table, unsigned int key) {
32   return ( key & (table->mask))>>1; //throw away low order bit
33 }
34
35 //Store objects and their pointers into hash
36 unsigned int chashInsert(chashtable_t *table, unsigned int key, void *val) {
37   unsigned int newsize;
38   int index;
39   chashlistnode_t *ptr, *node;
40
41   if(table->numelements > (table->loadfactor * table->size)) {
42     //Resize
43     newsize = table->size << 1;
44     chashResize(table,newsize);
45   }
46
47   ptr = table->table;
48   table->numelements++;
49   index = chashFunction(table, key);
50 #ifdef DEBUG
51   printf("chashInsert(): DEBUG -> index = %d, key = %d, val = %x\n", index, key, val);
52 #endif
53   if(ptr[index].next == NULL && ptr[index].key == 0) {  // Insert at the first position in the hashtable
54     ptr[index].key = key;
55     ptr[index].val = val;
56   } else { // Insert in the beginning of linked list
57     if ((node = calloc(1, sizeof(chashlistnode_t))) == NULL) {
58       printf("Calloc error %s, %d\n", __FILE__, __LINE__);
59       return 1;
60     }
61     node->key = key;
62     node->val = val;
63     node->next = ptr[index].next;
64     ptr[index].next = node;
65   }
66   return 0;
67 }
68
69 // Search for an address for a given oid
70 INLINE void * chashSearch(chashtable_t *table, unsigned int key) {
71   //REMOVE HASH FUNCTION CALL TO MAKE SURE IT IS INLINED HERE
72   chashlistnode_t *node = &table->table[(key & table->mask)>>1];
73
74   do {
75     if(node->key == key) {
76       return node->val;
77     }
78     node = node->next;
79   } while(node != NULL);
80
81   return NULL;
82 }
83
84 unsigned int chashRemove(chashtable_t *table, unsigned int key) {
85   return chashRemove2(table, key)==NULL;
86
87 }
88
89 void * chashRemove2(chashtable_t *table, unsigned int key) {
90   int index;
91   chashlistnode_t *curr, *prev;
92   chashlistnode_t *ptr, *node;
93   void *value;
94
95   ptr = table->table;
96   index = chashFunction(table,key);
97   curr = &ptr[index];
98
99   for (; curr != NULL; curr = curr->next) {
100     if (curr->key == key) {         // Find a match in the hash table
101       table->numelements--;  // Decrement the number of elements in the global hashtable
102       if ((curr == &ptr[index]) && (curr->next == NULL)) {  // Delete the first item inside the hashtable with no linked list of chashlistnode_t
103         curr->key = 0;
104         value=curr->val;
105         curr->val = NULL;
106       } else if ((curr == &ptr[index]) && (curr->next != NULL)) { //Delete the first item with a linked list of chashlistnode_t  connected
107         curr->key = curr->next->key;
108         value=curr->val;
109         curr->val = curr->next->val;
110         node = curr->next;
111         curr->next = curr->next->next;
112         free(node);
113       } else {                                          // Regular delete from linked listed
114         prev->next = curr->next;
115         value=curr->val;
116         free(curr);
117       }
118       return value;
119     }
120     prev = curr;
121   }
122   return NULL;
123 }
124
125 unsigned int chashResize(chashtable_t *table, unsigned int newsize) {
126   chashlistnode_t *node, *ptr, *curr, *next;    // curr and next keep track of the current and the next chashlistnodes in a linked list
127   unsigned int oldsize;
128   int isfirst;    // Keeps track of the first element in the chashlistnode_t for each bin in hashtable
129   int i,index;
130   chashlistnode_t *newnode;
131
132   ptr = table->table;
133   oldsize = table->size;
134
135   if((node = calloc(newsize, sizeof(chashlistnode_t))) == NULL) {
136     printf("Calloc error %s %d\n", __FILE__, __LINE__);
137     return 1;
138   }
139
140   table->table = node;          //Update the global hashtable upon resize()
141   table->size = newsize;
142   table->mask = (newsize << 1)-1;
143
144   for(i = 0; i < oldsize; i++) {                        //Outer loop for each bin in hash table
145     curr = &ptr[i];
146     isfirst = 1;
147     while (curr != NULL) {                      //Inner loop to go through linked lists
148       if (curr->key == 0) {             //Exit inner loop if there the first element for a given bin/index is NULL
149         break;                  //key = val =0 for element if not present within the hash table
150       }
151       next = curr->next;
152
153       index = chashFunction(table, curr->key);
154 #ifdef DEBUG
155       printf("DEBUG(resize) -> index = %d, key = %d, val = %x\n", index, curr->key, curr->val);
156 #endif
157       // Insert into the new table
158       if(table->table[index].next == NULL && table->table[index].key == 0) {
159         table->table[index].key = curr->key;
160         table->table[index].val = curr->val;
161         table->numelements++;
162       } else {
163         if((newnode = calloc(1, sizeof(chashlistnode_t))) == NULL) {
164           printf("Calloc error %s, %d\n", __FILE__, __LINE__);
165           return 1;
166         }
167         newnode->key = curr->key;
168         newnode->val = curr->val;
169         newnode->next = table->table[index].next;
170         table->table[index].next = newnode;
171         table->numelements++;
172       }
173
174       //free the linked list of chashlistnode_t if not the first element in the hash table
175       if (isfirst != 1) {
176         free(curr);
177       }
178
179       isfirst = 0;
180       curr = next;
181     }
182   }
183
184   free(ptr);            //Free the memory of the old hash table
185   return 0;
186 }
187
188 //Delete the entire hash table
189 void chashDelete(chashtable_t *ctable) {
190   int i, isFirst;
191   chashlistnode_t *ptr, *curr, *next;
192   ptr = ctable->table;
193
194   for(i=0 ; i<ctable->size ; i++) {
195     curr = &ptr[i];
196     isFirst = 1 ;
197     while(curr  != NULL) {
198       next = curr->next;
199       if(isFirst != 1) {
200         free(curr);
201       }
202       isFirst = 0;
203       curr = next;
204     }
205   }
206
207   free(ptr);
208   ptr = NULL;
209   free(ctable);
210   ctable = NULL;
211 }