哈希模块替换为 kshk123/hashMap 但还未适配

This commit is contained in:
CalciteM Team 2019-07-14 10:06:15 +08:00
parent 8faa9baa38
commit e55eee77a6
2 changed files with 230 additions and 121 deletions

View File

@ -1,72 +1,135 @@
#include "hashmap.h"
using namespace CTSL;
// template <typename T>
// HashMap<T>(uint64_t capacity, uint64_t size, T *pool)
// {
// this->capacity = capacity;
// size = size;
// //HashMap<T>::construct();
// }
template <typename T>
bool HashMap<T>::construct()
namespace CTSL //Concurrent Thread Safe Library
{
HashMap<T>::pool = new T[capacity];
// Function to find an entry in the bucket matching the key
// If key is found, the corresponding value is copied into the parameter "value" and function returns true.
// If key is not found, function returns false
template <typename K, typename V>
bool HashBucket<K, V>::find(const K &key, V &value) const
{
// A shared mutex is used to enable mutiple concurrent reads
std::shared_lock<std::shared_timed_mutex> lock(mutex_);
HashNode<K, V> *node = head;
if (HashMap<T>::pool == nullptr) {
return false;
while (node != nullptr) {
if (node->getKey() == key) {
value = node->getValue();
return true;
}
node = node->next;
}
return false;
}
// Function to insert into the bucket
// If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair
template <typename K, typename V>
void HashBucket<K, V>::insert(const K &key, const V &value)
{
// Exclusive lock to enable single write in the bucket
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
HashNode<K, V> *prev = nullptr;
HashNode<K, V> *node = head;
while (node != nullptr && node->getKey() != key) {
prev = node;
node = node->next;
}
return true;
}
template <typename T>
T& HashMap<T>::at(uint64_t i)
{
if (i >= capacity) {
qDebug() << "Error";
return HashMap<T>::pool[0];
if (nullptr == node) // New entry, create a node and add to bucket
{
if (nullptr == head) {
head = new HashNode<K, V>(key, value);
} else {
prev->next = new HashNode<K, V>(key, value);
}
} else {
node->setValue(value); // Key found in bucket, update the value
}
return HashMap<T>::pool[i];
}
template <typename T>
size_t HashMap<T>::getSize()
// Function to remove an entry from the bucket, if found
template <typename K, typename V>
void HashBucket<K, V>::erase(const K &key)
{
return size;
// Exclusive lock to enable single write in the bucket
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
HashNode<K, V> *prev = nullptr;
HashNode<K, V> *node = head;
while (node != nullptr && node->getKey() != key) {
prev = node;
node = node->next;
}
if (nullptr == node) //Key not found, nothing to be done
{
return;
} else //Remove the node from the bucket
{
if (head == node) {
head = node->next;
} else {
prev->next = node->next;
}
delete node; //Free up the memory
}
}
template <typename T>
uint64_t HashMap<T>::getCapacity()
// Function to clear the bucket
template <typename K, typename V>
void HashBucket<K, V>::clear()
{
return capacity;
// Exclusive lock to enable single write in the bucket
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
HashNode<K, V> *prev = nullptr;
HashNode<K, V> *node = head;
while (node != nullptr) {
prev = node;
node = node->next;
delete prev;
}
head = nullptr;
}
template <typename T>
uint64_t HashMap<T>::hashToAddr(uint64_t hash)
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to find an entry in the hash map matching the key.
// If key is found, the corresponding value is copied into the parameter "value" and function returns true.
// If key is not found, function returns false.
template <typename K, typename V, typename F>
bool HashMap<K, V, F>::find(const K &key, V &value) const
{
return hash << 32 >> 32;
size_t hashValue = hashFn(key) % hashSize;
return hashTable[hashValue].find(key, value);
}
template <typename T>
void HashMap<T>::insert(uint64_t hash, T &hashValue)
// Function to insert into the hash map.
// If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair.
template <typename K, typename V, typename F>
void HashMap<K, V, F>::insert(const K &key, const V &value)
{
uint64_t addr = hashToAddr(hash);
pool[addr] = hashValue;
size_t hashValue = hashFn(key) % hashSize;
hashTable[hashValue].insert(key, value);
}
template <typename T>
void HashMap<T>::clear()
// Function to remove an entry from the bucket, if found
template <typename K, typename V, typename F>
void HashMap<K, V, F>::erase(const K &key)
{
delete[] pool;
pool = nullptr;
size_t hashValue = hashFn(key) % hashSize;
hashTable[hashValue].erase(key);
}
template <typename T>
HashMap<T>* HashMap<T>::instance = new HashMap<T>(capacity = 1024, size = 0);
// Function to clean up the hasp map, i.e., remove all entries from it
template <typename K, typename V, typename F>
void HashMap<K, V, F>::clear()
{
for (size_t i = 0; i < hashSize; i++) {
(hashTable[i]).clear();
}
}
}

View File

@ -1,88 +1,134 @@
#ifndef HASHMAP_H
#define HASHMAP_H
#ifndef HASH_MAP_H_
#define HASH_MAP_H_
#include <limits>
#include <memory>
#include <mutex>
#include <qDebug>
#include <cstdint>
#include <iostream>
#include <functional>
#include <mutex>
#include <shared_mutex>
template <typename T>
class HashMap
constexpr size_t HASH_SIZE_DEFAULT = 1031; // A prime number as hash size gives a better distribution of values in buckets
namespace CTSL //Concurrent Thread Safe Library
{
// Class representing a templatized hash node
template <typename K, typename V>
class HashNode
{
public:
//HashMap(size_t capacity, size_t size, T* pool);
//~HashMap();
HashMap() = default;
static HashMap *getInstance()
HashNode() : next(nullptr)
{
#if 0
static std::once_flag s_flag;
std::call_once(s_flag, [&]() {
instance.reset(new HashMap);
});
#endif
if (instance)
return *instance;
}
HashNode(K key_, V value_) : next(nullptr), key(key_), value(value_)
{
}
~HashNode()
{
next = nullptr;
}
static void lock()
const K &getKey() const
{
hashMapMutex.lock();
return key;
}
void setValue(V value_)
{
value = value_;
}
const V &getValue() const
{
return value;
}
static void unlock()
{
hashMapMutex.unlock();
}
static T& at(uint64_t i);
#if 0
T& operator[](uint64_t hash)
{
uint64_t addr = hashToAddr(hash);
return pool[addr];
}
#endif
static uint64_t hashToAddr(uint64_t hash);
static char* find(uint64_t hash)
{
// uint64_t addr = hashToAddr(hash);
return pool[hash <<32 >>32];
}
static size_t getSize();
static size_t getCapacity();
static void clear();
static void insert(uint64_t hash, T &hashValue);
static bool construct();
public:
static const uint64_t capacity;
static uint64_t size;
static char *pool;
static std::mutex hashMapMutex;
//static std::auto_ptr<HashMap<T>> instance;
static HashMap<T>* instance;
public:
// 防止外部构造。
//HashMap() = default;
// 防止拷贝和赋值。
HashMap &operator=(const HashMap &) = delete; HashMap(const HashMap &another) = delete;
HashNode *next; // Pointer to the next node in the same bucket
private:
K key; // the hash key
V value; // the value corresponding to the key
};
// Class representing a hash bucket. The bucket is implemented as a singly linked list.
// A bucket is always constructed with a dummy head node
template <typename K, typename V>
class HashBucket
{
public:
HashBucket() : head(nullptr)
{
}
#endif // HASHMAP_H
~HashBucket() //delete the bucket
{
clear();
}
// Function to find an entry in the bucket matching the key
// If key is found, the corresponding value is copied into the parameter "value" and function returns true.
// If key is not found, function returns false
bool find(const K &key, V &value) const;
// Function to insert into the bucket
// If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair
void insert(const K &key, const V &value);
// Function to remove an entry from the bucket, if found
void erase(const K &key);
// Function to clear the bucket
void clear();
private:
HashNode<K, V> *head; //The head node of the bucket
mutable std::shared_timed_mutex mutex_; //The mutex for this bucket
};
// The class represting the hash map.
// It is expected for user defined types, the hash function will be provided.
// By default, the std::hash function will be used
// If the hash size is not provided, then a defult size of 1031 will be used
// The hash table itself consists of an array of hash buckets.
// Each hash bucket is implemented as singly linked list with the head as a dummy node created
// during the creation of the bucket. All the hash buckets are created during the construction of the map.
// Locks are taken per bucket, hence multiple threads can write simultaneously in different buckets in the hash map
template <typename K, typename V, typename F = std::hash<K> >
class HashMap
{
public:
HashMap(size_t hashSize_ = HASH_SIZE_DEFAULT) : hashSize(hashSize_)
{
hashTable = new HashBucket<K, V>[hashSize]; // create the hash table as an array of hash buckets
}
~HashMap()
{
delete[] hashTable;
}
// Copy and Move of the HashMap are not supported at this moment
HashMap(const HashMap &) = delete;
HashMap(HashMap &&) = delete;
HashMap &operator=(const HashMap &) = delete;
HashMap &operator=(HashMap &&) = delete;
// Function to find an entry in the hash map matching the key.
// If key is found, the corresponding value is copied into the parameter "value" and function returns true.
// If key is not found, function returns false.
bool find(const K &key, V &value) const;
// Function to insert into the hash map.
// If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair.
void insert(const K &key, const V &value);
// Function to remove an entry from the bucket, if found
void erase(const K &key);
// Function to clean up the hasp map, i.e., remove all entries from it
void clear();
private:
HashBucket<K, V> *hashTable;
F hashFn;
const size_t hashSize;
};
}
#endif /* HASH_MAP_H_ */