WheeelTimer定时器

WhellTimer定时器
enum
{
    WHEEL_BUCKETS = 4,
    TVN_BITS = 6,                   // time vector level shift bits
    TVR_BITS = 8,                   // timer vector shift bits
    TVN_SIZE = (1 << TVN_BITS),     // wheel slots of level vector
    TVR_SIZE = (1 << TVR_BITS),     // wheel slots of vector
    TVN_MASK = (TVN_SIZE - 1),      //
    TVR_MASK = (TVR_SIZE - 1),      //

    MAX_TVAL = ((uint64_t)((1ULL << (TVR_BITS + 4 * TVN_BITS)) - 1)),
};
定时器一开始将当前时间(厘秒)赋值给current_
每隔一小时段时间update一次,取自开始以来的运行时间interval=now-currend_
(实际上就是jiffies_的值,jiffies_在每个tick都会自增一次)
定时器将数字划分为[0,429496729)的五个区域,
[0,256)   [0,TVR_SIZE)
[256,16384)  [TVR_SIZE, TVR_BITS + TVN_BITS)
[16384,1048576) [ TVR_BITS + TVN_BIT, TVR_BITS + 2*TVN_BITS)
[1048576,67108864)
[67108864,4294967296)
为了方便理解,近似看成时钟的时分秒,
秒针类比到[0,256),分针类比到[256,16384),时针类比到[16384,1048576),jiffies_自增1相当于秒针加一,
比如现在是定时器运行后的1小时,将定时任务设定在3小时02分59秒,实际是定时器运行后的4小时02分59秒,
秒针转一圈分针加一,分针转一圈时针加一,
这样要到达4小时02分59秒,必然是4小时这个点先到达,刚好到达4小时这个点后,这时候秒针和分针刚好是0(即相当于程序里的
index == 0且 INDEX(0) == 0,执行cascade(0, INDEX(0)和cascade(1, INDEX(1))),
用过期时间减去运行时间(jiffies_的值,相当于程序里的expires - jiffies_),得到是02分59秒,再通过算法将02分这个点求出来放到对应的数组对应的下标
(相当于程序里的(expires >> TVR_BITS) & TVN_MASK)
然后时间继续走,秒针加一,转完一圈后分针加一,刚到达02分这个点时,秒针必然为0,执行cascade(0, INDEX(0)),用过期时间减去运行时间(jiffies_的值,
注意,这里的jiffies_应该是4小时加上2分钟的值),所以剩下的是59秒,通过算法将59秒这个点放到对应的数组对应的下标(相当于expires & TVR_MASK)
因为秒针是最小的单位,即对应[0,256),所以相当于放在[0,256),然后秒针加一继续转,当转到59时,取出这个数组下标的所有过期
事件来执行(execute)


求39000在[0,256),[256,16384),[16384,1048576)这三个数组中分别对应的槽点,

256 = 1 << 8
16384 = 1 << (8+6)
1048576 = 1 << (8+2*6)

39000在[16384,1048576)范围内,
先求这个数组的槽点,
(39000 >> (8+6)) & 63 = 2 等价于 39000 / 16384 % 64 
再求在[256,16384)数组对应的槽点,
(39000 >> 8) & 63 = 24 等价于 39000 / 256 % 64 
再求在[0,256)数组对应的槽点,
39000 & 255 = 88 等价于 39000 % 256 

类比于时钟, 7507转化为时分秒
7507 % 60 = 7
7507 / 60 % 60 = 5 (/ 60是为了求出有多少分钟,
再%60是除去完整的小时后还有多少分钟,不足一圈不足一小时)
7507 / 3600 = 2

256相当于秒针到分针的进率60,
64相当于分针到时针的进率60
即假设秒针要转256次分针才加1,
分针要转64次时针才加1

验证:
39000 = 16384*2 + 256 * 24 + 88
即39000 = (1 << (8+6))*2 + (1 << 8) * 24 + 88

39000转二进制                    1001100001011000
16384*2(即1 << (8+6))*2)转二进制 1000000000000000
(1 << 8) * 24  转二进制           0001100000000000
88  转二进制                     0000000001011000

32768在[16384,1048576)范围内,
先求这个数组的槽点,
(32768 >> (8+6)) & 63 = 2
再求在[256,16384)数组对应的槽点,
(32768 >> 8) & 63 = 0
再求在[0,256)数组对应的槽点,
32768 & 255 = 0
验证:
32768 = 16384*2 + 256 * 0 + 0

发布了50 篇原创文章 · 获赞 24 · 访问量 13万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览