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 ...
随机推荐
- jQ1.5源码注释以及解读RE
jQ作为javascript的库( ▼-▼ ), 尽善尽美, 代码优美, 值得学习. 这一周平常上班没啥事也看jQ1.5的代码, 今天周六差不多看完了(Sizzle部分还没看), 重新看了一下, ...
- bootstrap-fileupload-上传文件控件
官方github:https://github.com/kartik-v/bootstrap-fileinput 官方dome网站:http://plugins.krajee.com/file-bas ...
- 如何在HTMl网页中插入百度地图
方法/步骤 1.打开"百度地图生成器"的网址:http://api.map.baidu.com/lbsapi/creatmap/index.html 如下图: 2.在"1 ...
- python初识生成器 迭代器
生成器 带有 yield 的函数在 Python 中被称之为 generator(生成器) def xragns(): #定义函数生成器 print('小伙') yield ('好') #加上yiel ...
- Python 编辑器 tips
1. IDLE界面美化 注意IDLE是可以设置语法高亮的:(美化参考 http://www.linuxidc.com/Linux/2012-07/66129.htm) windows 用户,直接打开 ...
- 小记-虚拟机装ubuntu遇到问题
今天用虚拟机virtualbox装ubuntu遇到了一个问题,如图 解决方法: 1.首先查看创建虚拟机的时候是基本设置有没有对:(如图) 主要去看所选择的版本对应是否正确,比如32位和64位之类的. ...
- BZOJ 1088 扫雷Mine
今天做了几道BZOJ的题,发现统观题目时还是很多很多都不会的,不过还是有几道时可以作的,以后要慢慢加强,争取多做题 BZOJ 1088 扫雷 其实本人平常不大玩扫雷的,就算玩也不是很好,不过看n*2的 ...
- Unable to load native-hadoop library for your platform... using builtin-Java classes where applicable
以前hadoop也有这个问题,没注意,用spark也提示,解决一下. 首先找到对应自己hadoop版本的的lib包,编译好后,名字类似hadoop-native-64-2.4.1.tar ,放到lib ...
- Linux Process Virtual Memory
目录 . 简介 . 进程虚拟地址空间 . 内存映射的原理 . 数据结构 . 对区域的操作 . 地址空间 . 内存映射 . 反向映射 .堆的管理 . 缺页异常的处理 . 用户空间缺页异常的校正 . 内核 ...
- MVC5-10 从模型验证来说内部那些事
源码解析 模型验证几乎在大部分的项目中都在被使用,这方面的博文教程也很多,关于那些更详细的模型验证这里就不多赘述了,主要讲解内部是如何进行验证的. 在前几篇博文中提到了DefaultModelBind ...