00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef INCLUDE_BASE_TABLES_H
00021 #define INCLUDE_BASE_TABLES_H
00022
00023 #include "base/intutils.h"
00024 #include "base/Enumerator.h"
00025
00026
00027
00028
00029
00030
00031
00032
00033 namespace hash
00034 {
00035
00036
00037
00038
00039
00040
00041
00042 struct SingleBucket_t :
00043 public base::SingleLinkable<SingleBucket_t>
00044 {
00045 uint32_t info;
00046 };
00047
00048 template<class BucketType>
00049 struct SingleBucket :
00050 public base::SingleLinkable<BucketType>
00051 {
00052 uint32_t info;
00053 };
00054
00055
00056
00057
00058 struct DoubleBucket_t :
00059 public base::DoubleLinkable<DoubleBucket_t>
00060 {
00061 uint32_t info;
00062 };
00063
00064 template<class BucketType>
00065 struct DoubleBucket :
00066 public base::DoubleLinkable<BucketType>
00067 {
00068 uint32_t info;
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 void incRef(uint32_t mask)
00081 {
00082 if ((info & mask) != mask) info++;
00083 }
00084
00085
00086
00087
00088
00089
00090 bool decRef(uint32_t mask)
00091 {
00092 if ((info & mask) == mask) return false;
00093 assert(info & mask);
00094 return (--info & mask) == 0;
00095 }
00096 };
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 void rehash(SingleBucket_t*** tablePtr, uint32_t *maskPtr);
00113 void rehash(DoubleBucket_t*** tablePtr, uint32_t *maskPtr);
00114
00115
00116
00117
00118
00119
00120
00121
00122 template<class BucketType,
00123 class BucketParentType,
00124 class BucketParentTemplate>
00125 class AbstractTable
00126 {
00127 public:
00128
00129
00130
00131
00132
00133
00134 void disableRehash() { mayRehash = false; }
00135 void enableRehash() { mayRehash = mask < MAX_TABLE_SIZE-1; }
00136
00137
00138
00139
00140
00141 uint32_t getHashMask() const { return mask; }
00142
00143
00144
00145
00146
00147 size_t getNbBuckets() const { return nbBuckets; }
00148
00149
00150
00151
00152
00153
00154 size_t getTableSize() const { return mask + 1; }
00155
00156
00157
00158
00159 void reset()
00160 {
00161 nbBuckets = 0;
00162 base_resetLarge(buckets, getTableSize());
00163 }
00164
00165
00166
00167
00168
00169
00170 void resetDelete()
00171 {
00172 size_t n = getTableSize();
00173 BucketType **table = getBuckets();
00174 do {
00175 if (*table) {
00176 BucketType *bucket = *table;
00177 do {
00178 BucketType *next = bucket->getNext();
00179 delete bucket;
00180 bucket = next;
00181 } while(bucket);
00182 *table = NULL;
00183 }
00184 ++table;
00185 } while(--n);
00186 nbBuckets = 0;
00187 }
00188
00189
00190
00191
00192
00193 struct Bucket_t : public BucketParentTemplate
00194 {};
00195
00196
00197
00198
00199 base::Enumerator<BucketType> getEnumerator() const
00200 {
00201 return base::Enumerator<BucketType>(getTableSize(), getBuckets());
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211 void incBuckets()
00212 {
00213 ++nbBuckets;
00214 if (needsRehash() && mayRehash)
00215 {
00216 rehash(reinterpret_cast<BucketParentType***>(&buckets), &mask);
00217 mayRehash = mask < MAX_TABLE_SIZE-1;
00218 }
00219 }
00220
00221
00222
00223
00224
00225
00226 void decBuckets()
00227 {
00228 assert(nbBuckets);
00229 --nbBuckets;
00230 }
00231
00232
00233
00234
00235
00236
00237 BucketType** getAtBucket(uint32_t hashValue) const
00238 {
00239 return &buckets[hashValue & mask];
00240 }
00241
00242
00243
00244
00245
00246
00247 BucketType* getBucket(uint32_t hashValue) const
00248 {
00249 return buckets[hashValue & mask];
00250 }
00251
00252
00253 protected:
00254
00255
00256
00257 BucketType** getBuckets() const
00258 {
00259 return buckets;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 AbstractTable(uint32_t sizePower2, bool aggressive)
00271 : nbBuckets(0),
00272 mask((1 << sizePower2) - 1),
00273 shiftThreshold(aggressive ? 1 : 0),
00274 mayRehash(true)
00275 {
00276 buckets = new BucketType*[getTableSize()];
00277 base_resetLarge(buckets, getTableSize());
00278
00279 #ifndef NDEBUG
00280 for (size_t i = 0; i < getTableSize(); ++i) {
00281 assert(buckets[i] == 0);
00282 }
00283 #endif
00284 }
00285
00286
00287
00288
00289
00290 ~AbstractTable() { delete [] buckets; }
00291
00292
00293
00294
00295
00296 enum { MAX_TABLE_SIZE = (1 << 26) };
00297
00298 size_t nbBuckets;
00299
00300 private:
00301
00302
00303
00304 bool needsRehash() const
00305 {
00306 return nbBuckets > (mask >> shiftThreshold);
00307 }
00308
00309
00310 uint32_t mask;
00311
00312
00313 uint32_t shiftThreshold;
00314 bool mayRehash;
00315 BucketType **buckets;
00316 };
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 template<class BucketType>
00341 class TableSingle :
00342 public AbstractTable<BucketType,
00343 SingleBucket_t,
00344 SingleBucket<BucketType> >
00345 {
00346 public:
00347 TableSingle(uint32_t sizePower2 = 8, bool aggressive = false)
00348 : AbstractTable<BucketType,
00349 SingleBucket_t,
00350 SingleBucket<BucketType> >
00351 (sizePower2, aggressive)
00352 {}
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 void remove(BucketType *bucket)
00366 {
00367 remove(bucket, bucket->info);
00368 }
00369
00370
00371
00372
00373
00374
00375
00376 void remove(BucketType *bucket, uint32_t hashValue)
00377 {
00378 BucketType **entry =
00379 AbstractTable<BucketType,
00380 SingleBucket_t,
00381 SingleBucket<BucketType> >::getAtBucket(hashValue);
00382 while(*entry != bucket)
00383 {
00384 assert(*entry);
00385 entry = (*entry)->getAtNext();
00386 }
00387 *entry = bucket->getNext();
00388 AbstractTable<BucketType,
00389 SingleBucket_t,
00390 SingleBucket<BucketType> >::decBuckets();
00391 }
00392
00393 };
00394
00395 template<class BucketType>
00396 class TableDouble :
00397 public AbstractTable<BucketType,
00398 DoubleBucket_t,
00399 DoubleBucket<BucketType> >
00400 {
00401 public:
00402 TableDouble(uint32_t sizePower2 = 8, bool aggressive = false)
00403 : AbstractTable<BucketType,
00404 DoubleBucket_t,
00405 DoubleBucket<BucketType> >
00406 (sizePower2, aggressive)
00407 {}
00408
00409
00410
00411
00412 void remove(BucketType *bucket)
00413 {
00414 assert(bucket);
00415 bucket->unlink();
00416 AbstractTable<BucketType,
00417 DoubleBucket_t,
00418 DoubleBucket<BucketType> >::decBuckets();
00419 }
00420 };
00421
00422 }
00423
00424 #endif // INCLUDE_BASE_TABLES_H
00425