You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
387 lines
11 KiB
387 lines
11 KiB
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Digital Voice Modem - Common Library
|
|
* GPLv2 Open Source. Use is subject to license terms.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright (C) 2025 Bryan Biedenkapp, N2PLL
|
|
*
|
|
*/
|
|
/**
|
|
* @file unordered_map.h
|
|
* @ingroup concurrency
|
|
*/
|
|
#if !defined(__CONCURRENCY_UNORDERED_MAP_H__)
|
|
#define __CONCURRENCY_UNORDERED_MAP_H__
|
|
|
|
#include "common/concurrent/concurrent_lock.h"
|
|
#include "common/Thread.h"
|
|
|
|
#include <unordered_map>
|
|
#include <mutex>
|
|
|
|
namespace concurrent
|
|
{
|
|
// ---------------------------------------------------------------------------
|
|
// Class Declaration
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief Thread-safe std::unordered_map.
|
|
* @ingroup concurrency
|
|
*/
|
|
template <typename Key, typename T>
|
|
class unordered_map : public concurrent_lock
|
|
{
|
|
using __std = std::unordered_map<Key, T>;
|
|
public:
|
|
using iterator = typename __std::iterator;
|
|
using const_iterator = typename __std::const_iterator;
|
|
|
|
/**
|
|
* @brief Initializes a new instance of the unordered_map class.
|
|
*/
|
|
unordered_map() : concurrent_lock(),
|
|
m_map()
|
|
{
|
|
/* stub */
|
|
}
|
|
/**
|
|
* @brief Initializes a new instance of the unordered_map class.
|
|
* @param size Initial size of the unordered_map.
|
|
*/
|
|
unordered_map(size_t size) : concurrent_lock(),
|
|
m_map(size)
|
|
{
|
|
/* stub */
|
|
}
|
|
/**
|
|
* @brief Finalizes a instance of the unordered_map class.
|
|
*/
|
|
virtual ~unordered_map()
|
|
{
|
|
m_map.clear();
|
|
}
|
|
|
|
/**
|
|
* @brief Unordered map assignment operator.
|
|
* @param other A map of identical element and allocator types.
|
|
*/
|
|
unordered_map& operator=(const unordered_map& other)
|
|
{
|
|
__lock();
|
|
m_map = other.m_map;
|
|
__unlock();
|
|
return *this;
|
|
}
|
|
/**
|
|
* @brief Unordered map assignment operator.
|
|
* @param other A map of identical element and allocator types.
|
|
*/
|
|
unordered_map& operator=(const std::unordered_map<Key, T>& other)
|
|
{
|
|
__lock();
|
|
m_map = other;
|
|
__unlock();
|
|
return *this;
|
|
}
|
|
/**
|
|
* @brief Unordered map assignment operator.
|
|
* @param other A map of identical element and allocator types.
|
|
*/
|
|
unordered_map& operator=(unordered_map& other)
|
|
{
|
|
__lock();
|
|
m_map = other.m_map;
|
|
__unlock();
|
|
return *this;
|
|
}
|
|
/**
|
|
* @brief Unordered map assignment operator.
|
|
* @param other A map of identical element and allocator types.
|
|
*/
|
|
unordered_map& operator=(std::unordered_map<Key, T>& other)
|
|
{
|
|
__lock();
|
|
m_map = other;
|
|
__unlock();
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief Assigns a given value to a unordered_map.
|
|
* @param size Number of elements to be assigned.
|
|
* @param value Value to be assigned.
|
|
*/
|
|
void assign(size_t size, const T& value)
|
|
{
|
|
__lock();
|
|
m_map.assign(size, value);
|
|
__unlock();
|
|
}
|
|
|
|
/**
|
|
* @brief Returns a read/write iterator that points to the first
|
|
* element in the unordered_map. Iteration is done in ordinary
|
|
* element order.
|
|
* @returns iterator
|
|
*/
|
|
iterator begin()
|
|
{
|
|
__spinlock();
|
|
return m_map.begin();
|
|
}
|
|
/**
|
|
* @brief Returns a read-only (constant) iterator that points to the
|
|
* first element in the unordered_map. Iteration is done in ordinary
|
|
* element order.
|
|
* @returns const_iterator
|
|
*/
|
|
const_iterator begin() const
|
|
{
|
|
__spinlock();
|
|
return m_map.begin();
|
|
}
|
|
/**
|
|
* @brief Returns a read/write iterator that points one past the last
|
|
* element in the unordered_map. Iteration is done in ordinary
|
|
* element order.
|
|
* @returns iterator
|
|
*/
|
|
iterator end()
|
|
{
|
|
__spinlock();
|
|
return m_map.end();
|
|
}
|
|
/**
|
|
* @brief Returns a read-only (constant) iterator that points one past
|
|
* the last element in the unordered_map. Iteration is done in ordinary
|
|
* element order.
|
|
* @returns const_iterator
|
|
*/
|
|
const_iterator end() const
|
|
{
|
|
__spinlock();
|
|
return m_map.end();
|
|
}
|
|
|
|
/**
|
|
* @brief Returns a read-only (constant) iterator that points to the
|
|
* first element in the unordered_map. Iteration is done in ordinary
|
|
* element order.
|
|
* @returns const_iterator
|
|
*/
|
|
const_iterator cbegin() const
|
|
{
|
|
__spinlock();
|
|
return m_map.cbegin();
|
|
}
|
|
/**
|
|
* @brief Returns a read-only (constant) iterator that points one past
|
|
* the last element in the unordered_map. Iteration is done in ordinary
|
|
* element order.
|
|
* @returns const_iterator
|
|
*/
|
|
const_iterator cend() const
|
|
{
|
|
__spinlock();
|
|
return m_map.cend();
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the element at the specified key.
|
|
* @param key Key of the element to get.
|
|
* @returns T& Element at the specified key.
|
|
*/
|
|
T& operator[](const Key& key)
|
|
{
|
|
__spinlock();
|
|
return m_map[key];
|
|
}
|
|
/**
|
|
* @brief Gets the element at the specified key.
|
|
* @param key Key of the element to get.
|
|
* @returns const T& Element at the specified key.
|
|
*/
|
|
const T& operator[](const Key& key) const
|
|
{
|
|
__spinlock();
|
|
return m_map[key];
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the element at the specified key.
|
|
* @param key Key of the element to get.
|
|
* @returns T& Element at the specified key.
|
|
*/
|
|
T& at(const Key& key)
|
|
{
|
|
__spinlock();
|
|
return m_map.at(key);
|
|
}
|
|
/**
|
|
* @brief Gets the element at the specified key.
|
|
* @param key Key of the element to get.
|
|
* @returns const T& Element at the specified key.
|
|
*/
|
|
const T& at(const Key& key) const
|
|
{
|
|
__spinlock();
|
|
return m_map.at(key);
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the total number of elements in the unordered_map.
|
|
* @returns size_t Total number of elements in the unordered_map.
|
|
*/
|
|
size_t size() const
|
|
{
|
|
__spinlock();
|
|
return m_map.size();
|
|
}
|
|
|
|
/**
|
|
* @brief Checks if the unordered_map is empty.
|
|
* @returns bool True if the unordered_map is empty, false otherwise.
|
|
*/
|
|
bool empty() const
|
|
{
|
|
__spinlock();
|
|
return m_map.empty();
|
|
}
|
|
|
|
/**
|
|
* @brief Checks if the unordered_map contains the specified key.
|
|
* @param key Key to check.
|
|
* @returns bool True if the unordered_map contains the specified key, false otherwise.
|
|
*/
|
|
bool contains(const Key& key) const
|
|
{
|
|
__spinlock();
|
|
return m_map.contains(key);
|
|
}
|
|
|
|
/**
|
|
* @brief Inserts a new element into the unordered_map.
|
|
* @param key Key of the element to insert.
|
|
* @param value Value of the element to insert.
|
|
*/
|
|
void insert(const Key& key, const T& value)
|
|
{
|
|
__lock();
|
|
m_map.insert({key, value});
|
|
__unlock();
|
|
}
|
|
|
|
/**
|
|
* @brief Removes the element at the specified key.
|
|
* @param key Key of the element to remove.
|
|
*/
|
|
void erase(const Key& key)
|
|
{
|
|
__lock();
|
|
m_map.erase(key);
|
|
__unlock();
|
|
}
|
|
/**
|
|
* @brief Removes the element at the specified iterator.
|
|
* @param position Iterator of the element to remove.
|
|
*/
|
|
void erase(const_iterator position)
|
|
{
|
|
__lock();
|
|
m_map.erase(position);
|
|
__unlock();
|
|
}
|
|
/**
|
|
* @brief Removes the elements in the specified range.
|
|
* @param first Iterator of the first element to remove.
|
|
* @param last Iterator of the last element to remove.
|
|
*/
|
|
void erase(const_iterator first, const_iterator last)
|
|
{
|
|
__lock();
|
|
m_map.erase(first, last);
|
|
__unlock();
|
|
}
|
|
|
|
/**
|
|
* @brief Clears the unordered_map.
|
|
*/
|
|
void clear()
|
|
{
|
|
__lock();
|
|
m_map.clear();
|
|
__unlock();
|
|
}
|
|
|
|
/**
|
|
* @brief Tries to locate an element in an unordered_map.
|
|
* @param key Key to be located.
|
|
* @return iterator Iterator pointing to sought-after element, or end() if not
|
|
* found.
|
|
*/
|
|
iterator find(const Key& key)
|
|
{
|
|
__spinlock();
|
|
return m_map.find(key);
|
|
}
|
|
/**
|
|
* @brief Tries to locate an element in an unordered_map.
|
|
* @param key Key to be located.
|
|
* @return const_iterator Iterator pointing to sought-after element, or end() if not
|
|
* found.
|
|
*/
|
|
const_iterator find(const Key& key) const
|
|
{
|
|
__spinlock();
|
|
return m_map.find(key);
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the number of elements.
|
|
* @param key Key to count.
|
|
* @return size_t Number of elements with specified key.
|
|
*/
|
|
size_t count(const Key& key) const
|
|
{
|
|
__spinlock();
|
|
return m_map.count(key);
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the underlying unordered_map.
|
|
* @returns std::unordered_map<Key, T>& Underlying unordered_map.
|
|
*/
|
|
std::unordered_map<Key, T>& get()
|
|
{
|
|
__spinlock();
|
|
return m_map;
|
|
}
|
|
/**
|
|
* @brief Gets the underlying unordered_map.
|
|
* @returns const std::unordered_map<Key, T>& Underlying unordered_map.
|
|
*/
|
|
const std::unordered_map<Key, T>& get() const
|
|
{
|
|
__spinlock();
|
|
return m_map;
|
|
}
|
|
|
|
/**
|
|
* @brief Prepare the underlying unordered_map for a specified number of
|
|
* elements.
|
|
* @param n Number of elements required.
|
|
*/
|
|
void reserve(size_t n)
|
|
{
|
|
m_map.reserve(n);
|
|
}
|
|
|
|
private:
|
|
std::unordered_map<Key, T> m_map;
|
|
};
|
|
} // namespace concurrent
|
|
|
|
#endif // __CONCURRENCY_UNORDERED_MAP_H__
|