source: proiecte/PDAD/trunk/nodeslocation/mpi/hashmap.c @ 154

Last change on this file since 154 was 154, checked in by (none), 14 years ago

PDAD project

File size: 4.9 KB
Line 
1/*
2 * hashmap.c
3 * Copyright (c) 2009 Vedant Kumar
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23#include <stdio.h>
24#include <string.h>
25#include "hashmap_public.h"
26
27struct key_val_map {
28    key k;
29    val v;
30};
31
32struct hashmap {
33    key_val_map *map;
34    uint32_t size;
35    uint32_t capacity;
36    uint32_t (*hash_fn)(key);
37    bool (*eq_fn)(key, key);
38#ifdef HMAP_DESTRUCTORS
39    void (*del_fn)(val);
40#endif
41#ifdef HMAP_THREAD_SAFE
42    sem_t lock;
43#endif
44};
45
46// hashmaps need a hash function, an equality function, and a destructor
47hashmap* mk_hmap(uint32_t (*hash_fn)(key),
48                 bool (*eq_fn)(key, key)
49#ifdef HMAP_DESTRUCTORS
50                 , void (*del_fn)(val)
51#endif
52                 ) {
53   
54    hashmap* hmap = (hashmap*) malloc(sizeof(hashmap));
55    hmap->map = (key_val_map*) malloc(sizeof(key_val_map) * HMAP_PRESET_SIZE);
56    bzero(hmap->map, sizeof(key_val_map) * HMAP_PRESET_SIZE); 
57    hmap->size = 0;
58    hmap->capacity = HMAP_PRESET_SIZE;
59    hmap->hash_fn = hash_fn;
60    hmap->eq_fn = eq_fn;
61#ifdef HMAP_DESTRUCTORS
62    hmap->del_fn = del_fn;
63#endif
64#ifdef HMAP_THREAD_SAFE
65    sem_init(&hmap->lock, 0, 1);
66#endif
67    return hmap;
68}
69
70void free_hmap(hashmap* hmap) {
71#ifdef HMAP_THREAD_SAFE
72    sem_wait(&hmap->lock);
73#endif
74
75#ifdef HMAP_DESTRUCTORS
76    static uint32_t it;
77    for (it=0; it < hmap->size; ++it) {
78        if (hmap->map[it].v != NULL) {
79            hmap->del_fn(hmap->map[it].v);
80        }
81    }
82#endif
83
84    free(hmap->map);
85       
86#ifdef HMAP_THREAD_SAFE
87    sem_post(&hmap->lock);
88#endif
89
90    free(hmap);
91}
92
93static void __oa_hmap_add(key_val_map* map, uint32_t size, 
94                         uint32_t (*hash_fn)(key),
95                         key in, val out) {
96    static uint32_t hash;
97    hash = hash_fn(in) % size;
98       
99    uint32_t count = 0; 
100    while (map[hash].k != NULL) {
101        hash = (hash + 1) % size;
102        count++; 
103        if (count > size) { 
104            fprintf(stdout, "Hashmap has no free entries \n"); 
105            exit(0);
106        }
107    }
108       
109    map[hash].k = in;
110    map[hash].v = out;
111       
112}
113
114bool __hmap_add(hashmap* hmap, key in, val out) {
115#ifdef HMAP_THREAD_SAFE
116    sem_wait(&hmap->lock);
117#endif
118
119    // performace degrades after a certain load
120    if (((float) hmap->size) / hmap->capacity > 0.70) {
121        key_val_map* temp = (key_val_map*) malloc(sizeof(key_val_map) * hmap->capacity * HMAP_GROWTH_RATE);
122        if (temp != NULL) {
123            //hmap->capacity *= HMAP_GROWTH_RATE;
124        } else {
125#ifdef HMAP_THREAD_SAFE
126            sem_post(&hmap->lock);
127#endif
128            // we're out of memory
129            return false;
130        }
131       
132        // init new hashmap
133        bzero(temp, sizeof(key_val_map) * hmap->capacity * HMAP_GROWTH_RATE);
134
135        // re-posn all elements
136        static uint32_t it;
137        for (it=0; it < hmap->capacity; ++it) {
138            if (hmap->map[it].k != NULL) {
139                __oa_hmap_add(temp, hmap->capacity * HMAP_GROWTH_RATE, hmap->hash_fn, hmap->map[it].k, hmap->map[it].v);
140            }
141        }
142               
143        // swap out the old map with the new one
144        free(hmap->map);
145        hmap->map = temp;
146        hmap->capacity *= HMAP_GROWTH_RATE;
147    }
148       
149    __oa_hmap_add(hmap->map, hmap->capacity, hmap->hash_fn, in, out);
150    hmap->size += 1;
151
152#ifdef HMAP_THREAD_SAFE
153    sem_post(&hmap->lock);
154#endif
155    return true;
156}
157
158val __hmap_get(hashmap* hmap, key in) {
159#ifdef HMAP_THREAD_SAFE
160    sem_wait(&hmap->lock);
161#endif
162
163    static uint32_t hash;
164    hash = hmap->hash_fn(in) % hmap->capacity;
165   
166    while (hmap->map[hash].k != NULL) {
167        if (hmap->eq_fn(in, hmap->map[hash].k)) {
168#ifdef HMAP_THREAD_SAFE
169            sem_post(&hmap->lock);
170#endif                 
171            return hmap->map[hash].v;
172        }
173               
174        hash = (hash + 1) % hmap->capacity;
175    }
176
177       
178#ifdef HMAP_THREAD_SAFE
179    sem_post(&hmap->lock);
180#endif
181       
182    return NULL;
183}
184
185#ifdef HMAP_MAKE_HASHFN
186// Robert Jenkins' 32 bit integer hash function
187uint32_t int_hash_fn(key in) {
188    static uint32_t a;
189    a = *((uint32_t*) in);
190       
191    a = (a+0x7ed55d16) + (a<<12);
192    a = (a^0xc761c23c) ^ (a>>19);
193    a = (a+0x165667b1) + (a<<5);
194    a = (a+0xd3a2646c) ^ (a<<9);
195    a = (a+0xfd7046c5) + (a<<3);
196    a = (a^0xb55a4f09) ^ (a>>16);
197       
198    return a;
199}
200
201bool int_eq_fn(key a, key b) {
202    return *((uint32_t*) a) == *((uint32_t*) b) ? true : false;
203}
204
205#endif
Note: See TracBrowser for help on using the repository browser.