I'm trying to create a hash map that is thread-safe. I have a vector of mutexes for each bucket in the hash map to support a reader-writer lock for each entry in the hash map.
However, when I want to rehash the hash map, I want to lock the whole map so that no reads/writes can occur during rehashing.
I think I need an additional mutex, however do my Gets/Puts methods also need to acquire this mutex? How do I block other threads from doing Reads/Writes only when rehashing is occurring and not block each other when only writing and reading is happening?
This is how my current hash table class looks:
template<typename K, typename T>
class HashTable {
int num_buckets_;
double threshold_ratio_;
int num_elements_;
vector<vector<pair<T, K>>> table_;
vector<mutex> read_write_locks_;
mutex mu_;
int GetHash(const K& key) {
return hash<K>{}(key) % num_buckets_;
}
void Rehash() {
scoped_lock<mutex> lock(mu_); // Lock the whole table?
cout << "Threshold Value has been reached. Rehashing...\n";
vector<vector<T>> new_table(2 * num_buckets_);
num_buckets_ = 2 * num_buckets_;
vector<mutex> new_mutexes(2 * num_buckets_);
read_write_locks_.swap(new_mutexes);
// TODO : Implementation
}
public:
explicit HashTable(int num_buckets) : num_buckets_(num_buckets), threshold_ratio_(0.75), num_elements_(0) {
table_.resize(num_buckets);
vector<mutex> temp(num_buckets);
read_write_locks_.swap(temp);
}
void Put(const K& key, const T& val) {
++num_elements_;
if (static_cast<double>(num_elements_) / num_buckets_ > threshold_ratio_) {
Rehash();
}
int hash_val = GetHash(key);
scoped_lock<mutex> write_lock(read_write_locks_[hash_val]);
cout << "Putting Key: " << key << ", Hash: "<< hash_val << " with Value: " << val << '\n';
table_[hash_val].push_back({val, key}); //TODO: For existing keys it should replace the value, not create a new entry
}
T Get(const K& key) {
int hash_val = GetHash(key);
scoped_lock<mutex> read_lock(read_write_locks_[hash_val]);
if (table_[hash_val].size() >= 1) {
for (const auto& elem : table_[hash_val]) {
if (elem.second == key) {
cout << "Key: " << key << " gets value: " << elem.first << '\n';
return elem.first;
}
}
}
cerr << "Unable to find key in hash table. Terminating Program. \n";
exit(EXIT_FAILURE);
}
};
Aucun commentaire:
Enregistrer un commentaire