Redis学习——链表源码分析
0. 前言
Redis 中的链表是以通用链表的形式实现的,而对于链表的用途来说,主要的功能就是增删改查,所以对于查找来说,redis其提供了一个match函数指针,用户负责实现其具体的匹配操作,从而实现通用化。
涉及的文件:adlist.h/adlist.c
1. 数据结构
typedef struct listNode {
struct listNode *prev;
struct listNode *next;
void *value; //通用实现,可以存放任意类型的数据
} listNode;
typedef struct listIter {
listNode *next;
int direction; //用于控制链表遍历的方向
} listIter;
typedef struct list {
listNode *head; //表头
listNode *tail; //表尾
void *(*dup)(void *ptr); //用于复制ptr值,实现深度复制
void (*free)(void *ptr); //释放对应类型结构的内存
int (*match)(void *ptr, void *key); //自定义匹配key
unsigned long len; //节点数量
} list;
#define listSetDupMethod(l,m) ((l)->dup = (m))
#define listSetFreeMethod(l,m) ((l)->free = (m))
#define listSetMatchMethod(l,m) ((l)->match = (m))
其中提供了dup,free,match的函数指针,用户可以通过设置该函数指针,来存取特定类型的数据。
2. API实现:
只提取几个主要的API,该文件完整的注释在GitHud上(用户名:jabnih)
a. listRelease
对于释放链表的操作,其中对于每个节点的释放会判断用户是否设置了free函数,若有则执行用户的操作,用以释放特定类型数据。例如:value为指向一个从堆分配的字符数组,在释放该节点的时候,就需要先释放value内存
对于free可以实现为:
void free(void * value)
{
if( value )
free( (char *)value );
}
//释放链表
void listRelease(list *list)
{
unsigned long len;
listNode *current, *next; current = list->head;
len = list->len;
while(len--) {
next = current->next;
//若设置了free函数,则调用该自定义free函数
if (list->free) list->free(current->value); zfree(current);
current = next;
}
zfree(list);
}
b. listDup
当执行复制的时候,对于设置了dup函数可以实现深度复制或自定义复制的功能。
//复制链表,若有链表有dup,则调用该函数进行深度复制,否则直接复制节点的值(浅复制)
list *listDup(list *orig)
{
list *copy;
listIter *iter;
listNode *node; if ((copy = listCreate()) == NULL)
return NULL;
copy->dup = orig->dup;
copy->free = orig->free;
copy->match = orig->match;
iter = listGetIterator(orig, AL_START_HEAD);
while((node = listNext(iter)) != NULL) {
//遍历整个链表
void *value; if (copy->dup) {
//深度复制
value = copy->dup(node->value);
if (value == NULL) {
//复制出错
listRelease(copy);
listReleaseIterator(iter);
return NULL;
}
} else
//浅复制
value = node->value; //将复制后的节点添加的copy链表尾部
if (listAddNodeTail(copy, value) == NULL) {
listRelease(copy);
listReleaseIterator(iter);
return NULL;
}
}
listReleaseIterator(iter);
return copy;
}
c. listSearchKey
//查找节点,如果设置了match方法,则使用match方法比较,否则仅仅比较节点的value值
listNode *listSearchKey(list *list, void *key)
{
listIter *iter;
listNode *node; iter = listGetIterator(list, AL_START_HEAD);
while((node = listNext(iter)) != NULL) {
if (list->match) {
if (list->match(node->value, key)) {
//这里可以将下面两条语句改为break(下同),最后return NULL改为 return node
listReleaseIterator(iter);
return node;
}
} else {
if (key == node->value) {
listReleaseIterator(iter);
return node;
}
}
}
listReleaseIterator(iter);
return NULL;
}
3. 总结
1. 通用链表实现
2. 对外提供扩展,用户可以自定义查找,复制,释放的功能。
Redis学习——链表源码分析的更多相关文章
- DotNetty网络通信框架学习之源码分析
DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...
- Redis学习之底层链表源码分析
Redis底层链表的源码分析: 一.链表结点的结构(单个结点): // listNode 双端链表节点 typedef struct listNode { // 前置节点 struct listNod ...
- Redis 内存管理 源码分析
要想了解redis底层的内存管理是如何进行的,直接看源码绝对是一个很好的选择 下面是我添加了详细注释的源码,需要注意的是,为了便于源码分析,我把redis为了弥补平台差异的那部分代码删了,只需要知道有 ...
- Redis网络模型的源码分析
Redis的网络模型是基于I/O多路复用程序来实现的.源码中包含四种多路复用函数库epoll.select.evport.kqueue.在程序编译时会根据系统自动选择这四种库其中之一.下面以epoll ...
- Redis之quicklist源码分析
一.quicklist简介 Redis列表是简单的字符串列表,按照插入顺序排序.你可以添加一个元素到列表的头部(左边)或者尾部(右边). 一个列表最多可以包含 232 - 1 个元素 (4294967 ...
- Redis之ziplist源码分析
一.ziplist简介 从上一篇分析我们知道quicklist的底层存储使用了ziplist(压缩列表),由于压缩列表本身也有不少内容,所以重新开了一篇,在正式源码之前,还是先看下ziplist的特点 ...
- Redis网络库源码分析(1)之介绍篇
一.前言 Redis网络库是一个单线程EPOLL模型的网络库,和Memcached使用的libevent相比,它没有那么庞大,代码一共2000多行,因此比较容易分析.其实网上已经有非常多有关这个网络库 ...
- bootstrap-modal 学习笔记 源码分析
Bootstrap是Twitter推出的一个开源的用于前端开发的工具包,怎么用直接官网 http://twitter.github.io/bootstrap/ 我博客的定位就是把这些年看过的源码给慢慢 ...
- Redis 数据结构-字符串源码分析
相关文章 Redis 初探-安装与使用 Redis常用指令 本文将从以下几个部分进行介绍 1.前言 2.常用命令 3.字符串结构 4.字符串实现 5.命令是如果操作字符串的 前言 平时在使用 Redi ...
随机推荐
- 【CodeVS 1037】取数游戏
http://codevs.cn/problem/1037/ Alice必胜是Alice将硬币移向边权为0的一端并且把经过的边变为0,让BoB无路可走. 这样只要起点到两个方向最近的0边权的端点的边数 ...
- 100114H
模拟 #include<iostream> #include<Cstdio> using namespace std; int n,k; ]; ][]; int main() ...
- Xmanager注册吗
xmanager4.0注册吗 --
- 控件(选择类): ListBox, RadioButton, CheckBox, ToggleSwitch
1.ListBox 的示例Controls/SelectionControl/ListBoxDemo.xaml <Page x:Class="Windows10.Controls.Se ...
- 在打开vs解决方案时,怎样让所以打开的项目自动折叠
使用VS 2010中的扩展性,搜PowerCommands,PowerCommands扩展在Visual Studio 2010中添加了数十个有用的的命令, Collapse Projects(折叠项 ...
- Oracle技术嘉年华
只有把一件事情做好,才会获得更多的机会! 短期的努力,成效并不明显,但是自己的成长一定能够感受到! 嘉年华的收获: 遗憾: 总结: 展望:
- 洛谷P1595 信封问题
题目描述 某人写了n封信和n个信封,如果所有的信都装错了信封.求所有信都装错信封共有多少种不同情况. 输入输出格式 输入格式: 一个信封数n 输出格式: 一个整数,代表有多少种情况. 输入输出样例 输 ...
- js调用刷新
_self.fireEvent('refresh');
- AngularJs filter 过滤器
Filter Ng里的过滤器. currency:把一个数字格式化成货币模式(如$1,234.56).当没有提供任何货币符号时,默认使用当前区域的符号. 使用: HTML:{{ currency_ex ...
- HDU 3466 Proud Merchants(01背包问题)
题目链接: 传送门 Proud Merchants Time Limit: 1000MS Memory Limit: 65536K Description Recently, iSea wen ...