usermode/library/common/cuckoo_hash/PointerSetHashInline.h

00001 /*
00002  *  PointerSetHash.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 "PointerSetHash_struct.h"
00029 
00030 static inline BASEKIT_API PointerSetHash *PointerSetHash_new(void);
00031 static inline BASEKIT_API void PointerSetHash_copy_(PointerSetHash *self, const PointerSetHash *other);
00032 static inline BASEKIT_API PointerSetHash *PointerSetHash_clone(PointerSetHash *self);
00033 static inline BASEKIT_API void PointerSetHash_free(PointerSetHash *self);
00034 
00035 static inline BASEKIT_API void PointerSetHash_at_put_(PointerSetHash *self, void *k);
00036 static inline BASEKIT_API void PointerSetHash_removeKey_(PointerSetHash *self, void *k);
00037 static inline BASEKIT_API size_t PointerSetHash_size(PointerSetHash *self); // actually the keyCount
00038 
00039 static inline BASEKIT_API size_t PointerSetHash_memorySize(PointerSetHash *self);
00040 static inline BASEKIT_API void PointerSetHash_compact(PointerSetHash *self);
00041 
00042 // --- private methods ----------------------------------------
00043 
00044 static inline BASEKIT_API void PointerSetHash_setSize_(PointerSetHash *self, size_t size); 
00045 static inline BASEKIT_API void PointerSetHash_insert_(PointerSetHash *self, PointerSetHashRecord *x); 
00046 static inline BASEKIT_API void PointerSetHash_grow(PointerSetHash *self); 
00047 static inline BASEKIT_API void PointerSetHash_shrinkIfNeeded(PointerSetHash *self); 
00048 static inline BASEKIT_API void PointerSetHash_shrink(PointerSetHash *self); 
00049 static inline BASEKIT_API void PointerSetHash_show(PointerSetHash *self);
00050 static inline BASEKIT_API void PointerSetHash_updateMask(PointerSetHash *self); 
00051 
00052 #undef IOINLINE
00053 #define IOINLINE static inline
00054 
00055 // -----------------------------------
00056 
00057 #define PointerSetHashRecords_recordAt_(records, pos) (PointerSetHashRecord *)(records + (pos * sizeof(PointerSetHashRecord)))
00058 
00059 
00060 IOINLINE PointerSetHashRecord *PointerSetHash_record1_(PointerSetHash *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 PointerSetHashRecords_recordAt_(self->records, pos);
00066 }
00067 
00068 IOINLINE PointerSetHashRecord *PointerSetHash_record2_(PointerSetHash *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 PointerSetHashRecords_recordAt_(self->records, pos);
00075 }
00076 
00077 IOINLINE void *PointerSetHash_at_(PointerSetHash *self, void *k)
00078 {
00079         PointerSetHashRecord *r;
00080         
00081         r = PointerSetHash_record1_(self, k);
00082         if(k == r->k) return 1;
00083         
00084         r = PointerSetHash_record2_(self, k);   
00085         if(k == r->k) return 1;
00086         
00087         return 0x0;
00088 }
00089 
00090 IOINLINE size_t PointerSetHash_count(PointerSetHash *self)
00091 {
00092         return self->keyCount;
00093 }
00094 
00095 IOINLINE int PointerSetHashKey_hasKey_(PointerSetHash *self, void *key)
00096 {
00097         return PointerSetHash_at_(self, key) != NULL;
00098 }
00099 
00100 IOINLINE void PointerSetHash_at_put_(PointerSetHash *self, void *k)
00101 {
00102         PointerSetHashRecord *r;
00103         
00104         r = PointerSetHash_record1_(self, k);
00105         
00106         if(!r->k)
00107         {
00108                 r->k = k;
00109                 self->keyCount ++;
00110                 return;
00111         }
00112         
00113         if(r->k == k)
00114         {
00115                 return;
00116         }
00117 
00118         r = PointerSetHash_record2_(self, k);
00119 
00120         if(!r->k)
00121         {
00122                 r->k = k;
00123                 self->keyCount ++;
00124                 return;
00125         }
00126         
00127         if(r->k == k)
00128         {
00129                 return;
00130         }
00131         
00132         {
00133         PointerSetHashRecord x;
00134         x.k = k;
00135         PointerSetHash_insert_(self, &x);
00136         }
00137 }
00138 
00139 IOINLINE void PointerSetHash_shrinkIfNeeded(PointerSetHash *self)
00140 {
00141         if(self->keyCount < self->size/8)
00142         {
00143                 PointerSetHash_shrink(self);
00144         }
00145 }
00146 
00147 IOINLINE void PointerSetHashRecord_swapWith_(PointerSetHashRecord *self, PointerSetHashRecord *other)
00148 {
00149         PointerSetHashRecord tmp = *self;
00150         *self = *other;
00151         *other = tmp;
00152 }
00153 
00154 IOINLINE void PointerSetHash_clean(PointerSetHash *self)
00155 {
00156         memset(self->records, 0, sizeof(PointerSetHashRecord) * self->size);
00157         self->keyCount = 0;
00158 }
00159 
00160 // --- enumeration --------------------------------------------------
00161 
00162 #define POINTERHASH_FOREACH(self, pkey, code) \
00163 {\
00164         PointerSetHash *_self = (self);\
00165         unsigned char *_records = _self->records;\
00166         unsigned int _i, _size = _self->size;\
00167         void *pkey;\
00168         void *pvalue;\
00169         \
00170         for (_i = 0; _i < _size; _i ++)\
00171         {\
00172                 PointerSetHashRecord *_record = PointerSetHashRecords_recordAt_(_records, _i);\
00173                 if (_record->k)\
00174                 {\
00175                         pkey = _record->k;\
00176                         code;\
00177                 }\
00178         }\
00179 }
00180 
00181 // -----------------------------------
00182 
00183 IOINLINE PointerSetHash *PointerSetHash_new(void)
00184 {
00185         PointerSetHash *self = (PointerSetHash *)io_calloc(1, sizeof(PointerSetHash));
00186         PointerSetHash_setSize_(self, 8);
00187         return self;
00188 }
00189 
00190 IOINLINE void PointerSetHash_copy_(PointerSetHash *self, const PointerSetHash *other)
00191 {
00192         io_free(self->records);
00193         memcpy(self, other, sizeof(PointerSetHash));
00194         self->records = malloc(self->size * sizeof(PointerSetHashRecord));
00195         memcpy(self->records, other->records, self->size * sizeof(PointerSetHashRecord));
00196 }
00197 
00198 IOINLINE PointerSetHash *PointerSetHash_clone(PointerSetHash *self)
00199 {
00200         PointerSetHash *other = PointerSetHash_new();
00201         PointerSetHash_copy_(other, self);
00202         return other;
00203 }
00204 
00205 IOINLINE void PointerSetHash_setSize_(PointerSetHash *self, size_t size)
00206 {
00207         self->records = realloc(self->records, size * sizeof(PointerSetHashRecord));
00208         
00209         if(size > self->size)
00210         {               
00211                 memset(self->records + self->size * sizeof(PointerSetHashRecord), 
00212                         0x0, (size - self->size) * sizeof(PointerSetHashRecord));
00213         }
00214         
00215         self->size = size;
00216         
00217         PointerSetHash_updateMask(self);
00218 }
00219 
00220 IOINLINE void PointerSetHash_updateMask(PointerSetHash *self)
00221 {
00222         self->mask = (intptr_t)(self->size - 1);
00223 }
00224 
00225 IOINLINE void PointerSetHash_show(PointerSetHash *self)
00226 {
00227         size_t i;
00228         
00229         printf("PointerSetHash records:\n");
00230         for(i = 0; i < self->size; i++)
00231         {
00232                 PointerSetHashRecord *r = PointerSetHashRecords_recordAt_(self->records, i);
00233                 printf("  %i: %p\n", (int)i, r->k);
00234         }
00235 }
00236 
00237 IOINLINE void PointerSetHash_free(PointerSetHash *self)
00238 {
00239         io_free(self->records);
00240         io_free(self);
00241 }
00242 
00243 IOINLINE void PointerSetHash_insert_(PointerSetHash *self, PointerSetHashRecord *x)
00244 {       
00245         int n;
00246         
00247         for (n = 0; n < POINTERHASH_MAXLOOP; n ++)
00248         { 
00249                 PointerSetHashRecord *r;
00250                 
00251                 r = PointerSetHash_record1_(self, x->k);
00252                 PointerSetHashRecord_swapWith_(x, r);
00253                 if(x->k == 0x0) { self->keyCount ++; return; }
00254                  
00255                 r = PointerSetHash_record2_(self, x->k);
00256                 PointerSetHashRecord_swapWith_(x, r);
00257                 if(x->k == 0x0) { self->keyCount ++; return; }
00258         }
00259         
00260         PointerSetHash_grow(self); 
00261         PointerSetHash_at_put_(self, x->k);
00262 }
00263 
00264 IOINLINE void PointerSetHash_insertRecords(PointerSetHash *self, unsigned char *oldRecords, size_t oldSize)
00265 {
00266         size_t i;
00267         
00268         for (i = 0; i < oldSize; i ++)
00269         {
00270                 PointerSetHashRecord *r = PointerSetHashRecords_recordAt_(oldRecords, i);
00271                 
00272                 if (r->k)
00273                 {
00274                         PointerSetHash_at_put_(self, r->k);
00275                 }
00276         }
00277 }
00278 
00279 IOINLINE void PointerSetHash_resizeTo_(PointerSetHash *self, size_t newSize)
00280 {
00281         unsigned char *oldRecords = self->records;
00282         size_t oldSize = self->size;
00283         self->size = newSize;
00284         self->records = io_calloc(1, sizeof(PointerSetHashRecord) * self->size);
00285         self->keyCount = 0;
00286         PointerSetHash_updateMask(self);
00287         PointerSetHash_insertRecords(self, oldRecords, oldSize);
00288         io_free(oldRecords);
00289 }
00290 
00291 IOINLINE void PointerSetHash_grow(PointerSetHash *self)
00292 {
00293         PointerSetHash_resizeTo_(self, self->size * 2);
00294 }
00295 
00296 void PointerSetHash_shrink(PointerSetHash *self)
00297 {
00298         PointerSetHash_resizeTo_(self, self->size / 2);
00299 }
00300 
00301 IOINLINE void PointerSetHash_removeKey_(PointerSetHash *self, void *k)
00302 {
00303         PointerSetHashRecord *r;
00304         
00305         r = PointerSetHash_record1_(self, k);   
00306         if(r->k == k)
00307         {
00308                 r->k = 0x0;
00309                 self->keyCount --;
00310                 PointerSetHash_shrinkIfNeeded(self);
00311                 return;
00312         }
00313         
00314         r = PointerSetHash_record2_(self, k);
00315         if(r->k == k)
00316         {
00317                 r->k = 0x0;
00318                 self->keyCount --;
00319                 PointerSetHash_shrinkIfNeeded(self);
00320                 return;
00321         }
00322 }
00323 
00324 IOINLINE size_t PointerSetHash_size(PointerSetHash *self) // actually the keyCount
00325 {
00326         return self->keyCount;
00327 }
00328 
00329 // ----------------------------
00330 
00331 IOINLINE size_t PointerSetHash_memorySize(PointerSetHash *self)
00332 {
00333         return sizeof(PointerSetHash) + self->size * sizeof(PointerSetHashRecord);
00334 }
00335 
00336 IOINLINE void PointerSetHash_compact(PointerSetHash *self)
00337 {
00338 }
00339 
00340 
00341 #define PointerSetHash_cleanSlots(self)
00342 #define PointerSetHash_hasDirtyKey_(self, k) 0
00343 
00344 #ifdef __cplusplus
00345 }
00346 #endif
00347 #endif

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