Redis list

Redis list

先简单介绍下redis中用到的链表,是在文件adlist.c和adlist.h中实现的。

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);
    
void  ( * free)( void   * ptr);
    
int  ( * match)( void   * ptr,  void   * key);
    unsigned 
int  len;
} list;

/*  Functions implemented as macros  */
#define  listLength(l) ((l)->len)
#define  listFirst(l) ((l)->head)
#define  listLast(l) ((l)->tail)
#define  listPrevNode(n) ((n)->prev)
#define  listNextNode(n) ((n)->next)
#define  listNodeValue(n) ((n)->value)

#define  listSetDupMethod(l,m) ((l)->dup = (m))
#define  listSetFreeMethod(l,m) ((l)->free = (m))
#define  listSetMatchMethod(l,m) ((l)->match = (m))

#define  listGetDupMethod(l) ((l)->dup)
#define  listGetFree(l) ((l)->free)
#define  listGetMatchMethod(l) ((l)->match)

/*  Prototypes  */
list 
* listCreate( void );
void  listRelease(list  * list);
list 
* listAddNodeHead(list  * list,  void   * value);
list 
* listAddNodeTail(list  * list,  void   * value);
list 
* listInsertNode(list  * list, listNode  * old_node,  void   * value,  int  after);
void  listDelNode(list  * list, listNode  * node);
listIter 
* listGetIterator(list  * list,  int  direction);
listNode 
* listNext(listIter  * iter);
void  listReleaseIterator(listIter  * iter);
list 
* listDup(list  * orig);
listNode 
* listSearchKey(list  * list,  void   * key);
listNode 
* listIndex(list  * list,  int  index);
void  listRewind(list  * list, listIter  * li);
void  listRewindTail(list  * list, listIter  * li);

实现中主要用到listNode、list、listIter三个结构,listNode代表链表中的每个节点,list指向整个链表,listIter是为了迭代访问整个list,内部其实就是个listNode指针。

listNode提供的prev、next指针将整个list链接成一个双向链表,保存的值是void *类型,对值的复制、释放、匹配操作是用在list中注册的三个函数指针dup、free、match完成的。

在list结构中,除提供对listNode中的值进行操作的三个函数指针外,还提供了head、tail指针,以指向list的头部和尾部。另外list的len保存了整个list的长度,方便对list是否为空的判断(纯属多余吧)。

listIter是为了遍历list,可以从头部、尾部开始遍历。用法可用如下伪代码表示:

iter=listGetIterotr(list, <direction>); while ((node=listNext(iter)) !=NULL) { 	DoSomethingWith(listNodeValue(node)); }

另外注意:在提供的增加、删除节点的api(listAddNodeHead、listAddNodeTail、listDelNode)中,并没有分配、释放节点 内部的value所用内存,需要调用者自己分配或者释放value所占的内存(除了分配和释放节点本身的内存外)。

乍一看没有提供修改某个节点的值的方法,但是由于listSearchKey、listIndex等方法返回了节点指针,故可以直接修改节点的value。

你可能感兴趣的:(Redis list)