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 #include <type_traits>
00091
00092
00093
00094
00095 typedef unsigned int CkHashCode;
00096
00097
00098 inline CkHashCode circleShift(CkHashCode h,unsigned int by)
00099 {
00100 const unsigned int intBits=8*sizeof(CkHashCode);
00101 by%=intBits;
00102 if (by == 0)
00103 return h;
00104 return (h<<by)|(h>>(intBits-by));
00105 }
00106
00107
00108 typedef CkHashCode (*CkHashFunction)(const void *keyData,size_t keyLen);
00109 CkHashCode CkHashFunction_default(const void *keyData,size_t keyLen);
00110 CkHashCode CkHashFunction_string(const void *keyData,size_t keyLen);
00111 inline CkHashCode CkHashFunction_int(const void *keyData,size_t )
00112 {return *(int *)keyData;}
00113 inline CkHashCode CkHashFunction_pointer(const void *keyData,size_t )
00114 {if (sizeof(char*)==sizeof(int)) return *(int *)keyData;
00115 else if (sizeof(char*)==2*sizeof(int)) return ((int*)keyData)[0] ^ ((int*)keyData)[1];
00116 else CmiAbort("Invalid key data for hash code");
00117 return 0;
00118 }
00119
00120
00121 typedef int (*CkHashCompare)(const void *key1,const void *key2,size_t keyLen);
00122 int CkHashCompare_default(const void *key1,const void *key2,size_t keyLen);
00123 int CkHashCompare_string(const void *key1,const void *key2,size_t keyLen);
00124 inline int CkHashCompare_int(const void *k1,const void *k2,size_t )
00125 {return *(int *)k1 == *(int *)k2;}
00126 inline int CkHashCompare_pointer(const void *k1,const void *k2,size_t )
00127 {return *(char **)k1 == *(char **)k2;}
00128
00129
00131
00132 class CkHashtableIterator;
00133
00151 class CkHashtableLayout {
00152 int size;
00153 int ks;
00154 int po;
00155 int oo,os;
00156 public:
00157 CkHashtableLayout(int keySize,int emptyOffset,
00158 int objectOffset,int objectSize,int entryLength):
00159 size(entryLength),
00160 ks(keySize),
00161 po(emptyOffset),
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;}
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;}
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 static_assert(std::is_standard_layout<KEY>::value, "KEY type is not standard layout, breaking offsetof()");
00320 static_assert(std::is_standard_layout<OBJ>::value, "OBJ type is not standard layout, breaking offsetof()");
00321 int emptyOffset = offsetof(entry_t, empty);
00322 int oOffset = offsetof(entry_t, o);
00323
00324 return CkHashtableLayout(sizeof(KEY),emptyOffset,
00325 oOffset,sizeof(OBJ),sizeof(entry_t));
00326 }
00327 public:
00328
00329 CkHashtableTslow(
00330 int initLen=5,float NloadFactor=0.5,
00331 CkHashFunction Nhash=CkHashFunction_default,
00332 CkHashCompare Ncompare=CkHashCompare_default)
00333 :CkHashtable(getLayout(),initLen,NloadFactor,Nhash,Ncompare)
00334 {}
00335
00336 OBJ &put(const KEY &key, int *existing=NULL) {
00337 void *obj = CkHashtable::put((const void *)&key, existing);
00338 return *(OBJ *)obj;
00339 }
00340 OBJ get(const KEY &key) const {
00341 void *r=CkHashtable::get((const void *)&key);
00342 if (r==NULL) return OBJ(0);
00343 else return *(OBJ *)r;
00344 }
00345
00346 OBJ &getRef(const KEY &key) {
00347 return *(OBJ *)CkHashtable::get((const void *)&key);
00348 }
00349 void remove(const KEY &key) {CkHashtable::remove((const void *)&key);}
00350 };
00351
00352
00353
00354
00355
00356 template <class KEY, class OBJ>
00357 class CkHashtableT:public CkHashtableTslow<KEY,OBJ> {
00358 public:
00359
00360 CkHashtableT(int initLen=5,float NloadFactor=0.5)
00361 :CkHashtableTslow<KEY,OBJ>(initLen,NloadFactor,
00362 KEY::staticHash,KEY::staticCompare)
00363 {}
00364 CkHashtableT(
00365 int initLen,float NloadFactor,
00366 CkHashFunction Nhash,CkHashCompare Ncompare)
00367 :CkHashtableTslow<KEY,OBJ>(initLen,NloadFactor,Nhash,Ncompare)
00368 {}
00369
00370
00371 OBJ get(const KEY &key) const {
00372 int i=key.hash()%this->len;
00373 while(1) {
00374 char *cur=this->entry(i);
00375
00376 if (this->layout.isEmpty(cur)){
00377 return OBJ(0);
00378 }
00379
00380 if (key.compare(*(KEY *)this->layout.getKey(cur)))
00381 return *(OBJ *)this->layout.getObject(cur);
00382 this->inc(i);
00383 };
00384 }
00385
00386 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
00387 OBJ *getPointer(const KEY &key) {
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 };
00400 return NULL;
00401 }
00402 #endif
00403
00404
00405
00406 OBJ &getRef(const KEY &key) {
00407 int i=key.hash()%this->len;
00408 while(1) {
00409 char *cur=this->entry(i);
00410
00411 if (key.compare(*(KEY *)this->layout.getKey(cur)))
00412 return *(OBJ *)this->layout.getObject(cur);
00413 this->inc(i);
00414 };
00415 }
00416 void pup(PUP::er &p){
00417 if(!p.isUnpacking()){
00418
00419 CkHashtableIterator *it=CkHashtable::iterator();
00420 int hasNext=1;
00421 OBJ *o; KEY *k;
00422 while (NULL!=(o=(OBJ *)it->next((void **)&k))) {
00423 p|hasNext;
00424 p|*k;
00425 p|*o;
00426 }
00427 hasNext=0; p|hasNext;
00428 delete it;
00429 }else{
00430
00431 int hasNext=1;
00432 p|hasNext;
00433 while (hasNext) {
00434 OBJ o; KEY k;
00435 p|k;
00436 p|o;
00437 this->put(k)=o;
00438 p|hasNext;
00439 }
00440 }
00441 }
00442 };
00443
00454 template <class T> class CkHashtableAdaptorT {
00455 T val;
00456 public:
00457 CkHashtableAdaptorT<T>(const T &v):val(v) {}
00459 CkHashtableAdaptorT<T>(){}
00460 operator T & () {return val;}
00461 operator const T & () const {return val;}
00462 inline CkHashCode hash(void) const
00463 {return (CkHashCode)val;}
00464 static CkHashCode staticHash(const void *k,size_t)
00465 {return ((CkHashtableAdaptorT<T> *)k)->hash();}
00466 inline int compare(const CkHashtableAdaptorT<T> &t) const
00467 {return val==t.val;}
00468 static int staticCompare(const void *a,const void *b,size_t)
00469 {
00470 return ((CkHashtableAdaptorT<T> *)a)->
00471 compare(*(CkHashtableAdaptorT<T> *)b);
00472 }
00473 void pup(PUP::er &p){
00474 p | val;
00475 }
00476 };
00477
00478 #endif
00479
00480 #endif