c语言利用gcc cas原子操作实现双向循环链表,支持引用计数
时间: 2024-01-28 08:03:09 浏览: 175
C语言实现通用双向链表标准版.rar
下面是一个基于 GCC 内建原子操作实现的双向循环链表,支持引用计数的C语言代码示例:
```c
#include <stdint.h>
#include <stdbool.h>
#include <stdatomic.h>
typedef struct node {
int val;
int refcnt;
struct node* prev;
struct node* next;
} node_t;
typedef struct list {
node_t* tail;
} list_t;
void init_list(list_t* list) {
node_t* head = (node_t*)malloc(sizeof(node_t));
head->val = 0;
head->refcnt = 1;
head->prev = head->next = head;
list->tail = head;
}
void destroy_list(list_t* list) {
node_t* head = list->tail->next;
while (head != list->tail) {
node_t* next = head->next;
if (--(head->refcnt) == 0) {
free(head);
}
head = next;
}
if (--(list->tail->refcnt) == 0) {
free(list->tail);
}
}
bool insert_node(list_t* list, int val) {
node_t* node = (node_t*)malloc(sizeof(node_t));
node->val = val;
node->refcnt = 1;
while (true) {
node_t* tail = list->tail;
node_t* prev = tail;
node_t* next = prev->next;
while (next != tail && next->val < val) {
prev = next;
next = prev->next;
}
node->prev = prev;
node->next = next;
if (prev->next == next) {
if (atomic_compare_exchange_strong(&prev->next, &next, node)) {
next->prev = node;
atomic_fetch_add(&node->prev->refcnt, 1);
atomic_fetch_add(&node->next->refcnt, 1);
return true;
}
}
}
}
bool remove_node(list_t* list, int val) {
while (true) {
node_t* tail = list->tail;
node_t* prev = tail;
node_t* curr = prev->next;
while (curr != tail && curr->val < val) {
prev = curr;
curr = prev->next;
}
if (curr == tail || curr->val > val) {
return false;
}
if (atomic_compare_exchange_strong(&prev->next, &curr, curr->next)) {
curr->next->prev = prev;
atomic_fetch_sub(&curr->prev->refcnt, 1);
atomic_fetch_sub(&curr->next->refcnt, 1);
if (--(curr->refcnt) == 0) {
free(curr);
}
return true;
}
}
}
```
上述代码中,我们使用了 `atomic_compare_exchange_strong()` 函数来实现 CAS 操作,避免了多线程竞争的问题。引用计数机制能够有效地防止在删除节点时出现数据竞争问题。当节点的引用计数为 0 时,我们才能够安全地释放该节点的内存空间。需要注意的是,在使用 GCC 内建原子操作时,需要对指针进行类型转换,以匹配原子操作函数的参数类型。
阅读全文