Files
mir_server/Gateway/srvlib/include/container/static_hash_table.h
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

166 lines
2.9 KiB
C++

#ifndef _STATIC_HASH_TABLE_H_
#define _STATIC_HASH_TABLE_H_
/************************
* 一个封装了暴雪hash算法的hashtable
* 表长度是固定的,不能动态增长,同时不提供删除的接口
* 为提供更快的性能
*************************/
namespace container
{
template <typename T, int MAX_NODE_NUM>
class StaticHashTable
{
protected:
class HashNode
{
public:
bool exists_; // 是否保存有数据
uint64_t key_; // key
T value_; // 数据值
};
size_t size_;
size_t out_count_;
static const size_t MAX_SIZE_ = MAX_NODE_NUM * 2;
HashNode ptr_[MAX_SIZE_];
//Vector<HashNode, MAX_NODE_NUM> data_;
public:
StaticHashTable() : size_(0), out_count_(0)
{
//data_.reserve(MAX_SIZE_);
//ptr_ = data_;
clear();
}
virtual ~StaticHashTable()
{
clear();
}
// 清空哈希表
void clear()
{
size_ = 0;
out_count_ = 0;
memset(ptr_, 0, MAX_SIZE_ * sizeof(HashNode));
}
inline size_t count() const { return size_; }
public:
//通过键查找值
inline T* get(uint64_t key)
{
int idx = getIndex(key);
return (idx >= 0) ? &ptr_[idx].value_ : NULL;
}
inline T* put(uint64_t key, T& data)
{
if (size_ >= MAX_NODE_NUM) return NULL;
unsigned int start = key % MAX_NODE_NUM, idx = start;
do
{
HashNode *node = ptr_ + idx;
//如果该位置没有值,则设置到该位置,否则向后找到一个空位置
if (!node->exists_)
{
node->exists_ = true;
node->key_ = key;
size_++;
node->value_ = data;
if (idx >= MAX_NODE_NUM)
++out_count_;
return &(node->value_);
}
#ifdef _DEBUG
else if (node->key_ == key)
{
//调用者重复添加,或者确实出现错误!
DebugBreak();
}
#endif
++idx;
}
while (idx < MAX_SIZE_);
return NULL;
}
inline bool remove(uint64_t key)
{
int idx = getIndex(key);
if (idx < 0)
return false;
ptr_[idx].exists_ = false;
--size_;
if (idx >= MAX_NODE_NUM)
--out_count_;
// 往后寻找一个移上来替换
int start = idx;
++idx;
while (ptr_[idx].exists_ && idx < (int)MAX_SIZE_)
{
if (start >= MAX_NODE_NUM)
{
int cnt = (int)out_count_ - (start - MAX_NODE_NUM);
if (cnt > 0)
{
memmove(ptr_ + start, ptr_ + idx, cnt * sizeof(HashNode));
// 整块内存往前移动了一格,原来最后的那个格就可以设为false
ptr_[MAX_NODE_NUM + out_count_].exists_ = false;
}
break;
}
int key_idx = ptr_[idx].key_ % MAX_NODE_NUM;
if (key_idx <= start)
{
ptr_[start] = ptr_[idx];
ptr_[idx].exists_ = false;
start = idx;
if (idx >= MAX_NODE_NUM)
-- out_count_;
}
++idx;
}
return true;
}
// 获取键在表中的索引
int getIndex(uint64_t key) const
{
size_t start = key % MAX_NODE_NUM, idx = start;
while (ptr_[idx].exists_ && idx < MAX_SIZE_)
{
if (ptr_[idx].key_ == key)
return (int)idx;
else
++idx;
}
return -1;
}
void update(uint64_t key, const T& data)
{
int idx = getIndex(key);
if (idx >= 0)
{
ptr_[idx].value_ = data;
}
}
};
}
#endif