[map] Keep is_used, is_tombstone as booleans

This commit is contained in:
Behdad Esfahbod 2022-06-02 10:13:55 -06:00
parent 7ec3aad20f
commit 4f58ae60eb
1 changed files with 20 additions and 24 deletions

View File

@ -71,6 +71,16 @@ struct hb_hashmap_t
uint32_t hash; uint32_t hash;
V value; V value;
bool is_used_;
bool is_tombstone_;
bool is_used () const { return is_used_; }
void set_used (bool is_used) { is_used_ = is_used; }
bool is_tombstone () const { return is_tombstone_; }
void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; }
bool is_real () const { return is_used_ && !is_tombstone_; }
void clear () void clear ()
{ {
new (std::addressof (key)) K (); new (std::addressof (key)) K ();
@ -78,27 +88,12 @@ struct hb_hashmap_t
new (std::addressof (value)) V (); new (std::addressof (value)) V ();
value = hb_coerce<V> (vINVALID); value = hb_coerce<V> (vINVALID);
hash = 0; hash = 0;
is_used_ = false;
is_tombstone_ = false;
} }
bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); } bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); }
bool operator == (const item_t &o) { return *this == o.key; } bool operator == (const item_t &o) { return *this == o.key; }
bool is_unused () const
{
const K inv = hb_coerce<K> (kINVALID);
return key == inv;
}
bool is_tombstone () const
{
const K kinv = hb_coerce<K> (kINVALID);
const V vinv = hb_coerce<V> (vINVALID);
return key != kinv && value == vinv;
}
bool is_real () const
{
const K kinv = hb_coerce<K> (kINVALID);
const V vinv = hb_coerce<V> (vINVALID);
return key != kinv && value != vinv;
}
hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); } hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
uint32_t total_hash () const uint32_t total_hash () const
@ -213,7 +208,7 @@ struct hb_hashmap_t
return items[i].is_real () && items[i] == key ? items[i].value : hb_coerce<V> (vINVALID); return items[i].is_real () && items[i] == key ? items[i].value : hb_coerce<V> (vINVALID);
} }
void del (K key) { set (key, hb_coerce<V> (vINVALID)); } void del (K key) { set_with_hash (key, hb_hash (key), hb_coerce<V> (vINVALID), true); }
/* Has interface. */ /* Has interface. */
typedef V value_t; typedef V value_t;
@ -297,7 +292,7 @@ struct hb_hashmap_t
protected: protected:
template <typename VV> template <typename VV>
bool set_with_hash (K key, uint32_t hash, VV&& value) bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false)
{ {
if (unlikely (!successful)) return false; if (unlikely (!successful)) return false;
const K kinv = hb_coerce<K> (kINVALID); const K kinv = hb_coerce<K> (kINVALID);
@ -305,11 +300,10 @@ struct hb_hashmap_t
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
unsigned int i = bucket_for_hash (key, hash); unsigned int i = bucket_for_hash (key, hash);
const V vinv = hb_coerce<V> (vINVALID); if (is_delete && items[i].key != key)
if (value == vinv && items[i].key != key)
return true; /* Trying to delete non-existent key. */ return true; /* Trying to delete non-existent key. */
if (!items[i].is_unused ()) if (items[i].is_used ())
{ {
occupancy--; occupancy--;
if (!items[i].is_tombstone ()) if (!items[i].is_tombstone ())
@ -319,9 +313,11 @@ struct hb_hashmap_t
items[i].key = key; items[i].key = key;
items[i].value = value; items[i].value = value;
items[i].hash = hash; items[i].hash = hash;
items[i].set_used (true);
items[i].set_tombstone (is_delete);
occupancy++; occupancy++;
if (!items[i].is_tombstone ()) if (!is_delete)
population++; population++;
return true; return true;
@ -337,7 +333,7 @@ struct hb_hashmap_t
unsigned int i = hash % prime; unsigned int i = hash % prime;
unsigned int step = 0; unsigned int step = 0;
unsigned int tombstone = (unsigned) -1; unsigned int tombstone = (unsigned) -1;
while (!items[i].is_unused ()) while (items[i].is_used ())
{ {
if (items[i].hash == hash && items[i] == key) if (items[i].hash == hash && items[i] == key)
return i; return i;