Service_NSSM/CC_SDK/Include/basic/ConcurrentLinkedList.h
2025-09-27 14:24:18 +08:00

213 lines
6.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef CONCURRENTLINKEDLIST_H
#define CONCURRENTLINKEDLIST_H
#include <atomic>
#include <memory> // for std::allocator
#include <stdexcept> // for std::out_of_range
/**
* 命名空间 CTL用于并发线程安全链表
*/
namespace CTL {
/**
* 模板类 ConcurrentLinkedList 实现了一个线程安全的单向链表。
*
* @tparam T 链表中存储的数据类型
* @tparam Alloc 分配器类型,默认为 std::allocator<T>
*/
template<typename T, class Alloc = std::allocator<T>>
class ConcurrentLinkedList {
/**
* 链表节点结构体
*/
public:
struct Node {
T data; // 节点中存储的数据
std::atomic<Node*> next; // 指向下一个节点的原子指针
explicit Node(const T& value) : data(value), next(nullptr) {} // 构造函数
};
typedef typename std::allocator_traits<Alloc>::template rebind_alloc<Node> Node_alloc_type;
Node_alloc_type allocator_; // 节点分配器
std::atomic<Node*> head; // 指向链表头节点的原子指针
public:
/**
* 构造函数,初始化空链表
*/
ConcurrentLinkedList() : head(nullptr) {}
ConcurrentLinkedList(const ConcurrentLinkedList& other) {
typename ConcurrentLinkedList<T, Alloc>::Node* current = other.head.load();
while (current) {
add(current->data);
current = current->next.load();
}
}
ConcurrentLinkedList(const std::list<T> &list) {
for (const auto &item : list) {
add(item);
}
}
/**
* 析构函数,释放链表中的所有节点
*/
~ConcurrentLinkedList() {
Node* current = head.load();
while (current != nullptr) {
Node* next = current->next.load();
std::allocator_traits<Node_alloc_type>::destroy(allocator_, current);
allocator_.deallocate(current, 1);
current = next;
}
}
/**
* 在链表头部插入一个元素
*
* @param value 要插入的元素值
*/
void push_front(const T& value) {
Node* new_node = allocator_.allocate(1);
std::allocator_traits<Node_alloc_type>::construct(allocator_, new_node, value);
new_node->next.store(head.load());
while (!head.compare_exchange_weak(new_node->next.load(), new_node)) {
new_node->next.store(head.load());
}
}
/**
* 移除并返回链表头部的元素
*
* @param result 存储移除的元素值
* @return 如果操作成功返回 true否则返回 false
*/
bool pop_front(T& result) {
Node* old_head = head.load();
while (old_head != nullptr && !head.compare_exchange_weak(old_head, old_head->next.load())) {
// 重试
}
if (old_head == nullptr) {
return false;
}
result = old_head->data;
std::allocator_traits<Node_alloc_type>::destroy(allocator_, old_head);
allocator_.deallocate(old_head, 1);
return true;
}
/**
* 在链表尾部添加一个元素
*
* @param value 要添加的元素值
*/
void add(const T& value) {
Node* new_node = allocator_.allocate(1);
std::allocator_traits<Node_alloc_type>::construct(allocator_, new_node, value);
new_node->next.store(nullptr);
Node* current = head.load();
if (!current) {
head.store(new_node);
return;
}
while (true) {
Node* next = current->next.load();
if (!next) {
if (current->next.compare_exchange_weak(next, new_node)) {
return;
}
}
else {
current = next;
}
}
}
/**
* 移除链表中第一个匹配指定值的元素
*
* @param value 要移除的元素值
* @return 如果操作成功返回 true否则返回 false
*/
bool remove(const T& value) {
Node* current = head.load();
Node* prev = nullptr;
while (current) {
Node* next = current->next.load();
if (current->data == value) {
if (prev) {
prev->next.store(next);
}
else {
head.store(next);
}
std::allocator_traits<Node_alloc_type>::destroy(allocator_, current);
allocator_.deallocate(current, 1);
return true;
}
prev = current;
current = next;
}
return false;
}
/**
* 返回链表中元素的数量
*
* @return 链表中元素的数量
*/
size_t size() const {
size_t count = 0;
Node* current = head.load();
while (current) {
count++;
current = current->next.load();
}
return count;
}
/**
* 返回链表中指定索引处的元素值
*
* @param index 元素的索引位置
* @return 索引处的元素值
* @note 如果索引超出范围,行为未定义
*/
T get(size_t index) const {
Node* current = head.load();
size_t count = 0;
while (current) {
if (count == index) {
return current->data;
}
count++;
current = current->next.load();
}
// throw std::out_of_range("Index out of range");
return T();
}
/**
* 检查链表是否为空
*
* @return 如果链表为空返回 true否则返回 false
*/
bool isEmpty() const {
return head.load() == nullptr;
}
friend std::ostream &operator<<(std::ostream &os, const ConcurrentLinkedList<T, Alloc> &list) {
typename ConcurrentLinkedList<T, Alloc>::Node* current = list.head.load();
os<< "[";
while (current) {
os << current->data << ", ";
current = current->next.load();
}
os << "]";
return os;
}
};
} // namespace CTL
#endif // CONCURRENTLINKEDLIST_H