Added simple version.
diff --git a/storage/SeparateChainingHashTable.hpp b/storage/SeparateChainingHashTable.hpp
index b8f62dd..3de4c65 100644
--- a/storage/SeparateChainingHashTable.hpp
+++ b/storage/SeparateChainingHashTable.hpp
@@ -713,7 +713,8 @@
writeScalarKeyToBucket(key, hash_code, bucket, prealloc_state);
new(static_cast<char*>(bucket) + kValueOffset) ValueT(value);
- std::atomic<std::size_t>* buckets_next_ptr = static_cast<std::atomic<std::size_t>*>(bucket);
+ std::atomic<std::size_t> *buckets_next_ptr
+ = static_cast<std::atomic<std::size_t>*>(bucket);
pending_chain_ptr = &(slots_[hash_code % header_->num_slots]);
for (;;) {
diff --git a/storage/SimpleScalarSeparateChainingHashTable.hpp b/storage/SimpleScalarSeparateChainingHashTable.hpp
index 8448896..50c3929 100644
--- a/storage/SimpleScalarSeparateChainingHashTable.hpp
+++ b/storage/SimpleScalarSeparateChainingHashTable.hpp
@@ -634,34 +634,36 @@
const std::size_t hash_code = key.getHashScalarLiteral();
Bucket *bucket = nullptr;
std::atomic<std::size_t> *pending_chain_ptr;
- std::size_t pending_chain_ptr_finish_value;
- if (locateBucketForInsertion(hash_code,
- &bucket,
- &pending_chain_ptr,
- &pending_chain_ptr_finish_value,
- prealloc_state)) {
- // Found an empty bucket.
- // Write the hash, which can be reversed to recover the key.
- bucket->hash = hash_code;
-
- // Store the value by using placement new with ValueT's copy constructor.
- new(&(bucket->value)) ValueT(value);
-
- // Update the previous chain pointer to point to the new bucket.
- pending_chain_ptr->store(pending_chain_ptr_finish_value, std::memory_order_release);
-
- // We're all done.
- return HashTablePutResult::kOK;
- } else if (bucket == nullptr) {
- // Ran out of buckets.
- DCHECK(prealloc_state == nullptr);
+
+ const std::size_t allocated_bucket_num
+ = (prealloc_state == nullptr)
+ ? header_->buckets_allocated.fetch_add(1, std::memory_order_relaxed)
+ : (prealloc_state->bucket_position)++;
+
+ if (allocated_bucket_num >= header_->num_buckets) {
+ header_->buckets_allocated.fetch_sub(1, std::memory_order_relaxed);
return HashTablePutResult::kOutOfSpace;
- } else {
- // Collision found, and duplicates aren't allowed.
- DCHECK(!allow_duplicate_keys);
- DCHECK(prealloc_state == nullptr);
- return HashTablePutResult::kDuplicateKey;
}
+
+ bucket = buckets_ + allocated_bucket_num;
+ bucket->hash = hash_code;
+ new(&(bucket->value)) ValueT(value);
+
+ std::atomic<std::size_t> *buckets_next_ptr = &(bucket->next);
+
+ pending_chain_ptr = &(slots_[hash_code % header_->num_slots]);
+ for (;;) {
+ // Save the old address;
+ std::size_t existing_chain_ptr = pending_chain_ptr->load(std::memory_order_release);
+
+ if (pending_chain_ptr->compare_exchange_strong(existing_chain_ptr,
+ allocated_bucket_num + 1,
+ std::memory_order_acq_rel)) {
+ buckets_next_ptr->store(existing_chain_ptr, std::memory_order_release);
+ break;
+ }
+ }
+ return HashTablePutResult::kOK;
}
template <typename ValueT,