redis源码解析-整数集-intset(6.2.3版本)

整数集,为redis中的一种结构体,你可以把它理解成stl中的std::<set>,当然redis专门定制化这种结构是为了优化内存效率和查找效率。

#define INTSET_ENC_INT16 (sizeof(int16_t)) //16位编码
#define INTSET_ENC_INT32 (sizeof(int32_t))  //32位编码
#define INTSET_ENC_INT64 (sizeof(int64_t))  //64位编码

#ifndef __INTSET_H
#define __INTSET_H
#include <stdint.h>

typedef struct intset {
    uint32_t encoding;//保存元素所使用类型的长度
    uint32_t length;//保存元素的个数
    int8_t contents[];//保存元素的数组
} intset;

intset *intsetNew(void);  //新建一个inset实例
intset *intsetAdd(intset *is, int64_t value, uint8_t *success);//添加一个元素
intset *intsetRemove(intset *is, int64_t value, int *success);//删除一个元素
uint8_t intsetFind(intset *is, int64_t value);//查找元素
int64_t intsetRandom(intset *is);//随机返回一个元素
uint8_t intsetGet(intset *is, uint32_t pos, int64_t *value);//获取具体位置的元素
uint32_t intsetLen(const intset *is);//返回intset的长度
size_t intsetBlobLen(intset *is);//返回整数集合现在占用的字节数

//验证数据结构的完整性。
//当'deep'为0时,仅验证标头的完整性。
//当'deep'为1时,我们确保没有重复或无序的记录
int intsetValidateIntegrity(const unsigned char *is, size_t size, int deep);

#ifdef REDIS_TEST
int intsetTest(int argc, char *argv[], int accurate);//测试intse用
#endif

#endif // __INTSET_H

        在intset.c源码中,提供了三种编码类型,16位、32位和64位,用户可以根据需要定制各种类型的整数集。intset内部也提供可动态伸缩编码类型的函数

/* Upgrades the intset to a larger encoding and inserts the given integer. */

static intset *intsetUpgradeAndAdd(intset *is, int64_t value) 

inset内部查找算法,一个二分查找算法。

/* Search for the position of "value". Return 1 when the value was found and
 * sets "pos" to the position of the value within the intset. Return 0 when
 * the value is not present in the intset and sets "pos" to the position
 * where "value" can be inserted. */
static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) {
    int min = 0, max = intrev32ifbe(is->length)-1, mid = -1;
    int64_t cur = -1;

    /* The value can never be found when the set is empty */
    if (intrev32ifbe(is->length) == 0) {
        if (pos) *pos = 0;
        return 0;
    } else {
        /* Check for the case where we know we cannot find the value,
         * but do know the insert position. */
        if (value > _intsetGet(is,max)) {
            if (pos) *pos = intrev32ifbe(is->length);
            return 0;
        } else if (value < _intsetGet(is,0)) {
            if (pos) *pos = 0;
            return 0;
        }
    }

    while(max >= min) {
        mid = ((unsigned int)min + (unsigned int)max) >> 1;
        cur = _intsetGet(is,mid);
        if (value > cur) {
            min = mid+1;
        } else if (value < cur) {
            max = mid-1;
        } else {
            break;
        }
    }

    if (value == cur) {
        if (pos) *pos = mid;
        return 1;
    } else {
        if (pos) *pos = min;
        return 0;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值