学一下redis,源码版本: bedecec786767b84215f4002a02d18110585915a
- 为了兼容printf,返回出去的指针不是sds的头而是str部分的地址,有点类似kernel的list header那味,通过偏移来获得sds的header地址,进而得到其field。redis/src/sds.c:103 函数: _sdsnewlen可以体现,偏移怎么算在header里面有宏
- flag标记就在返回指针的前一个字节,所以会看到很多[-1]这样的骚操作。说人话就是返回前面那个flag地址,低三位是类型标记信息
- 分配空间包括string + header + 1 也就是最后那个’\0’来封堵一下。同时也是flat的,头+string+1是连续空间,也是为什么sds[-1]拿到flag可以成立的前提
- 为什么要定义好几个sds类型? 从定义来看还是通过string本身的长度来决定让sdsheader更小一点,体现在len/alloc的数据类型上。从uint8->uint16->uint32->uint64,能省就省,能抠一点是一点。
- argc/argv已经忘光了,里面这些函数基本忽略了
typedef struct list {
listNode *head;
listNode *tail;
void *(*dup)(void *ptr);
void (*free)(void *ptr);
int (*match)(void *ptr, void *key);
unsigned long len;
} list;
两头指针加函数指针用来操作,通过函数名称已经知道各个函数什么意思。
- 不打环,首尾两个指针不互相串,一个元素时prev/next都为nullptr,头的prev,尾的next都为nullptr;
// 插入node时的体现
if (node->prev != NULL) {
node->prev->next = node;
}
if (node->next != NULL) {
node->next->prev = node;
}
void listLinkNodeTail(list *list, listNode *node) {
if (list->len == 0) {
list->head = list->tail = node;
// 单节点的体现
node->prev = node->next = NULL;
} else {
node->prev = list->tail;
node->next = NULL;
list->tail->next = node;
list->tail = node;
}
list->len++;
}
- 这个骚操作想干嘛?
void listRotateTailToHead(list *list) {
void listRotateHeadToTail(list *list) {
函数指针指着dict的具体操作,比如hash,cmp函数等。
- unsigned int keys_are_odd:1; 这个字段用处?
- void *dictFindPositionForInsert(dict *d, const void *key, dictEntry **existing) key存在吗? yes, 那就返回nullptr, 否则返回bucket给插入的位置。
- 总体上两个指针分别指向连续开辟的size * sizeof(dictEntry)的地方,然后hash(key) % len –> 得到存储的index,挂指针串起来来解决冲突。 一个[0] 用来