Skip to content

Commit 8f6d86d

Browse files
committed
Add implementation
1 parent 64d6f0c commit 8f6d86d

6 files changed

Lines changed: 402 additions & 0 deletions

File tree

ConcurrentHashMap.h

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
ConcurrentHashMap C++ Library
3+
A thread-safe hash map implementation in C++ with support for concurrent read and write operations.
4+
This C++ library provides a ConcurrentHashMap class that allows multiple threads to perform read and write operations on a hash map concurrently. It uses std::shared_timed_mutex to provide efficient and safe concurrent access.
5+
Author : Eray Ozturk | erayozturk1@gmail.com
6+
URL : github.com/diffstorm
7+
Date : 10/06/2020
8+
*/
9+
10+
#ifndef CONCURRENT_HASH_MAP_H
11+
#define CONCURRENT_HASH_MAP_H
12+
13+
#include <iostream>
14+
#include <vector>
15+
#include <mutex>
16+
#include <functional>
17+
18+
template <typename Key, typename Value, typename Hash = std::hash<Key>>
19+
class ConcurrentHashMap {
20+
private:
21+
// Define the structure of each node in the hash map
22+
struct Node {
23+
Key key;
24+
Value value;
25+
Node* next;
26+
Node(const Key& k, const Value& v) : key(k), value(v), next(nullptr) {}
27+
};
28+
29+
// Define the hash map buckets and associated mutexes
30+
std::vector<std::vector<Node*>> buckets;
31+
std::vector<std::mutex> mutexes;
32+
Hash hashFunction;
33+
34+
// Get the mutex for a given key
35+
std::mutex& getMutex(const Key& key) {
36+
std::size_t hashValue = hashFunction(key);
37+
return mutexes[hashValue % mutexes.size()];
38+
}
39+
40+
public:
41+
explicit ConcurrentHashMap(std::size_t num_buckets = 16) : buckets(num_buckets), mutexes(num_buckets) {}
42+
43+
// Insert a key-value pair into the hash map
44+
void insert(const Key& key, const Value& value) {
45+
std::unique_lock lock(getMutex(key));
46+
std::size_t hashValue = hashFunction(key);
47+
std::size_t index = hashValue % buckets.size();
48+
49+
Node* newNode = new Node(key, value);
50+
newNode->next = buckets[index].empty() ? nullptr : buckets[index][0]; // Cast to Node*
51+
buckets[index] = {newNode};
52+
}
53+
54+
// Retrieve the value associated with a key from the hash map
55+
bool get(const Key& key, Value& value) {
56+
std::unique_lock lock(getMutex(key));
57+
std::size_t hashValue = hashFunction(key);
58+
std::size_t index = hashValue % buckets.size();
59+
60+
Node* current = buckets[index].empty() ? nullptr : buckets[index][0]; // Cast to Node*
61+
while (current != nullptr) {
62+
if (current->key == key) {
63+
value = current->value;
64+
return true; // Found the key
65+
}
66+
current = current->next; // No need to cast here
67+
}
68+
69+
return false; // Key not found
70+
}
71+
72+
// Remove a key-value pair from the hash map
73+
void remove(const Key& key) {
74+
std::unique_lock lock(getMutex(key));
75+
std::size_t hashValue = hashFunction(key);
76+
std::size_t index = hashValue % buckets.size();
77+
78+
Node* current = buckets[index].empty() ? nullptr : buckets[index][0]; // Cast to Node*
79+
Node* prev = nullptr;
80+
81+
while (current != nullptr) {
82+
if (current->key == key) {
83+
if (prev == nullptr) {
84+
buckets[index][0] = current->next; // No need to cast here
85+
} else {
86+
prev->next = current->next; // No need to cast here
87+
}
88+
delete current;
89+
return;
90+
}
91+
prev = current;
92+
current = current->next; // No need to cast here
93+
}
94+
}
95+
96+
// Print the contents of the hash map
97+
void print() {
98+
for (std::size_t i = 0; i < buckets.size(); ++i) {
99+
std::lock_guard lock(mutexes[i]);
100+
std::cout << "Bucket " << i << ": ";
101+
Node* current = buckets[i].empty() ? nullptr : buckets[i][0]; // Cast to Node*
102+
while (current != nullptr) {
103+
std::cout << "(" << current->key << ", " << current->value << ") ";
104+
current = current->next; // No need to cast here
105+
}
106+
std::cout << std::endl;
107+
}
108+
}
109+
110+
// Destructor to clean up memory
111+
~ConcurrentHashMap() {
112+
for (auto& bucket : buckets) {
113+
Node* current = bucket.empty() ? nullptr : bucket[0]; // Cast to Node*
114+
while (current != nullptr) {
115+
Node* temp = current;
116+
current = current->next; // No need to cast here
117+
delete temp;
118+
}
119+
}
120+
}
121+
};
122+
123+
#endif // CONCURRENT_HASH_MAP_H

ConcurrentHashMap2.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
ConcurrentHashMap C++ Library
3+
A thread-safe hash map implementation in C++ with support for concurrent read and write operations.
4+
This C++ library provides a ConcurrentHashMap class that allows multiple threads to perform read and write operations on a hash map concurrently. It uses std::shared_timed_mutex to provide efficient and safe concurrent access, also std::unordered_map to simplify the code.
5+
Author : Eray Ozturk | erayozturk1@gmail.com
6+
URL : github.com/diffstorm
7+
Date : 01/08/2020
8+
*/
9+
#ifndef CONCURRENT_HASH_MAP_H
10+
#define CONCURRENT_HASH_MAP_H
11+
12+
#include <unordered_map>
13+
#include <shared_mutex>
14+
#include <string>
15+
#include <iostream>
16+
17+
template <typename Key, typename Value>
18+
class ConcurrentHashMap {
19+
private:
20+
std::unordered_map<Key, Value> map_;
21+
mutable std::shared_timed_mutex mutex_;
22+
23+
public:
24+
void insert(const Key& key, const Value& value) {
25+
std::unique_lock lock(mutex_);
26+
map_[key] = value;
27+
}
28+
29+
bool get(const Key& key, Value& value) const {
30+
std::shared_lock lock(mutex_);
31+
auto it = map_.find(key);
32+
if (it != map_.end()) {
33+
value = it->second;
34+
return true;
35+
}
36+
return false;
37+
}
38+
39+
void remove(const Key& key) {
40+
std::unique_lock lock(mutex_);
41+
map_.erase(key);
42+
}
43+
44+
void print() const {
45+
std::shared_lock lock(mutex_);
46+
for (const auto& entry : map_) {
47+
std::cout << "Key: " << entry.first << ", Value: " << entry.second << std::endl;
48+
}
49+
}
50+
51+
// Destructor to clean up memory
52+
~ConcurrentHashMap() {
53+
// No explicit memory cleanup needed for std::unordered_map
54+
}
55+
};
56+
57+
#endif // CONCURRENT_HASH_MAP_H

ConcurrentHashMap3.h

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
ConcurrentHashMap C++ Library
3+
A thread-safe hash map implementation in C++ with support for concurrent read and write operations.
4+
This C++ library provides a ConcurrentHashMap class that allows multiple threads to perform read and write operations on a hash map concurrently. It uses std::shared_timed_mutex to provide efficient and safe concurrent access, also std::list within each bucket to handle collisions.
5+
Author : Eray Ozturk | erayozturk1@gmail.com
6+
URL : github.com/diffstorm
7+
Date : 12/09/2020
8+
*/
9+
10+
#ifndef CONCURRENT_HASH_MAP_H
11+
#define CONCURRENT_HASH_MAP_H
12+
13+
#include <iostream>
14+
#include <vector>
15+
#include <mutex>
16+
#include <shared_mutex>
17+
#include <functional>
18+
#include <list>
19+
20+
template <typename Key, typename Value, typename Hash = std::hash<Key>>
21+
class ConcurrentHashMap {
22+
private:
23+
// Define the structure of each node in the hash map
24+
struct Node {
25+
Key key;
26+
Value value;
27+
};
28+
29+
// Define the hash map buckets and associated mutexes
30+
std::vector<std::list<Node>> buckets;
31+
std::vector<std::shared_mutex> mutexes;
32+
Hash hashFunction;
33+
34+
// Get the mutex for a given key
35+
std::shared_mutex& getMutex(const Key& key) {
36+
std::size_t hashValue = hashFunction(key);
37+
return mutexes[hashValue % mutexes.size()];
38+
}
39+
40+
public:
41+
explicit ConcurrentHashMap(std::size_t num_buckets = 16) : buckets(num_buckets), mutexes(num_buckets) {}
42+
43+
// Insert a key-value pair into the hash map
44+
void insert(const Key& key, const Value& value) {
45+
std::unique_lock lock(getMutex(key));
46+
std::size_t hashValue = hashFunction(key);
47+
std::size_t index = hashValue % buckets.size();
48+
49+
auto& bucket = buckets[index];
50+
auto it = std::find_if(bucket.begin(), bucket.end(), [&](const Node& node) { return node.key == key; });
51+
52+
if (it != bucket.end()) {
53+
// Update existing key
54+
it->value = value;
55+
} else {
56+
// Insert new key-value pair
57+
bucket.push_back({key, value});
58+
}
59+
}
60+
61+
// Retrieve the value associated with a key from the hash map
62+
bool get(const Key& key, Value& value) {
63+
std::shared_lock lock(getMutex(key));
64+
std::size_t hashValue = hashFunction(key);
65+
std::size_t index = hashValue % buckets.size();
66+
67+
const auto& bucket = buckets[index];
68+
auto it = std::find_if(bucket.begin(), bucket.end(), [&](const Node& node) { return node.key == key; });
69+
70+
if (it != bucket.end()) {
71+
value = it->value;
72+
return true; // Found the key
73+
}
74+
75+
return false; // Key not found
76+
}
77+
78+
// Remove a key-value pair from the hash map
79+
void remove(const Key& key) {
80+
std::unique_lock lock(getMutex(key));
81+
std::size_t hashValue = hashFunction(key);
82+
std::size_t index = hashValue % buckets.size();
83+
84+
auto& bucket = buckets[index];
85+
bucket.remove_if([&](const Node& node) { return node.key == key; });
86+
}
87+
88+
// Print the contents of the hash map
89+
void print() {
90+
for (std::size_t i = 0; i < buckets.size(); ++i) {
91+
std::shared_lock lock(mutexes[i]);
92+
std::cout << "Bucket " << i << ": ";
93+
const auto& bucket = buckets[i];
94+
for (const auto& node : bucket) {
95+
std::cout << "(" << node.key << ", " << node.value << ") ";
96+
}
97+
std::cout << std::endl;
98+
}
99+
}
100+
101+
// Destructor to clean up memory
102+
~ConcurrentHashMap() = default; // The default destructor is sufficient for cleanup.
103+
};
104+
105+
#endif // CONCURRENT_HASH_MAP_H

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 diffstorm
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# ConcurrentHashMap C++ Library
2+
3+
4+
A thread-safe hash map implementation in C++ with support for concurrent read and write operations.
5+
6+
7+
## Overview
8+
9+
10+
This is an attempt to create an equivalent of Java's ConcurrentHashMap in C++. It is not a direct equivalent because the underlying concurrency models in Java and C++ are different.
11+
12+
13+
This C++ library and its different versions provides a ConcurrentHashMap class that allows multiple threads to perform read and write operations on a hash map concurrently. It uses std::shared_timed_mutex to provide efficient and safe concurrent access.
14+
15+
16+
## Usage
17+
18+
19+
1. **Include the Library:**
20+
```cpp
21+
#include "ConcurrentHashMap.h"
22+
```
23+
2. **Create an Instance:**
24+
```cpp
25+
ConcurrentHashMap<std::string, int> concurrentMap;
26+
```
27+
3. **Perform Operations:**
28+
29+
```cpp
30+
// Insert a key-value pair
31+
concurrentMap.insert("one", 1);
32+
33+
// Retrieve the value for a key
34+
int value;
35+
if (concurrentMap.get("one", value)) {
36+
std::cout << "Value for key 'one': " << value << std::endl;
37+
} else {
38+
std::cout << "Key 'one' not found." << std::endl;
39+
}
40+
41+
// Remove a key-value pair
42+
concurrentMap.remove("one");
43+
```
44+
45+
46+
## Additional Methods:
47+
48+
`print()`: Print the contents of the hash map.
49+
50+
51+
## Build and Run Example
52+
To compile the example test.cpp, you can use:
53+
```
54+
g++ -std=c++17 test.cpp -o test
55+
```
56+
And run it:
57+
```
58+
./test
59+
```
60+
61+
62+
## License
63+
This project is licensed under the MIT License - see the LICENSE file for details.
64+
65+
Feel free to contribute, report issues, or suggest improvements!

0 commit comments

Comments
 (0)