slist.h
#ifndef SLIST_H
#define SLIST_H
#include <pthread.h>
#include <stdbool.h>
// 单链表节点结构
typedef struct SListNode
{
void *pdata; // 存储数据的指针
struct SListNode *next; // 指向下一个节点的指针
} SListNode;
// 单链表结构
typedef struct SList
{
SListNode *head; // 链表的头指针
pthread_mutex_t lock; // 互斥锁
} SList;
// 比较函数指针类型,返回值为0表示相等
typedef int (*CompareCallback)(void *pdata1, void *pdata2);
// 释放函数指针类型
typedef void (*FreeCallback)(void *pdata);
// 遍历函数指针类型
typedef void (*TraverseCallback)(const void *pdata, void *arg);
/**
* 初始化链表。
*
* @param list 需要初始化的链表指针。
* @return 初始化是否成功(0 表示成功,-1 表示失败)。
*/
int slist_init(SList *list);
/**
* 销毁链表,释放所有资源。
*
* @param list 需要销毁的链表指针。
* @param free_cb 自定义的释放函数,如果为 NULL,使用 free。
*/
void slist_destroy(SList *list, FreeCallback free_cb);
/**
* 添加数据
*
* @param list 链表指针。
* @param pdata 要添加的数据指针。
* @param size 数据的大小。
* @return 操作是否成功(0 表示成功,-1 表示失败)。
*/
int slist_insert(SList *list, void *pdata, size_t size);
/**
* 删除数据
*
* @param list 链表指针。
* @param pdata 要删除的节点数据指针。
* @param compare_cb 自定义的比较函数。
* @param free_cb 自定义的释放函数,如果为 NULL,使用 free。
* @return 操作是否成功(0 表示成功,-1 表示失败)。
*/
int slist_remove(SList *list, void *pdata, CompareCallback compare_cb, FreeCallback free_cb);
/**
* 查找数据
*
* @param list 链表指针。
* @param pdata 要查找的数据指针。
* @param compare_cb 自定义的比较函数。
* @return 如果找到,返回对应的节点数据;否则返回 NULL。
*/
const void *slist_find(SList *list, void *pdata, CompareCallback compare_cb);
/**
* 修改数据
*
* @param list 链表指针。
* @param old_data 需要修改的节点数据指针。
* @param new_data 替换为的新数据指针。
* @param size 数据的大小。
* @param compare_cb 自定义的比较函数。
* @return 操作是否成功(0 表示成功,-1 表示失败)。
*/
int slist_modify(SList *list, void *old_data, void *new_data, size_t size,
CompareCallback compare_cb);
/**
* 遍历链表
*
* @param list 链表指针。
* @param traverse_cb 自定义的遍历函数。
* @param arg 回调携带的参数。
* @return 操作是否成功(0 表示成功,-1 表示失败)。
*/
int slist_foreach(SList *list, TraverseCallback traverse_cb, void *arg);
/**
* 遍历链表
*
* @param list 链表指针。
* @param pdata 遍历到的节点数据指针,函数内部会分配内存,需要调用者释放。
* @param count 遍历到的节点数量。
* @return 操作是否成功(0 表示成功,-1 表示失败)。
*/
int slist_foreach2(SList *list, void ***pdata, size_t *count);
/**
* 释放遍历链表时分配的内存。
*
* @param pdata 遍历到的节点数据指针。
* @return 无。
*/
void slist_free_foreach2(void ***pdata);
/**
* 获取链表中元素数量
*
* @param list 链表指针。
* @return 链表中元素的数量。
*/
size_t slist_size(SList *list);
/**
* 链表是否为空。
*
* @param list 链表指针。
* @return 如果链表为空,返回 true;否则返回 false。
*/
bool slist_empty(SList *list);
/**
* 清空链表,释放所有节点。
*
* @param list 链表指针。
* @param free_cb 自定义的释放函数,如果为 NULL,使用 free。
* @return 无。
*/
void slist_clear(SList *list, FreeCallback free_cb);
#endif // SLIST_H
slist.c
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "slist.h"
int slist_init(SList *list)
{
list->head = NULL;
if (pthread_mutex_init(&list->lock, NULL) != 0)
{
return -1; // 初始化互斥锁失败
}
return 0;
}
void slist_destroy(SList *list, FreeCallback free_cb)
{
pthread_mutex_lock(&list->lock);
SListNode *current = list->head;
while (current)
{
SListNode *next = current->next;
// 释放节点数据,如果没提供自定义释放函数,使用free
(free_cb) ? free_cb(current->pdata) : free(current->pdata);
free(current);
current = next;
}
list->head = NULL;
pthread_mutex_unlock(&list->lock);
pthread_mutex_destroy(&list->lock);
}
int slist_insert(SList *list, void *pdata, size_t size)
{
SListNode *new_node = (SListNode *)malloc(sizeof(SListNode));
uint8_t *data = (uint8_t *)malloc(size);
if (!new_node || !data)
{
free(new_node);
free(data);
return -1; // 分配内存失败
}
memcpy(data, pdata, size);
new_node->pdata = data;
pthread_mutex_lock(&list->lock);
// 头插法
new_node->next = list->head;
list->head = new_node;
pthread_mutex_unlock(&list->lock);
return 0;
}
int slist_remove(SList *list, void *pdata, CompareCallback compare_cb, FreeCallback free_cb)
{
if (!compare_cb)
{
return -1;
}
pthread_mutex_lock(&list->lock);
SListNode *current = list->head;
SListNode *previous = NULL;
while (current)
{
if (compare_cb(current->pdata, pdata) == 0)
{
if (previous)
{
previous->next = current->next;
}
else
{
list->head = current->next;
}
(free_cb) ? free_cb(current->pdata) : free(current->pdata);
free(current);
pthread_mutex_unlock(&list->lock);
return 0;
}
previous = current;
current = current->next;
}
pthread_mutex_unlock(&list->lock);
return -1; // 未找到数据
}
const void *slist_find(SList *list, void *pdata, CompareCallback compare_cb)
{
if (!compare_cb)
{
return NULL;
}
pthread_mutex_lock(&list->lock);
SListNode *current = list->head;
while (current)
{
if (compare_cb(current->pdata, pdata) == 0)
{
pthread_mutex_unlock(&list->lock);
return current->pdata;
}
current = current->next;
}
pthread_mutex_unlock(&list->lock);
return NULL; // 未找到数据
}
int slist_modify(SList *list, void *old_data, void *new_data, size_t size,
CompareCallback compare_cb)
{
if (!compare_cb)
{
return -1;
}
pthread_mutex_lock(&list->lock);
SListNode *current = list->head;
while (current)
{
if (compare_cb(current->pdata, old_data) == 0)
{
memcpy(current->pdata, new_data, size);
pthread_mutex_unlock(&list->lock);
return 0;
}
current = current->next;
}
pthread_mutex_unlock(&list->lock);
return -1; // 未找到数据
}
int slist_foreach(SList *list, TraverseCallback traverse_cb, void *arg)
{
if (!traverse_cb)
{
return -1;
}
pthread_mutex_lock(&list->lock);
SListNode *current = list->head;
while (current)
{
traverse_cb(current->pdata, arg);
current = current->next;
}
pthread_mutex_unlock(&list->lock);
return 0;
}
int slist_foreach2(SList *list, void ***pdata, size_t *count)
{
pthread_mutex_lock(&list->lock);
size_t size = 0;
SListNode *current = list->head;
while (current)
{
size++;
current = current->next;
}
*pdata = (void *)malloc(sizeof(void *) * size);
if (!*pdata)
{
pthread_mutex_unlock(&list->lock);
return -1; // 分配内存失败
}
current = list->head;
for (size_t i = 0; i < size; i++)
{
(*pdata)[i] = current->pdata;
current = current->next;
}
*count = size;
pthread_mutex_unlock(&list->lock);
return 0;
}
void slist_free_foreach2(void ***pdata)
{
free(*pdata);
*pdata = NULL;
}
size_t slist_size(SList *list)
{
size_t size = 0;
pthread_mutex_lock(&list->lock);
SListNode *current = list->head;
while (current)
{
size++;
current = current->next;
}
pthread_mutex_unlock(&list->lock);
return size;
}
bool slist_empty(SList *list)
{
pthread_mutex_lock(&list->lock);
bool is_empty = (list->head == NULL);
pthread_mutex_unlock(&list->lock);
return is_empty;
}
void slist_clear(SList *list, FreeCallback free_cb)
{
pthread_mutex_lock(&list->lock);
SListNode *next = NULL;
SListNode *current = list->head;
while (current)
{
next = current->next;
(free_cb) ? free_cb(current->pdata) : free(current->pdata);
free(current);
current = next;
}
list->head = NULL;
pthread_mutex_unlock(&list->lock);
}
测试:
#include <stdio.h>
#include <stdlib.h>
#include "slist.h"
int CompareFun(void *pdata1, void *pdata2)
{
return *(int *)pdata1 - *(int *)pdata2;
}
void TraverseFun(const void *pdata, void *)
{
printf("%d\n", *(int *)pdata);
}
int main(void)
{
SList list;
int buf[10] = {0};
for (int i = 0; i < 10; i++)
{
buf[i] = i;
}
slist_init(&list);
for (int i = 0; i < 10; i++)
slist_insert(&list, &buf[i], sizeof(int));
printf("size = %zu\n", slist_size(&list));
if (slist_empty(&list))
printf("empty\n");
else
printf("not empty\n");
// 遍历
printf("--------\n");
slist_foreach(&list, TraverseFun, NULL);
printf("--------\n");
size_t count = 0;
void **pdata2 = NULL;
slist_foreach2(&list, &pdata2, &count);
printf("\ncount = %zu\n", count);
printf("--------\n");
for (size_t i = 0; i < count; i++)
{
printf("%d\n", *((int *)pdata2[i]));
}
printf("--------\n");
slist_free_foreach2(&pdata2);
const int *p = slist_find(&list, &buf[3], CompareFun);
if (p)
printf("found: %d\n", *p);
else
printf("Not found\n");
printf("remove\n");
slist_remove(&list, &buf[3], CompareFun, NULL);
p = slist_find(&list, &buf[3], CompareFun);
if (p)
printf("found: %d\n", *p);
else
printf("Not found\n");
int *pValue = (int *)malloc(sizeof(int));
*pValue = 666;
slist_modify(&list, &buf[0], pValue, sizeof(int), CompareFun);
p = slist_find(&list, pValue, CompareFun);
if (p)
printf("found: %d\n", *p);
else
printf("Not found\n");
printf("clear\n");
slist_clear(&list, NULL);
printf("size = %zu\n", slist_size(&list));
if (slist_empty(&list))
printf("empty\n");
else
printf("not empty\n");
slist_destroy(&list, NULL);
return 0;
}
测试输出:
size = 10
not empty
--------
9
8
7
6
5
4
3
2
1
0
--------
count = 10
--------
9
8
7
6
5
4
3
2
1
0
--------
found: 3
remove
Not found
found: 666
clear
size = 0
empty