redis原始碼閱讀筆記-dict.h
阿新 • • 發佈:2019-02-10
dict.h
在redis中,dict.h主要是hash的底層實現方式。
在dict.h中主要是一些資料結構的定義,以及一些巨集函式的定義相關的內容。
雜湊節點定義
原始碼中的dictEntry就是雜湊節點的相關定義
typedef struct dictEntry {
void *key; //存放key值
union { //使用一個union存放value值
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry * next; //hash衝突使用開鏈法,因此使用了一個next指標指向下一個節點
} dictEntry;
dictType
在dictType中,存放了一些操作函式
typedef struct dictType {
uint64_t (*hashFunction)(const void *key); //雜湊函式
void *(*keyDup)(void *privdata, const void *key); //key複製
void *(*valDup)(void *privdata, const void *obj); //value複製
int (*keyCompare) (void *privdata, const void *key1, const void *key2); //key比較函式
void (*keyDestructor)(void *privdata, void *key); //key析構
void (*valDestructor)(void *privdata, void *obj); //value析構
} dictType;
dictht
dictht就是雜湊表的結構
`typedef struct dictht {
dictEntry **table; //雜湊節點指標陣列
unsigned long size; //雜湊長度
unsigned long sizemask; //雜湊掩碼(用於計算雜湊索引)
unsigned long used; //已經使用的節點數目
} dictht;
``
#### dict
//字典的資料結構的定義
```c
typedef struct dict {
dictType *type; //儲存一些函式
void *privdata; //私有資料
dictht ht[2]; //雜湊表,注意,這裡的雜湊表有兩張,主要是為了rehash操作預備
long rehashidx; //雜湊索引
unsigned long iterators; //記錄正在使用的迭代器數量
} dict;```
#### dictIterator
dictIterator充當字典迭代器的作用。
這裡的迭代器分為了兩種,一種迭代器是safe的,它可以進行讀寫操作
另外一種迭代器是unsafe的,是一種只讀迭代器
```c
`typedef struct dictIterator {
dict *d; //字典
long index; //字典索引
int table, safe; //safe標誌是否為safe迭代器,table標誌當前雜湊表號碼(0或者1
dictEntry *entry, *nextEntry; //當前節點與下一個節點
long long fingerprint; //dict指紋,避免迭代器失效的作用
} dictIterator;
另外一些巨集函式
//釋放節點
#define dictFreeVal(d, entry) \
if ((d)->type->valDestructor) \ //如果hashType中定義了valDestructor函式的話,呼叫其釋放節點
(d)->type->valDestructor((d)->privdata, (entry)->v.val)
//設定節點的value
#define dictSetVal(d, entry, _val_) do { \
if ((d)->type->valDup) \ //如果存在value複製函式,就呼叫value複製函式,否則直接賦值
(entry)->v.val = (d)->type->valDup((d)->privdata, _val_); \
else \
(entry)->v.val = (_val_); \
} while(0)
//設定int的value值
#define dictSetSignedIntegerVal(entry, _val_) \
do { (entry)->v.s64 = _val_; } while(0)
//設定unsigned的value值
#define dictSetUnsignedIntegerVal(entry, _val_) \
do { (entry)->v.u64 = _val_; } while(0)
//設定double的value值
#define dictSetDoubleVal(entry, _val_) \
do { (entry)->v.d = _val_; } while(0)
//釋放key值,呼叫dictType中的函式釋放
#define dictFreeKey(d, entry) \
if ((d)->type->keyDestructor) \
(d)->type->keyDestructor((d)->privdata, (entry)->key)
//設定key
//如果存在keyDup函式,那麼呼叫keyDup函式,否則直接賦值
#define dictSetKey(d, entry, _key_) do { \
if ((d)->type->keyDup) \
(entry)->key = (d)->type->keyDup((d)->privdata, _key_); \
else \
(entry)->key = (_key_); \
} while(0)
//比較key,同樣的,呼叫dictType中的keyCompare函式
#define dictCompareKeys(d, key1, key2) \
(((d)->type->keyCompare) ? \
(d)->type->keyCompare((d)->privdata, key1, key2) : \
(key1) == (key2))
//獲取hash
#define dictHashKey(d, key) (d)->type->hashFunction(key)
#define dictGetKey(he) ((he)->key) //得到節點的key
#define dictGetVal(he) ((he)->v.val) //得到節點的value值
#define dictGetSignedIntegerVal(he) ((he)->v.s64) //得到節點的int值
#define dictGetUnsignedIntegerVal(he) ((he)->v.u64) //得到節點的unsigned int值
#define dictGetDoubleVal(he) ((he)->v.d) //得到節點的value值
#define dictSlots(d) ((d)->ht[0].size+(d)->ht[1].size) //總size
#define dictSize(d) ((d)->ht[0].used+(d)->ht[1].used) //總的used size
#define dictIsRehashing(d) ((d)->rehashidx != -1) //是否正在rehash