mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:58:11 +00:00
AK: Inline HashTable writing bucket lookup
The old approach was more complex and also had a very bad edge case with lots of collisions. This approach eliminates that possiblility. It also makes both reading and writing lookups a little bit faster.
This commit is contained in:
parent
509eb10df4
commit
e55b8712d4
1 changed files with 14 additions and 18 deletions
|
@ -304,7 +304,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Finder>
|
template<typename Finder>
|
||||||
Bucket* lookup_with_hash(unsigned hash, Finder finder, Bucket** usable_bucket_for_writing = nullptr) const
|
Bucket* lookup_with_hash(unsigned hash, Finder finder) const
|
||||||
{
|
{
|
||||||
if (is_empty())
|
if (is_empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -312,10 +312,6 @@ private:
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto& bucket = m_buckets[hash % m_capacity];
|
auto& bucket = m_buckets[hash % m_capacity];
|
||||||
|
|
||||||
if (usable_bucket_for_writing && !*usable_bucket_for_writing && !bucket.used) {
|
|
||||||
*usable_bucket_for_writing = &bucket;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bucket.used && finder(*bucket.slot()))
|
if (bucket.used && finder(*bucket.slot()))
|
||||||
return &bucket;
|
return &bucket;
|
||||||
|
|
||||||
|
@ -333,25 +329,25 @@ private:
|
||||||
|
|
||||||
Bucket& lookup_for_writing(const T& value)
|
Bucket& lookup_for_writing(const T& value)
|
||||||
{
|
{
|
||||||
auto hash = TraitsForT::hash(value);
|
|
||||||
Bucket* usable_bucket_for_writing = nullptr;
|
|
||||||
if (auto* bucket_for_reading = lookup_with_hash(
|
|
||||||
hash,
|
|
||||||
[&value](auto& entry) { return TraitsForT::equals(entry, value); },
|
|
||||||
&usable_bucket_for_writing)) {
|
|
||||||
return *const_cast<Bucket*>(bucket_for_reading);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (should_grow())
|
if (should_grow())
|
||||||
rehash(capacity() * 2);
|
rehash(capacity() * 2);
|
||||||
else if (usable_bucket_for_writing)
|
|
||||||
return *usable_bucket_for_writing;
|
|
||||||
|
|
||||||
|
|
||||||
|
auto hash = TraitsForT::hash(value);
|
||||||
|
Bucket* first_empty_bucket = nullptr;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto& bucket = m_buckets[hash % m_capacity];
|
auto& bucket = m_buckets[hash % m_capacity];
|
||||||
if (!bucket.used)
|
|
||||||
|
if (bucket.used && TraitsForT::equals(*bucket.slot(), value))
|
||||||
return bucket;
|
return bucket;
|
||||||
|
|
||||||
|
if (!bucket.used) {
|
||||||
|
if (!first_empty_bucket)
|
||||||
|
first_empty_bucket = &bucket;
|
||||||
|
|
||||||
|
if (!bucket.deleted)
|
||||||
|
return *const_cast<Bucket*>(first_empty_bucket);
|
||||||
|
}
|
||||||
|
|
||||||
hash = double_hash(hash);
|
hash = double_hash(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue