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を直接変更することができる.