Discover a generic, thread-safe map class in C++ that’s production-ready and handles any data type. Unlike std::map, which is not thread-safe by default, this class ensures safe concurrent access in multi-threaded environments.
Why Use This?
This thread-safe map class offers robust protection against concurrent access issues, unlike the default std::map, which isn’t thread-safe. Its generic design accommodates any data type, making it a versatile choice for reliable and efficient multi-threaded applications.
Source code:
#ifndef ThreadSafeMap_h
#define ThreadSafeMap_h
#include <map>
#include <mutex>
namespace your_namespace {
template <class Key, class T, class Compare = std::less<Key>,
class Allocator = std::allocator<std::pair<const Key, T>>>
class ThreadSafeMap {
public:
typedef typename std::map<Key, T, Compare, Allocator>::iterator iterator;
typedef typename std::map<Key, T, Compare, Allocator>::const_iterator
const_iterator;
typedef typename std::map<Key, T, Compare, Allocator>::reverse_iterator
reverse_iterator;
typedef
typename std::map<Key, T, Compare, Allocator>::const_reverse_iterator
const_reverse_iterator;
typedef typename std::map<Key, T, Compare, Allocator>::allocator_type
allocator_type;
typedef typename std::map<Key, T, Compare, Allocator>::size_type size_type;
typedef
typename std::map<Key, T, Compare, Allocator>::key_compare key_compare;
typedef typename std::map<Key, T, Compare, Allocator>::value_compare
value_compare;
typedef
typename std::map<Key, T, Compare, Allocator>::value_type value_type;
explicit ThreadSafeMap(const Compare &comp = Compare(),
const Allocator &alloc = Allocator())
: internal(comp, alloc) {}
template <class InputIterator>
ThreadSafeMap(InputIterator first, InputIterator last,
const Compare &comp = Compare(),
const Allocator &alloc = Allocator())
: internal(first, last, comp, alloc) {}
ThreadSafeMap(const ThreadSafeMap<Key, T, Compare, Allocator> &x)
: internal(x.internal) {}
ThreadSafeMap(std::initializer_list<std::pair<const Key, T>> ilist,
const Compare &comp = Compare(),
const Allocator &alloc = Allocator())
: internal(ilist, comp, alloc) {}
ThreadSafeMap<Key, Compare, Allocator> &
operator=(const ThreadSafeMap<Key, Compare, Allocator> &x) {
std::scoped_lock<std::mutex> lock(mutex);
std::scoped_lock<std::mutex> lock2(x.mutex);
internal = x.internal;
return *this;
}
iterator begin(void) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.begin();
}
const_iterator begin(void) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.begin();
}
iterator end(void) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.end();
}
const_iterator end(void) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.end();
}
reverse_iterator rbegin(void) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.rbegin();
}
const_reverse_iterator rbegin(void) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.rbegin();
}
reverse_iterator rend(void) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.rend();
}
const_reverse_iterator rend(void) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.rend();
}
T &operator[](const Key &x) {
std::scoped_lock<std::mutex> lock(mutex);
return internal[x];
}
std::pair<iterator, bool> insert(const value_type &x) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.insert(x);
}
template <class... _Args>
std::pair<iterator, bool> emplace(_Args &&...args) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.emplace(std::forward<_Args>(args)...);
}
iterator insert(iterator position, const value_type &x) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.insert(position, x);
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last) {
std::scoped_lock<std::mutex> lock(mutex);
internal.insert(first, last);
}
void erase(iterator pos) {
std::scoped_lock<std::mutex> lock(mutex);
internal.erase(pos);
}
size_type erase(const Key &x) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.erase(x);
}
void erase(iterator begin, iterator end) {
std::scoped_lock<std::mutex> lock(mutex);
internal.erase(begin, end);
}
void swap(ThreadSafeMap<Key, T, Compare, Allocator> &x) {
std::scoped_lock<std::mutex> lock(mutex);
std::scoped_lock<std::mutex> lock2(x.mutex);
internal.swap(x.internal);
}
void clear(void) {
std::scoped_lock<std::mutex> lock(mutex);
internal.clear();
}
// Observers
key_compare key_comp(void) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.key_comp();
}
value_compare value_comp(void) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.value_comp();
}
// Operations
const_iterator find(const Key &x) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.find(x);
}
iterator find(const Key &x) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.find(x);
}
size_type count(const Key &x) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.count(x);
}
bool contains(const Key &x) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.contains(x);
}
const_iterator lower_bound(const Key &x) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.lower_bound(x);
}
iterator lower_bound(const Key &x) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.lower_bound(x);
}
const_iterator upper_bound(const Key &x) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.upper_bound(x);
}
iterator upper_bound(const Key &x) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.upper_bound(x);
}
std::pair<const_iterator, const_iterator> equal_range(const Key &x) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.equal_range(x);
}
std::pair<iterator, iterator> equal_range(const Key &x) {
std::scoped_lock<std::mutex> lock(mutex);
return internal.equal_range(x);
}
size_type size(void) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.size();
}
size_type max_size(void) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.max_size();
}
bool empty(void) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.empty();
}
allocator_type get_allocator(void) const {
std::scoped_lock<std::mutex> lock(mutex);
return internal.get_allocator();
}
~ThreadSafeMap(void) {}
std::map<Key, T, Compare, Allocator> get() {
std::scoped_lock<std::mutex> lock(mutex);
return internal;
}
private:
std::map<Key, T, Compare, Allocator> internal;
mutable std::mutex mutex;
};
} // namespace Your_namespace
#endif /* ThreadSafeMap_h */