整体结构
cyber atomic hash map是用一个数组存储桶(bucket),桶是一个链表的形式存储值,每一个结点是个entry,哈希冲突的解决方法是链地址法。
整体结构 --- entry
entry为bucket链表的结点单位,代码:
struct Entry {Entry() {}explicit Entry(K key) : key(key) {value_ptr.store(new V(), std::memory_order_release);}Entry(K key, const V &value) : key(key) {value_ptr.store(new V(value), std::memory_order_release);}Entry(K key, V &&value) : key(key) {value_ptr.store(new V(std::forward<V>(value)), std::memory_order_release);}~Entry() { delete value_ptr.load(std::memory_order_acquire); }K key = 0;std::atomic<V *> value_ptr = {nullptr};std::atomic<Entry *> next = {nullptr};
};
存入每一个键值对的key,value,和同哈希值的next,需要注意的是value_ptr也就是指向value的指针,以及next指针都是原子的(atomic),也就是针对该指针的操作不需要考虑同步互斥问题。
整体结构 --- bucket
bucket串接的是一系列具有相同哈希值的键值对,且按照key升序串接,且具有一个头节点head_:
class Bucket {public:...Entry *head_;
};
bucket接口:
bool Has(K key)
bool Has(K key) {Entry *m_target = head_->next.load(std::memory_order_acquire);while (Entry *target = m_target) {if (target->key < key) {m_target = target->next.load(std::memory_order_acquire);continue;} else {return target->key == key;}}return false;
}
由于每个buffer是个升序链表,所以可以如上寻找
bool Find(K key, Entry **prev_ptr, Entry **target_ptr)
bool Find(K key, Entry **prev_ptr, Entry **target_ptr) {Entry *prev = head_;Entry *m_target = head_->next.load(std::memory_order_acquire);while (Entry *target = m_target) {if (target->key == key) {*prev_ptr = prev;*target_ptr = target;return true;} else if (target->key > key) {*prev_ptr = prev;*target_ptr = target;return false;} else {prev = target;m_target = target->next.load(std::memory_order_acquire);}}*prev_ptr = prev;*target_ptr = nullptr;return false;
}
void Insert(K key, const V &value)
void Insert(K key, const V &value) {Entry *prev = nullptr;Entry *target = nullptr;Entry *new_entry = nullptr;V *new_value = nullptr;while (true) {if (Find(key, &prev, &target)) {// key exists, update valueif (!new_value) {new_value = new V(value);}auto old_val_ptr = target->value_ptr.load(std::memory_order_acquire);if (target->value_ptr.compare_exchange_strong(old_val_ptr, new_value, std::memory_order_acq_rel,std::memory_order_relaxed)) {delete old_val_ptr;if (new_entry) {delete new_entry;new_entry = nullptr;}return;}continue;} else {if (!new_entry) {new_entry = new Entry(key, value);}new_entry->next.store(target, std::memory_order_release);if (prev->next.compare_exchange_strong(target, new_entry,std::memory_order_acq_rel,std::memory_order_relaxed)) {// Insert successif (new_value) {delete new_value;new_value = nullptr;}return;}// another entry has been inserted, retry}}
}
void Insert(K key, V &&value)
void Insert(K key, V &&value) {Entry *prev = nullptr;Entry *target = nullptr;Entry *new_entry = nullptr;V *new_value = nullptr;while (true) {if (Find(key, &prev, &target)) {// key exists, update valueif (!new_value) {new_value = new V(std::forward<V>(value));}auto old_val_ptr = target->value_ptr.load(std::memory_order_acquire);if (target->value_ptr.compare_exchange_strong(old_val_ptr, new_value, std::memory_order_acq_rel,std::memory_order_relaxed)) {delete old_val_ptr;if (new_entry) {delete new_entry;new_entry = nullptr;}return;}continue;} else {if (!new_entry) {new_entry = new Entry(key, value);}new_entry->next.store(target, std::memory_order_release);if (prev->next.compare_exchange_strong(target, new_entry,std::memory_order_acq_rel,std::memory_order_relaxed)) {// Insert successif (new_value) {delete new_value;new_value = nullptr;}return;}// another entry has been inserted, retry}}
}
void Insert(K key)
void Insert(K key) {Entry *prev = nullptr;Entry *target = nullptr;Entry *new_entry = nullptr;V *new_value = nullptr;while (true) {if (Find(key, &prev, &target)) {// key exists, update valueif (!new_value) {new_value = new V();}auto old_val_ptr = target->value_ptr.load(std::memory_order_acquire);if (target->value_ptr.compare_exchange_strong(old_val_ptr, new_value, std::memory_order_acq_rel,std::memory_order_relaxed)) {delete old_val_ptr;if (new_entry) {delete new_entry;new_entry = nullptr;}return;}continue;} else {if (!new_entry) {new_entry = new Entry(key);}new_entry->next.store(target, std::memory_order_release);if (prev->next.compare_exchange_strong(target, new_entry,std::memory_order_acq_rel,std::memory_order_relaxed)) {// Insert successif (new_value) {delete new_value;new_value = nullptr;}return;}// another entry has been inserted, retry}}
}
bool Get(K key, V **value)
bool Get(K key, V **value) {Entry *prev = nullptr;Entry *target = nullptr;if (Find(key, &prev, &target)) {*value = target->value_ptr.load(std::memory_order_acquire);return true;}return false;
}
接口
bool Has(K key) {uint64_t index = key & mode_num_;return table_[index].Has(key);}bool Get(K key, V **value) {uint64_t index = key & mode_num_;return table_[index].Get(key, value);}bool Get(K key, V *value) {uint64_t index = key & mode_num_;V *val = nullptr;bool res = table_[index].Get(key, &val);if (res) {*value = *val;}return res;}void Set(K key) {uint64_t index = key & mode_num_;table_[index].Insert(key);}void Set(K key, const V &value) {uint64_t index = key & mode_num_;table_[index].Insert(key, value);}void Set(K key, V &&value) {uint64_t index = key & mode_num_;table_[index].Insert(key, std::forward<V>(value));}