usermode/library/common/cuckoo_hash/PointerHashInline.h

00001 /*
00002  *  PointerHash.h
00003  *  CuckooHashTable
00004  *
00005  *  Created by Steve Dekorte on 2009 04 28.
00006  *  Copyright 2009 __MyCompanyName__. All rights reserved.
00007  *
00008  */
00009 
00010 #ifndef POINTERHASH_DEFINED
00011 #define POINTERHASH_DEFINED 1
00012 
00013 #include "Common.h"
00014 #include <stddef.h>
00015 #include "PortableStdint.h"
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <assert.h>
00020 
00021 
00022 #ifdef __cplusplus
00023 extern "C" {
00024 #endif
00025 
00026 #define POINTERHASH_MAXLOOP 10
00027 
00028 #include "PointerHash_struct.h"
00029 
00030 static inline BASEKIT_API PointerHash *PointerHash_new(void);
00031 static inline BASEKIT_API void PointerHash_copy_(PointerHash *self, const PointerHash *other);
00032 static inline BASEKIT_API PointerHash *PointerHash_clone(PointerHash *self);
00033 static inline BASEKIT_API void PointerHash_free(PointerHash *self);
00034 
00035 static inline BASEKIT_API void PointerHash_at_put_(PointerHash *self, void *k, void *v);
00036 static inline BASEKIT_API void PointerHash_removeKey_(PointerHash *self, void *k);
00037 static inline BASEKIT_API size_t PointerHash_size(PointerHash *self); // actually the keyCount
00038 
00039 static inline BASEKIT_API size_t PointerHash_memorySize(PointerHash *self);
00040 static inline BASEKIT_API void PointerHash_compact(PointerHash *self);
00041 
00042 // --- private methods ----------------------------------------
00043 
00044 static inline BASEKIT_API void PointerHash_setSize_(PointerHash *self, size_t size); 
00045 static inline BASEKIT_API void PointerHash_insert_(PointerHash *self, PointerHashRecord *x); 
00046 static inline BASEKIT_API void PointerHash_grow(PointerHash *self); 
00047 static inline BASEKIT_API void PointerHash_shrinkIfNeeded(PointerHash *self); 
00048 static inline BASEKIT_API void PointerHash_shrink(PointerHash *self); 
00049 static inline BASEKIT_API void PointerHash_show(PointerHash *self);
00050 static inline BASEKIT_API void PointerHash_updateMask(PointerHash *self); 
00051 
00052 #undef IOINLINE
00053 #define IOINLINE static inline
00054 
00055 // -----------------------------------
00056 
00057 #define PointerHashRecords_recordAt_(records, pos) (PointerHashRecord *)(records + (pos * sizeof(PointerHashRecord)))
00058 
00059 
00060 IOINLINE PointerHashRecord *PointerHash_record1_(PointerHash *self, void *k)
00061 {
00062         // the ~| 0x1 before the mask ensures an odd pos
00063         intptr_t kk = (intptr_t)k;
00064         size_t pos = ((kk^(kk>>4)) | 0x1) & self->mask;
00065         return PointerHashRecords_recordAt_(self->records, pos);
00066 }
00067 
00068 IOINLINE PointerHashRecord *PointerHash_record2_(PointerHash *self, void *k)
00069 {
00070         // the | 0x1 before the mask ensures an even pos
00071         intptr_t kk = (intptr_t)k;
00072         //size_t pos = (((kk^(kk/33)) << 1)) & self->mask;
00073         size_t pos = (kk << 1) & self->mask;
00074         return PointerHashRecords_recordAt_(self->records, pos);
00075 }
00076 
00077 IOINLINE void *PointerHash_at_(PointerHash *self, void *k)
00078 {
00079         PointerHashRecord *r;
00080         
00081         r = PointerHash_record1_(self, k);
00082         if(k == r->k) return r->v;
00083         
00084         r = PointerHash_record2_(self, k);      
00085         if(k == r->k) return r->v;
00086         
00087         return 0x0;
00088 }
00089 
00090 IOINLINE size_t PointerHash_count(PointerHash *self)
00091 {
00092         return self->keyCount;
00093 }
00094 
00095 IOINLINE int PointerHashKey_hasKey_(PointerHash *self, void *key)
00096 {
00097         return PointerHash_at_(self, key) != NULL;
00098 }
00099 
00100 IOINLINE void PointerHash_at_put_(PointerHash *self, void *k, void *v)
00101 {
00102         PointerHashRecord *r;
00103         
00104         r = PointerHash_record1_(self, k);
00105         
00106         if(!r->k)
00107         {
00108                 r->k = k;
00109                 r->v = v;
00110                 self->keyCount ++;
00111                 return;
00112         }
00113         
00114         if(r->k == k)
00115         {
00116                 r->v = v;
00117                 return;
00118         }
00119 
00120         r = PointerHash_record2_(self, k);
00121 
00122         if(!r->k)
00123         {
00124                 r->k = k;
00125                 r->v = v;
00126                 self->keyCount ++;
00127                 return;
00128         }
00129         
00130         if(r->k == k)
00131         {
00132                 r->v = v;
00133                 return;
00134         }
00135         
00136         {
00137         PointerHashRecord x;
00138         x.k = k;
00139         x.v = v;
00140         PointerHash_insert_(self, &x);
00141         }
00142 }
00143 
00144 IOINLINE void PointerHash_shrinkIfNeeded(PointerHash *self)
00145 {
00146         if(self->keyCount < self->size/8)
00147         {
00148                 PointerHash_shrink(self);
00149         }
00150 }
00151 
00152 IOINLINE void PointerHashRecord_swapWith_(PointerHashRecord *self, PointerHashRecord *other)
00153 {
00154         PointerHashRecord tmp = *self;
00155         *self = *other;
00156         *other = tmp;
00157 }
00158 
00159 IOINLINE void PointerHash_clean(PointerHash *self)
00160 {
00161         memset(self->records, 0, sizeof(PointerHashRecord) * self->size);
00162         self->keyCount = 0;
00163 }
00164 
00165 
00166 IOINLINE PointerHash *PointerHash_new(void)
00167 {
00168         PointerHash *self = (PointerHash *)io_calloc(1, sizeof(PointerHash));
00169         PointerHash_setSize_(self, 8);
00170         return self;
00171 }
00172 
00173 IOINLINE void PointerHash_copy_(PointerHash *self, const PointerHash *other)
00174 {
00175         io_free(self->records);
00176         memcpy(self, other, sizeof(PointerHash));
00177         self->records = (unsigned char *) malloc(self->size * sizeof(PointerHashRecord));
00178         memcpy(self->records, other->records, self->size * sizeof(PointerHashRecord));
00179 }
00180 
00181 IOINLINE PointerHash *PointerHash_clone(PointerHash *self)
00182 {
00183         PointerHash *other = PointerHash_new();
00184         PointerHash_copy_(other, self);
00185         return other;
00186 }
00187 
00188 IOINLINE void PointerHash_setSize_(PointerHash *self, size_t size)
00189 {
00190         self->records = (unsigned char *) realloc(self->records, size * sizeof(PointerHashRecord));
00191         
00192         if(size > self->size)
00193         {               
00194                 memset(self->records + self->size * sizeof(PointerHashRecord), 
00195                         0x0, (size - self->size) * sizeof(PointerHashRecord));
00196         }
00197         
00198         self->size = size;
00199         
00200         PointerHash_updateMask(self);
00201 }
00202 
00203 IOINLINE void PointerHash_updateMask(PointerHash *self)
00204 {
00205         self->mask = (intptr_t)(self->size - 1);
00206 }
00207 
00208 IOINLINE void PointerHash_show(PointerHash *self)
00209 {
00210         size_t i;
00211         
00212         printf("PointerHash records:\n");
00213         for(i = 0; i < self->size; i++)
00214         {
00215                 PointerHashRecord *r = PointerHashRecords_recordAt_(self->records, i);
00216                 printf("  %i: %p %p\n", (int)i, r->k, r->v);
00217         }
00218 }
00219 
00220 IOINLINE void PointerHash_free(PointerHash *self)
00221 {
00222         io_free(self->records);
00223         io_free(self);
00224 }
00225 
00226 IOINLINE void PointerHash_insert_(PointerHash *self, PointerHashRecord *x)
00227 {       
00228         int n;
00229         
00230         for (n = 0; n < POINTERHASH_MAXLOOP; n ++)
00231         { 
00232                 PointerHashRecord *r;
00233                 
00234                 r = PointerHash_record1_(self, x->k);
00235                 PointerHashRecord_swapWith_(x, r);
00236                 if(x->k == 0x0) { self->keyCount ++; return; }
00237                  
00238                 r = PointerHash_record2_(self, x->k);
00239                 PointerHashRecord_swapWith_(x, r);
00240                 if(x->k == 0x0) { self->keyCount ++; return; }
00241         }
00242         
00243         PointerHash_grow(self); 
00244         PointerHash_at_put_(self, x->k, x->v);
00245 }
00246 
00247 IOINLINE void PointerHash_insertRecords(PointerHash *self, unsigned char *oldRecords, size_t oldSize)
00248 {
00249         size_t i;
00250         
00251         for (i = 0; i < oldSize; i ++)
00252         {
00253                 PointerHashRecord *r = PointerHashRecords_recordAt_(oldRecords, i);
00254                 
00255                 if (r->k)
00256                 {
00257                         PointerHash_at_put_(self, r->k, r->v);
00258                 }
00259         }
00260 }
00261 
00262 IOINLINE void PointerHash_resizeTo_(PointerHash *self, size_t newSize)
00263 {
00264         unsigned char *oldRecords = self->records;
00265         size_t oldSize = self->size;
00266         self->size = newSize;
00267         self->records = (unsigned char *) io_calloc(1, sizeof(PointerHashRecord) * self->size);
00268         self->keyCount = 0;
00269         PointerHash_updateMask(self);
00270         PointerHash_insertRecords(self, oldRecords, oldSize);
00271         io_free(oldRecords);
00272 }
00273 
00274 IOINLINE void PointerHash_grow(PointerHash *self)
00275 {
00276         PointerHash_resizeTo_(self, self->size * 2);
00277 }
00278 
00279 IOINLINE void PointerHash_shrink(PointerHash *self)
00280 {
00281         PointerHash_resizeTo_(self, self->size / 2);
00282 }
00283 
00284 IOINLINE void PointerHash_removeKey_(PointerHash *self, void *k)
00285 {
00286         PointerHashRecord *r;
00287         
00288         r = PointerHash_record1_(self, k);      
00289         if(r->k == k)
00290         {
00291                 r->k = 0x0;
00292                 r->v = 0x0;
00293                 self->keyCount --;
00294                 PointerHash_shrinkIfNeeded(self);
00295                 return;
00296         }
00297         
00298         r = PointerHash_record2_(self, k);
00299         if(r->k == k)
00300         {
00301                 r->k = 0x0;
00302                 r->v = 0x0;
00303                 self->keyCount --;
00304                 PointerHash_shrinkIfNeeded(self);
00305                 return;
00306         }
00307 }
00308 
00309 IOINLINE size_t PointerHash_size(PointerHash *self) // actually the keyCount
00310 {
00311         return self->keyCount;
00312 }
00313 
00314 // ----------------------------
00315 
00316 IOINLINE size_t PointerHash_memorySize(PointerHash *self)
00317 {
00318         return sizeof(PointerHash) + self->size * sizeof(PointerHashRecord);
00319 }
00320 
00321 void PointerHash_compact(PointerHash *self)
00322 {
00323 }
00324 
00325 
00326 // --- enumeration --------------------------------------------------
00327 
00328 #define POINTERHASH_FOREACH(self, pkey, pvalue, code) \
00329 {\
00330         PointerHash *_self = (self);\
00331         unsigned char *_records = _self->records;\
00332         unsigned int _i, _size = _self->size;\
00333         void *pkey;\
00334         void *pvalue;\
00335         \
00336         for (_i = 0; _i < _size; _i ++)\
00337         {\
00338                 PointerHashRecord *_record = PointerHashRecords_recordAt_(_records, _i);\
00339                 if (_record->k)\
00340                 {\
00341                         pkey = _record->k;\
00342                         pvalue = _record->v;\
00343                         code;\
00344                 }\
00345         }\
00346 }
00347 
00348 
00349 #define PointerHash_cleanSlots(self)
00350 #define PointerHash_hasDirtyKey_(self, k) 0
00351 
00352 #ifdef __cplusplus
00353 }
00354 #endif
00355 #endif

Generated on Sat Apr 23 11:43:35 2011 for Mnemosyne by  doxygen 1.4.7