26 #ifndef SET_E_INCLUDED
27 #define SET_E_INCLUDED
34 #include "../base/ver.h"
38 #include "../base/str.h"
41 #ifndef CHECK_INCLUDED
42 #include "../base/check.h"
46 #include "../mem/page.h"
49 #ifndef MPOOL_INCLUDED
50 #include "../mem/mpool.h"
53 #ifndef RELSIZE_INCLUDED
54 #include "../rel/relsize.h"
58 #include "../rel/rel.h"
87 static const int SET_E_BUCKETSIZE = 16;
93 static const long SET_E_MAGIC = 0x5354450AL;
106 T Elems[SET_E_BUCKETSIZE];
109 #define SET_E_BUCKET_T set_e_bucket_c<T>*
110 #define SET_E_BUCKET_NULL (static_cast<set_e_bucket_c<T> *>(0))
111 #define SET_E_BUCKET_L0_NULL (static_cast<set_e_bucket_c<T> *>(0))
112 #define SET_E_BUCKET_L1_NULL (static_cast<set_e_bucket_c<T> **>(0))
113 #define SET_E_BUCKET_L2_NULL (static_cast<set_e_bucket_c<T> ***>(0))
122 #define SET_E_PAGESIZE_L0 PAGE_SIZE(set_e_bucket_c<T> *)
123 #define SET_E_PAGESIZE_L1 PAGE_SIZE(set_e_bucket_c<T> **)
124 #define SET_E_PAGESIZE_L2 PAGE_SIZE(set_e_bucket_c<T> ***)
232 bool contains(T elem)
const {
238 int hash_val = elem.hash();
239 CHECK(hash_val >= 0,
"set_e_c::contains: hash_val is negative");
247 SET_E_BUCKET_T bucket;
251 CHECK(hash_val < SET_E_PAGESIZE_L0,
252 "set_e_c::contains: hash_val invalid (L0)");
253 bucket = HashTab.Level0[hash_val];
257 CHECK(hash_val < SET_E_PAGESIZE_L1 * SET_E_PAGESIZE_L0,
258 "set_e_c::contains: hash_val invalid (L1)");
260 SET_E_BUCKET_T *page =
261 HashTab.Level1[hash_val / SET_E_PAGESIZE_L0];
262 bucket = page[hash_val % SET_E_PAGESIZE_L0];
267 CHECK(hash_val < SET_E_PAGESIZE_L2 * SET_E_PAGESIZE_L1 *
269 "set_e_c::contains: hash_val invalid (L2)");
271 int index2 = hash_val /
272 (SET_E_PAGESIZE_L1 * SET_E_PAGESIZE_L0);
273 int index1 = hash_val %
274 (SET_E_PAGESIZE_L1 * SET_E_PAGESIZE_L0);
275 int index0 = index1 % SET_E_PAGESIZE_L0;
276 index1 = index1 / SET_E_PAGESIZE_L0;
277 SET_E_BUCKET_T **page_level1 = HashTab.Level2[index2];
278 SET_E_BUCKET_T *page_level0 = page_level1[index1];
279 bucket = page_level0[index0];
289 for(; bucket != SET_E_BUCKET_NULL; bucket = bucket->Overflow) {
290 T *elem_ptr = bucket->Elems;
291 for(
int i = 0; i < bucket->NumElems; i++)
292 if(*elem_ptr++ == elem)
302 int hash_size()
const {
311 int num_buckets()
const {
320 int num_overflow()
const {
329 int size_value(relsize_t relsize)
const {
331 CHECK(relsize_valid(relsize),
332 "set_e_c::size_value: invalid size measure");
336 case RELSIZE_OBJ_SIZE:
338 case RELSIZE_HASHTAB_SIZE:
340 case RELSIZE_BUCKET_SIZE:
341 return SET_E_BUCKETSIZE;
342 case RELSIZE_BUCKET_BYTES:
343 return static_cast<int>(
345 case RELSIZE_TOTAL_BUCKETS:
347 case RELSIZE_OVERFLOW_BUCKETS:
371 void dump_bucket(
int i, SET_E_BUCKET_T bucket)
const;
417 SET_E_BUCKET_T Level0[SET_E_PAGESIZE_L0];
418 SET_E_BUCKET_T * Level1[SET_E_PAGESIZE_L1];
419 SET_E_BUCKET_T ** Level2[SET_E_PAGESIZE_L2];
433 inline SET_E_BUCKET_T get_new_bucket(
int bits)
438 page_t page = MemPool.alloc_page();
439 if(page == PAGE_NULL) {
441 return SET_E_BUCKET_NULL;
446 MemPtr =
reinterpret_cast<SET_E_BUCKET_T
>(MemPage);
451 CHECK(MemFree > 0,
"set_e_c::get_new_bucket: Page too small");
452 SET_E_BUCKET_T bucket = MemPtr++;
459 bucket->NumElems = 0;
460 bucket->LocalBits = bits;
461 bucket->Overflow = SET_E_BUCKET_NULL;
471 inline SET_E_BUCKET_T * hashtab_entry(
int i) {
477 CHECK(i >= 0,
"set_e_c::hashtab_entry: i is negative");
479 "set_e_c::hashtab_entry: i is too large");
484 CHECK(i < SET_E_PAGESIZE_L0,
485 "set_e_c::hashtab_entry: i invalid (L0)");
486 return &(HashTab.Level0[i]);
488 CHECK(i < SET_E_PAGESIZE_L1 * SET_E_PAGESIZE_L0,
489 "set_e_c::hashtab_entry: i invalid (L1)");
491 SET_E_BUCKET_T *page =
492 HashTab.Level1[i / SET_E_PAGESIZE_L0];
493 return page + (i % SET_E_PAGESIZE_L0);
496 CHECK(i < SET_E_PAGESIZE_L2 * SET_E_PAGESIZE_L1 *
498 "set_e_c::hashtab_entry: i invalid (L2)");
500 int index2 = i / (SET_E_PAGESIZE_L1*SET_E_PAGESIZE_L0);
501 int index1 = i % (SET_E_PAGESIZE_L1*SET_E_PAGESIZE_L0);
502 int index0 = index1 % SET_E_PAGESIZE_L0;
503 index1 = index1 / SET_E_PAGESIZE_L0;
504 SET_E_BUCKET_T **indirect_page = HashTab.Level2[index2];
505 SET_E_BUCKET_T *page = indirect_page[index1];
506 return page + index0;
510 "set_e_c::hashtab_entry: illegal level");
519 inline void set_hashtab_entry(
int i, SET_E_BUCKET_T bucket)
522 CHECK(i >= 0,
"set_e_c::set_hashtab_entry: i is negative");
524 "set_e_c::set_hashtab_entry: i is too large");
527 SET_E_BUCKET_T *entry = hashtab_entry(i);
538 inline SET_E_BUCKET_T *copy_page0(SET_E_BUCKET_T *input_page);
544 inline SET_E_BUCKET_T **copy_page1(SET_E_BUCKET_T **input_page);
550 inline bool double_table();
#define CHECK_IMPOSSIBLE(MSG)
Definition: check.h:151
#define CHECK_VALID(EX)
Definition: check.h:85
const char * str_t
Definition: str.h:41
#define STR_NULL
Definition: str.h:52
#define CHECK(EX, MSG)
Definition: check.h:69