nall: fix various hashset issues

- Fix copy assignment operator
- Prevent reserve() from reallocating/rehashing unless capacity is increasing
- Prevent insert() from inserting duplicate entries
- Disable remove() as needs some work and is currently unused
このコミットが含まれているのは:
invertego 2022-10-09 14:42:48 -07:00 committed by Luke Usher
コミット ed43ab72b2
1個のファイルの変更12行の追加4行の削除

ファイルの表示

@ -24,8 +24,8 @@ struct hashset {
if(this == &source) return *this; if(this == &source) return *this;
reset(); reset();
if(source.pool) { if(source.pool) {
for(u32 n : range(source.count)) { for(u32 n : range(source.length)) {
insert(*source.pool[n]); if(source.pool[n]) insert(*source.pool[n]);
} }
} }
return *this; return *this;
@ -63,6 +63,8 @@ struct hashset {
} }
auto reserve(u32 size) -> void { auto reserve(u32 size) -> void {
if(length >= size) return;
//ensure all items will fit into pool (with <= 50% load) and amortize growth //ensure all items will fit into pool (with <= 50% load) and amortize growth
size = bit::round(max(size, count << 1)); size = bit::round(max(size, count << 1));
T** copy = new T*[size](); T** copy = new T*[size]();
@ -100,15 +102,20 @@ struct hashset {
//double pool size when load is >= 50% //double pool size when load is >= 50%
if(count >= (length >> 1)) reserve(length << 1); if(count >= (length >> 1)) reserve(length << 1);
count++;
u32 hash = value.hash() & (length - 1); u32 hash = value.hash() & (length - 1);
while(pool[hash]) if(++hash >= length) hash = 0; while(pool[hash]) {
if(value == *pool[hash]) return nothing;
if(++hash >= length) hash = 0;
}
count++;
pool[hash] = new T(value); pool[hash] = new T(value);
return *pool[hash]; return *pool[hash];
} }
#if 0
//does not work! todo: implement tombstones or rehashing to fill gaps.
auto remove(const T& value) -> bool { auto remove(const T& value) -> bool {
if(!pool) return false; if(!pool) return false;
@ -125,6 +132,7 @@ struct hashset {
return false; return false;
} }
#endif
protected: protected:
T** pool = nullptr; T** pool = nullptr;