Distribution_Service/CC_SDK/Include/basic/ConcurrentLinkedList.h

213 lines
6.7 KiB
C
Raw Normal View History

2025-11-11 17:46:19 +08:00
#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;
}
};
}
#endif