Index: runtime/vm/hash_map.h |
diff --git a/runtime/vm/hash_map.h b/runtime/vm/hash_map.h |
index 5aa5343b33994636b1af4b355d74455d746781d9..6526acaf5c6b81f5c065e78ca06a10ceea543c2f 100644 |
--- a/runtime/vm/hash_map.h |
+++ b/runtime/vm/hash_map.h |
@@ -33,6 +33,7 @@ class BaseDirectChainedHashMap : public B { |
} |
void Insert(typename KeyValueTrait::Pair kv); |
+ bool Remove(typename KeyValueTrait::Key key); |
typename KeyValueTrait::Value LookupValue( |
typename KeyValueTrait::Key key) const; |
@@ -308,6 +309,68 @@ void BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Insert( |
} |
+template <typename KeyValueTrait, typename B, typename Allocator> |
+bool BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Remove( |
+ typename KeyValueTrait::Key key) { |
+ uword pos = Bound(static_cast<uword>(KeyValueTrait::Hashcode(key))); |
+ |
+ // Check to see if the first element in the bucket is the one we want to |
+ // remove. |
+ if (KeyValueTrait::KeyOf(array_[pos].kv) == key) { |
+ if (array_[pos].next == kNil) { |
+ array_[pos] = HashMapListElement(); |
+ } else { |
+ intptr_t next = array_[pos].next; |
+ array_[pos] = lists_[next]; |
+ lists_[next] = HashMapListElement(); |
+ lists_[next].next = free_list_head_; |
+ free_list_head_ = next; |
+ } |
+ count_--; |
+ return true; |
+ } |
+ |
+ intptr_t current = array_[pos].next; |
+ |
+ // If there's only the single element in the bucket and it does not match the |
+ // key to be removed, just return. |
+ if (current == kNil) { |
+ return false; |
+ } |
+ |
+ // Check the case where the second element in the bucket is the one to be |
+ // removed. |
+ if (KeyValueTrait::KeyOf(lists_[current].kv) == key) { |
+ array_[pos].next = lists_[current].next; |
+ lists_[current] = HashMapListElement(); |
+ lists_[current].next = free_list_head_; |
+ free_list_head_ = current; |
+ count_--; |
+ return true; |
+ } |
+ |
+ // Finally, iterate through the rest of the bucket to see if we can find the |
+ // entry that matches our key. |
+ intptr_t previous; |
+ while (KeyValueTrait::KeyOf(lists_[current].kv) != key) { |
+ previous = current; |
+ current = lists_[current].next; |
+ |
+ if (current == kNil) { |
+ // Could not find entry with provided key to remove. |
+ return false; |
+ } |
+ } |
+ |
+ lists_[previous].next = lists_[current].next; |
+ lists_[current] = HashMapListElement(); |
+ lists_[current].next = free_list_head_; |
+ free_list_head_ = current; |
+ count_--; |
+ return true; |
+} |
+ |
+ |
template <typename KeyValueTrait> |
class DirectChainedHashMap |
: public BaseDirectChainedHashMap<KeyValueTrait, ValueObject> { |