// 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 #include namespace concurrent { // --------------------------------------------------------------------------- // Class Declaration // --------------------------------------------------------------------------- /** * @brief Thread-safe std::unordered_map. * @ingroup concurrency */ template class unordered_map : public concurrent_lock { using __std = std::unordered_map; 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& 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& 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& Underlying unordered_map. */ std::unordered_map& get() { __spinlock(); return m_map; } /** * @brief Gets the underlying unordered_map. * @returns const std::unordered_map& Underlying unordered_map. */ const std::unordered_map& 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 m_map; }; } // namespace concurrent #endif // __CONCURRENCY_UNORDERED_MAP_H__