Redis list

3939 ワード

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の3つの構造が使用され、listNodeはチェーンテーブルの各ノードを表し、listはチェーンテーブル全体を指し、listIterはリスト全体に反復的にアクセスするためであり、内部は実はlistNodeポインタである.
ListNodeが提供するprev、nextポインタはlist全体を双方向チェーンテーブルにリンクし、保存された値はvoid*タイプであり、値のコピー、解放、マッチング操作はlistに登録された3つの関数ポインタdup、free、matchで行われる.
リスト構造では、リストノードの値を操作する3つの関数ポインタに加えて、リストのヘッダと末尾を指すhead、tailポインタも提供されます.またリストのlenはリスト全体の長さを保存しており、リストが空かどうかの判断に便利です(余計でしょう).
ListIterはlistを巡回するため、頭、尾から巡回することができます.使用法は、次のような疑似コードで表すことができます.
iter=listGetIterotr(list, <direction>); while ((node=listNext(iter)) !=NULL) { 	DoSomethingWith(listNodeValue(node)); }

また、ノードを追加、削除するapi(listAddNodeHead、listAddNodeTail、listDelNode)では、ノード内部のvalueを割り当て、解放するために使用されるメモリはなく、呼び出し者がvalueが占めるメモリ(ノード自体のメモリの割り当てと解放を除く)を自分で割り当てまたは解放する必要があります.
一見、あるノードの値を変更する方法は提供されていないが、listSearchKey、listIndexなどの方法でノードポインタが返されるため、ノードのvalueを直接変更することができる.