00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef __cplusplus
00020 #include "pup.h"
00021 extern "C" {
00022 #endif
00023 #ifndef __cplusplus
00024 #include "pup_c.h"
00025 #endif
00026
00027 #ifndef __OSL_HASH_TABLE_C
00028 #define __OSL_HASH_TABLE_C
00029
00030 #include <stddef.h>
00031
00032
00033 typedef void *CkHashtable_c;
00034
00035
00036 CkHashtable_c CkCreateHashtable_int(int objBytes,int initSize);
00037
00038 CkHashtable_c CkCreateHashtable_string(int objBytes,int initSize);
00039
00040 CkHashtable_c CkCreateHashtable_pointer(int objBytes,int initSize);
00041
00042 void CkDeleteHashtable(CkHashtable_c h);
00043
00044
00045 void *CkHashtablePut(CkHashtable_c h,const void *atKey);
00046
00047
00048
00049 void *CkHashtableGet(CkHashtable_c h,const void *fromKey);
00050
00051
00052 void *CkHashtableKeyFromObject(CkHashtable_c h,const void *object);
00053
00054
00055
00056 int CkHashtableRemove(CkHashtable_c h,const void *doomedKey);
00057
00058
00059 int CkHashtableSize(CkHashtable_c h);
00060
00061
00062 typedef void *CkHashtableIterator_c;
00063
00064
00065
00066
00067 CkHashtableIterator_c CkHashtableGetIterator(CkHashtable_c h);
00068
00069
00070 void CkHashtableDestroyIterator(CkHashtableIterator_c it);
00071
00072
00073 void *CkHashtableIteratorNext(CkHashtableIterator_c it, void **retKey);
00074
00075
00076 void CkHashtableIteratorSeek(CkHashtableIterator_c it, int n);
00077
00078
00079 void CkHashtableIteratorSeekStart(CkHashtableIterator_c it);
00080
00081 #endif
00082 #ifdef __cplusplus
00083 }
00084
00085 #ifndef __OSL_HASH_TABLE_CPP
00086 #define __OSL_HASH_TABLE_CPP
00087
00088 #include <stdio.h>
00089
00090
00091
00092
00093 typedef unsigned int CkHashCode;
00094
00095
00096 inline CkHashCode circleShift(CkHashCode h,unsigned int by)
00097 {
00098 const unsigned int intBits=8*sizeof(CkHashCode);
00099 by%=intBits;
00100 return (h<<by)|(h>>(intBits-by));
00101 }
00102
00103
00104 typedef CkHashCode (*CkHashFunction)(const void *keyData,size_t keyLen);
00105 CkHashCode CkHashFunction_default(const void *keyData,size_t keyLen);
00106 CkHashCode CkHashFunction_string(const void *keyData,size_t keyLen);
00107 inline CkHashCode CkHashFunction_int(const void *keyData,size_t )
00108 {return *(int *)keyData;}
00109 inline CkHashCode CkHashFunction_pointer(const void *keyData,size_t )
00110 {if (sizeof(char*)==sizeof(int)) return *(int *)keyData;
00111 else if (sizeof(char*)==2*sizeof(int)) return ((int*)keyData)[0] ^ ((int*)keyData)[1];
00112 else CmiAbort("Invalid key data for hash code");
00113 return 0;
00114 }
00115
00116
00117 typedef int (*CkHashCompare)(const void *key1,const void *key2,size_t keyLen);
00118 int CkHashCompare_default(const void *key1,const void *key2,size_t keyLen);
00119 int CkHashCompare_string(const void *key1,const void *key2,size_t keyLen);
00120 inline int CkHashCompare_int(const void *k1,const void *k2,size_t )
00121 {return *(int *)k1 == *(int *)k2;}
00122 inline int CkHashCompare_pointer(const void *k1,const void *k2,size_t )
00123 {return *(char **)k1 == *(char **)k2;}
00124
00125 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
00126 extern int countHashRefs;
00127 extern int countHashCollisions;
00128 #endif
00129
00131
00132 class CkHashtableIterator;
00133
00151 class CkHashtableLayout {
00152 int size;
00153 int ko,ks;
00154 int po,ps;
00155 int oo,os;
00156 public:
00157 CkHashtableLayout(int keySize,int emptyOffset,
00158 int objectOffset,int objectSize,int entryLength):
00159 size(entryLength),
00160 ko(0), ks(keySize),
00161 po(emptyOffset), ps(1),
00162 oo(objectOffset), os(objectSize)
00163 {}
00164
00165 inline int entrySize(void) const {return size;}
00166 inline int keySize(void) const {return ks;}
00167 inline int objectSize(void) const {return os;}
00168
00169
00171 inline char *getKey(char *entry) const {return entry+ko;}
00173 inline char *getObject(char *entry) const {return entry+oo;}
00174
00176 inline char isEmpty(char *entry) const {return *(entry+po);}
00178 inline void empty(char *entry) const {*(entry+po)=1;}
00180 inline void fill(char *entry) const {*(entry+po)=0;}
00181
00183 inline char *nextEntry(char *entry) const {return entry+size;}
00184
00186 inline char *entryFromKey(char *key) const {return key-ko;}
00187
00189 inline char *entryFromObject(char *obj) const {return obj-oo;}
00190 };
00191
00197 class CkHashtable {
00198 private:
00199 CkHashtable(const CkHashtable &);
00200 void operator=(const CkHashtable &);
00201 protected:
00202 int len;
00203 CkHashtableLayout layout;
00204 char *table;
00205
00206 int nObj;
00207 int resizeAt;
00208 CkHashFunction hash;
00209 CkHashCompare compare;
00210
00211 float loadFactor;
00212
00213
00214
00215 int inc(int &i) const {i++; if (i>=len) i=0; return i;}
00216
00217
00218 char *entry(int i) const {return (char *)(table+i*layout.entrySize());}
00219
00220
00221 char *findKey(const void *key) const;
00222
00223 char *findEntry(const void *key) const;
00224
00225
00226 void buildTable(int newLen);
00227
00228 void rehash(int newLen);
00229 public:
00230
00231 CkHashtable(const CkHashtableLayout &layout_,
00232 int initLen=5,float NloadFactor=0.5,
00233 CkHashFunction hash=CkHashFunction_default,
00234 CkHashCompare compare=CkHashCompare_default);
00235
00236 ~CkHashtable();
00237
00238
00239
00240
00241 void *put(const void *key, int *existing=NULL);
00242
00243
00244 void *get(const void *key) const {
00245 char *ent=findKey(key);
00246 if (ent==NULL) return NULL;
00247 else return layout.getObject(ent);
00248 }
00249
00250
00251
00252 int remove(const void *key);
00253
00254
00255 void empty(void);
00256
00257 int numObjects(void) const { return nObj; }
00258
00259
00260
00261
00262 CkHashtableIterator *iterator(void);
00263 };
00264
00265
00266
00267 class CkHashtableIterator {
00268 protected:
00269 int len;
00270 CkHashtableLayout layout;
00271 char *table;
00272 int curNo;
00273
00274 char *entry(int i) const {return table+i*layout.entrySize();}
00275 public:
00276 CkHashtableIterator(char *table_,int len_,const CkHashtableLayout &lo)
00277 :len(len_),layout(lo),table(table_),curNo(0)
00278 {}
00279 CkHashtableIterator(const CkHashtableIterator &it);
00280 void operator=(const CkHashtableIterator &it);
00281
00282
00283 void seekStart(void);
00284
00285
00286 void seek(int n);
00287
00288
00289 int hasNext(void);
00290
00291
00292 void *next(void **retKey=NULL);
00293 };
00294
00295
00297
00306 template <class KEY, class OBJ>
00307 class CkHashtableTslow:public CkHashtable {
00308
00309 static inline CkHashtableLayout getLayout(void) {
00310
00311
00312
00313 struct entry_t {
00314 KEY k;
00315 char empty;
00316 OBJ o;
00317 };
00318
00319
00320 entry_t *e=(entry_t *)0;
00321 int emptyOffset=((char *)&e->empty)-(char *)e;
00322 int oOffset=((char *)&e->o)-(char *)e;
00323 return CkHashtableLayout(sizeof(KEY),emptyOffset,
00324 oOffset,sizeof(OBJ),sizeof(entry_t));
00325 }
00326 public:
00327
00328 CkHashtableTslow(
00329 int initLen=5,float NloadFactor=0.5,
00330 CkHashFunction Nhash=CkHashFunction_default,
00331 CkHashCompare Ncompare=CkHashCompare_default)
00332 :CkHashtable(getLayout(),initLen,NloadFactor,Nhash,Ncompare)
00333 {}
00334
00335 OBJ &put(const KEY &key, int *existing=NULL) {
00336 void *obj = CkHashtable::put((const void *)&key, existing);
00337 return *(OBJ *)obj;
00338 }
00339 OBJ get(const KEY &key) const {
00340 void *r=CkHashtable::get((const void *)&key);
00341 if (r==NULL) return OBJ(0);
00342 else return *(OBJ *)r;
00343 }
00344
00345 OBJ &getRef(const KEY &key) {
00346 return *(OBJ *)CkHashtable::get((const void *)&key);
00347 }
00348 void remove(const KEY &key) {CkHashtable::remove((const void *)&key);}
00349 };
00350
00351
00352
00353
00354
00355 template <class KEY, class OBJ>
00356 class CkHashtableT:public CkHashtableTslow<KEY,OBJ> {
00357 public:
00358
00359 CkHashtableT(int initLen=5,float NloadFactor=0.5)
00360 :CkHashtableTslow<KEY,OBJ>(initLen,NloadFactor,
00361 KEY::staticHash,KEY::staticCompare)
00362 {}
00363 CkHashtableT(
00364 int initLen,float NloadFactor,
00365 CkHashFunction Nhash,CkHashCompare Ncompare)
00366 :CkHashtableTslow<KEY,OBJ>(initLen,NloadFactor,Nhash,Ncompare)
00367 {}
00368
00369
00370 OBJ get(const KEY &key) const {
00371 int i=key.hash()%this->len;
00372 while(1) {
00373 char *cur=this->entry(i);
00374
00375 if (this->layout.isEmpty(cur)){
00376 return OBJ(0);
00377 }
00378
00379 if (key.compare(*(KEY *)this->layout.getKey(cur)))
00380 return *(OBJ *)this->layout.getObject(cur);
00381 this->inc(i);
00382 };
00383 }
00384
00385 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
00386 OBJ *getPointer(const KEY &key) {
00387 countHashRefs++;
00388 int i=key.hash()%this->len;
00389 while(1) {
00390 char *cur=this->entry(i);
00391
00392 if (this->layout.isEmpty(cur)){
00393 return NULL;
00394 }
00395
00396 if (key.compare(*(KEY *)this->layout.getKey(cur)))
00397 return (OBJ *)this->layout.getObject(cur);
00398 this->inc(i);
00399 countHashCollisions++;
00400 };
00401 return NULL;
00402 }
00403 #endif
00404
00405
00406
00407 OBJ &getRef(const KEY &key) {
00408 int i=key.hash()%this->len;
00409 while(1) {
00410 char *cur=this->entry(i);
00411
00412 if (key.compare(*(KEY *)this->layout.getKey(cur)))
00413 return *(OBJ *)this->layout.getObject(cur);
00414 this->inc(i);
00415 };
00416 }
00417 void pup(PUP::er &p){
00418 if(!p.isUnpacking()){
00419
00420 CkHashtableIterator *it=CkHashtable::iterator();
00421 int hasNext=1;
00422 OBJ *o; KEY *k;
00423 while (NULL!=(o=(OBJ *)it->next((void **)&k))) {
00424 p|hasNext;
00425 p|*k;
00426 p|*o;
00427 }
00428 hasNext=0; p|hasNext;
00429 delete it;
00430 }else{
00431
00432 int hasNext;
00433 p|hasNext;
00434 while (hasNext) {
00435 OBJ o; KEY k;
00436 p|k;
00437 p|o;
00438 put(k)=o;
00439 p|hasNext;
00440 }
00441 }
00442 }
00443 };
00444
00455 template <class T> class CkHashtableAdaptorT {
00456 T val;
00457 public:
00458 CkHashtableAdaptorT<T>(const T &v):val(v) {}
00460 CkHashtableAdaptorT<T>(){}
00461 operator T & () {return val;}
00462 operator const T & () const {return val;}
00463 inline CkHashCode hash(void) const
00464 {return (CkHashCode)val;}
00465 static CkHashCode staticHash(const void *k,size_t)
00466 {return ((CkHashtableAdaptorT<T> *)k)->hash();}
00467 inline int compare(const CkHashtableAdaptorT<T> &t) const
00468 {return val==t.val;}
00469 static int staticCompare(const void *a,const void *b,size_t)
00470 {
00471 return ((CkHashtableAdaptorT<T> *)a)->
00472 compare(*(CkHashtableAdaptorT<T> *)b);
00473 }
00474 void pup(PUP::er &p){
00475 p | val;
00476 }
00477 };
00478
00479 #endif
00480
00481 #endif