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.
dvmhost/src/common/concurrent/shared_vector.h

439 lines
12 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,2026 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file shared_vector.h
* @ingroup concurrency
*/
#if !defined(__CONCURRENCY_SHARED_VECTOR_H__)
#define __CONCURRENCY_SHARED_VECTOR_H__
#include "common/concurrent/concurrent_shared_lock.h"
#include "common/Thread.h"
#include <vector>
#include <mutex>
namespace concurrent
{
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
/**
* @brief Thread-safe share-locked std::vector. Read operations
* must use shared_lock()/shared_unlock() to ensure thread-safety. (This includes iterators.)
* @ingroup concurrency
*/
template <typename T>
class shared_vector : public concurrent_shared_lock
{
using __std = std::vector<T>;
public:
using iterator = typename __std::iterator;
using const_iterator = typename __std::const_iterator;
/**
* @brief Initializes a new instance of the shared_vector class.
*/
shared_vector() : concurrent_shared_lock(),
m_vector()
{
/* stub */
}
/**
* @brief Initializes a new instance of the shared_vector class.
* @param size Initial size of the vector.
*/
shared_vector(size_t size) : concurrent_shared_lock(),
m_vector(size)
{
/* stub */
}
/**
* @brief Finalizes a instance of the shared_vector class.
*/
virtual ~shared_vector()
{
m_vector.clear();
}
/**
* @brief Vector assignment operator.
* @param other A vector of identical element and allocator types.
*/
shared_vector& operator=(const shared_vector& other)
{
__lock();
m_vector = other.m_vector;
__unlock();
return *this;
}
/**
* @brief Vector assignment operator.
* @param other A vector of identical element and allocator types.
*/
shared_vector& operator=(const std::vector<T>& other)
{
__lock();
m_vector = other;
__unlock();
return *this;
}
/**
* @brief Vector assignment operator.
* @param other A vector of identical element and allocator types.
*/
shared_vector& operator=(shared_vector& other)
{
__lock();
m_vector = other.m_vector;
__unlock();
return *this;
}
/**
* @brief Vector assignment operator.
* @param other A vector of identical element and allocator types.
*/
shared_vector& operator=(std::vector<T>& other)
{
__lock();
m_vector = other;
__unlock();
return *this;
}
/**
* @brief Assigns a given value to a %vector.
* @param size Number of elements to be assigned.
* @param value Value to be assigned.
*/
void assign(size_t size, const T& value)
{
__lock();
m_vector.assign(size, value);
__unlock();
}
/**
* @brief Returns a read/write iterator that points to the first
* element in the vector. Iteration is done in ordinary
* element order.
* @returns iterator
*/
iterator begin()
{
return m_vector.begin();
}
/**
* @brief Returns a read-only (constant) iterator that points to the
* first element in the vector. Iteration is done in ordinary
* element order.
* @returns const_iterator
*/
const_iterator begin() const
{
return m_vector.begin();
}
/**
* @brief Returns a read/write iterator that points one past the last
* element in the vector. Iteration is done in ordinary
* element order.
* @returns iterator
*/
iterator end()
{
return m_vector.end();
}
/**
* @brief Returns a read-only (constant) iterator that points one past
* the last element in the vector. Iteration is done in ordinary
* element order.
* @returns const_iterator
*/
const_iterator end() const
{
return m_vector.end();
}
/**
* @brief Returns a read-only (constant) iterator that points to the
* first element in the vector. Iteration is done in ordinary
* element order.
* @returns const_iterator
*/
const_iterator cbegin() const
{
return m_vector.cbegin();
}
/**
* @brief Returns a read-only (constant) iterator that points one past
* the last element in the vector. Iteration is done in ordinary
* element order.
* @returns const_iterator
*/
const_iterator cend() const
{
return m_vector.cend();
}
/**
* @brief Gets the number of elements in the vector.
* @returns size_t Number of elements in the vector.
*/
size_t size() const
{
return m_vector.size();
}
/**
* @brief Resizes the %vector to the specified number of elements.
* @param size Number of elements the %vector should contain.
*/
void resize(size_t size)
{
__lock();
m_vector.resize(size);
__unlock();
}
/**
* @brief Returns the total number of elements that the %vector can
* hold before needing to allocate more memory.
* @returns size_t
*/
size_t capacity() const
{
return m_vector.capacity();
}
/**
* @brief Checks if the vector is empty.
* @returns bool True if the vector is empty, false otherwise.
*/
bool empty() const
{
return m_vector.empty();
}
/**
* @brief Gets the element at the specified index.
* @param index Index of the element to get.
* @returns T& Element at the specified index.
*/
T& operator[](size_t index)
{
return m_vector[index];
}
/**
* @brief Gets the element at the specified index.
* @param index Index of the element to get.
* @returns const T& Element at the specified index.
*/
const T& operator[](size_t index) const
{
return m_vector[index];
}
/**
* @brief Gets the element at the specified index.
* @param index Index of the element to get.
* @returns T& Element at the specified index.
*/
T& at(size_t index)
{
return m_vector.at(index);
}
/**
* @brief Gets the element at the specified index.
* @param index Index of the element to get.
* @returns const T& Element at the specified index.
*/
const T& at(size_t index) const
{
return m_vector.at(index);
}
/**
* @brief Gets the first element of the vector.
* @returns T& First element of the vector.
*/
T& front()
{
__shared_lock();
T& value = m_vector.front();
__shared_unlock();
return value;
}
/**
* @brief Gets the first element of the vector.
* @returns const T& First element of the vector.
*/
const T& front() const
{
__shared_lock();
const T& value = m_vector.front();
__shared_unlock();
return value;
}
/**
* @brief Gets the last element of the vector.
* @returns T& Last element of the vector.
*/
T& back()
{
__shared_lock();
T& value = m_vector.back();
__shared_unlock();
return value;
}
/**
* @brief Gets the last element of the vector.
* @returns const T& Last element of the vector.
*/
const T& back() const
{
__shared_lock();
const T& value = m_vector.back();
__shared_unlock();
return value;
}
/**
* @brief Adds an element to the end of the vector.
* @param value Value to add.
*/
void push_back(const T& value)
{
__lock();
m_vector.push_back(value);
__unlock();
}
/**
* @brief Adds an element to the end of the vector.
* @param value Value to add.
*/
void push_back(T&& value)
{
__lock();
m_vector.push_back(std::move(value));
__unlock();
}
/**
* @brief Removes last element.
*/
void pop_back()
{
__lock();
m_vector.pop_back();
__unlock();
}
/**
* @brief Inserts given value into vector before specified iterator.
* @param position A const_iterator into the vector.
* @param value Data to be inserted.
* @return iterator An iterator that points to the inserted data.
*/
iterator insert(iterator position, const T& value)
{
__lock();
auto it = m_vector.insert(position, value);
__unlock();
return it;
}
/**
* @brief Removes the element at the specified index.
* @param index Index of the element to remove.
*/
void erase(size_t index)
{
__lock();
m_vector.erase(m_vector.begin() + index);
__unlock();
}
/**
* @brief Removes the element at the specified iterator.
* @param position Iterator of the element to remove.
*/
void erase(const_iterator position)
{
__lock();
m_vector.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_vector.erase(first, last);
__unlock();
}
/**
* @brief Swaps data with another vector.
* @param other A vector of the same element and allocator types.
*/
void swap(shared_vector& other)
{
__lock();
m_vector.swap(other.m_vector);
__unlock();
}
/**
* @brief Clears the vector.
*/
void clear()
{
__lock();
m_vector.clear();
__unlock();
}
/**
* @brief Gets the underlying vector.
* @returns std::vector<T>& Underlying vector.
*/
std::vector<T>& get()
{
return m_vector;
}
/**
* @brief Gets the underlying vector.
* @returns const std::vector<T>& Underlying vector.
*/
const std::vector<T>& get() const
{
return m_vector;
}
/**
* @brief Prepare the underlying vector for a specified number of
* elements.
* @param n Number of elements required.
*/
void reserve(size_t n)
{
m_vector.reserve(n);
}
private:
std::vector<T> m_vector;
};
} // namespace concurrent
#endif // __CONCURRENCY_SHARED_VECTOR_H__

Powered by TurnKey Linux.