| 860 | |
| 861 | template <typename Spec> |
| 862 | bool VMap<Spec>::add(VRef<K> key, VRef<V> value, VRef<K> &oldkey, |
| 863 | VRef<V> &oldvalue, bool replace) { |
| 864 | size_t hash = Spec::hash(key.as_ptr()); |
| 865 | size_t b = hash & (_nbuckets - 1); |
| 866 | _lock_bucket(b); |
| 867 | VRef<Node> node = _buckets[b]; |
| 868 | VRef<Node> last = vnull<Node>(); |
| 869 | while (!node.is_null()) { |
| 870 | Node *node_ptr = node.as_ptr(); |
| 871 | if (hash == node_ptr->hash |
| 872 | && Spec::equal(key.as_ptr(), node_ptr->key.as_ptr())) { |
| 873 | value = node_ptr->value; |
| 874 | if (!last.is_null()) { |
| 875 | // move to front |
| 876 | last->next = node_ptr->next; |
| 877 | node_ptr->next = _buckets[b]; |
| 878 | _buckets[b] = node; |
| 879 | } |
| 880 | oldkey = node_ptr->key; |
| 881 | oldvalue = node_ptr->value; |
| 882 | if (replace) { |
| 883 | node_ptr->key = key; |
| 884 | node_ptr->value = value; |
| 885 | } |
| 886 | _unlock_bucket(b); |
| 887 | return false; |
| 888 | } |
| 889 | last = node; |
| 890 | node = node->next; |
| 891 | } |
| 892 | node = vnew<Node>(); |
| 893 | Node *node_ptr = node.as_ptr(); |
| 894 | node_ptr->hash = hash; |
| 895 | node_ptr->key = key; |
| 896 | node_ptr->value = value; |
| 897 | node_ptr->next = _buckets[b]; |
| 898 | _buckets[b] = node; |
| 899 | oldkey = key; |
| 900 | oldvalue = value; |
| 901 | _unlock_bucket(b); |
| 902 | return true; |
| 903 | } |
| 904 | |
| 905 | template <typename Spec> |
| 906 | bool VMap<Spec>::remove(VRef<K> key, VRef<K> &oldkey, VRef<V> &oldvalue) { |