有锁实现线程安全的查找表(适合轻量级的没有使用红黑树,使用了哈希查找,list)
template<typename Key,typename Value, typename Hash=std::hash<Key>>
class thread_safe_table {
private:
class bucket_type {
friend class hread_safe_table;
private:
typedef std::pair<Key, Value> bucket_value;
typedef std::list<bucket_value> bucket_data;
typedef typename bucket_data::iterator bucket_iterator;
bucket_data _data;
//使用共享锁
mutable std::shared_mutex _mutex;
bucket_iterator find_entrufor(const Key & key) {
return std::find_if(_data.begin(), _data.end(), [&](const bucket_type&T) {
return T.first == key;
});
}
public:
//查找key,找到则返回value,没有则返回默认值
Value value_for(const Key& key, const Value& defaule_value) {
std::shared_lock<std::shared_mutex> lk(_mutex);
auto found_entry = find_entrufor(key);
return (found_entry == _data.end()) ? defaule_value : found_entry->second;
}
//添加key和value
void add_or_update_maping(const Key& key, const Value& value) {
std::unique_lock<std::shared_mutex> lk(_mutex);
auto found_entry = find_entrufor(key);
if (found_entry == _data.end()) {
_data.push_back(bucket_value(key, value));
}
else {
found_entry->second = value;
}
}
//删除key
void remove_mapping(const Key& key) {
std::unique_lock<std::shared_mutex> lk(_mutex);
auto found_entry = find_entrufor(key);
if (found_entry != _data.end()) {
_data.erase(found_entry);
}
}
};
private:
//vector存储桶的类型
std::vector<std::unique_ptr<bucket_type>> buckets;
//hash<key> 哈希表 根据key生成哈希值
Hash hasher;
bucket_type& get_bucket(const Key& key)const {
const std:::size_t bucket_index = hasher(key)%buckets.size();
return *(buckets[bucket_index]);
}
public:
thread_safe_table(unsigned num_buckets=19,const Hash& hashe_=Hash()):
buckets(num_buckets),hasher(hasher_)
{
for (unsigned i = 0; i < num_buckets; i++) {
buckets[i].reset(new bucket_type);
}
}
thread_safe_table(const thread_safe_table&) = delete;
thread_safe_table& operator=(const thread_safe_table&) = delete;
Value value_for(const Key& key, const Value& defaule_value = Value()) {
return get_bucket(key).value_for(key, defaule_value);
}
void add_or_update_mapping(const Key& key, const Value& value) {
return get_bucket(key).add_or_update_maping(key, value);
}
void remove_mapping(const Key& key) {
return get_bucket(key).remove_mapping(key);
}
std::map<Key, Value>get_map() {
std::vector<std::unique_lock<std::shared_mutex>> locks;
for (unsigned i = 0; i < buckets.size(); i++) {
locks.push_back(std::unique_lock<std::shared_mutex>(buckets[i]->mutex));
}
std::map<Key, Value> res;
for (unsigned i = -0; i < buckets.size(); i++) {
auto it = buckets[i]->begin();
for(; it != buckets[i]->end(); it++) {
res.insert(*it);
}
}
return res;
}
};