关于定时器的封装

为什么要封装定时器?

  1. skynet只提供定时器注册回调,缺少传参,注销,延伸等等常用方法。

实现思路

一开始尝试用分配定时器id的方式实现,这种方式要考虑id重用的情况,虽然说int64走一个轮回要很久,但是这种情况还是要处理,走了一个轮回后,就有可能前面的id还被占用着,后续的id分配效率会降低。这种实现方式不是很稳定可靠。
后续想了一下还是用面向对象的思想,因为前一种方式无非是timer模块用一个map对应id映射定时器信息表,注册好了返回一个id,供使用者做后续注销延期,既然返回id是返回,为什么不直接返回table呢,反正返回的也是table的引用,并没有增加什么开销,感觉分配id的操作有点画蛇添足了。
还是用面向对象思想,定时器实例提供创建定时器取消定时器延长定时器等等方法。
定时器实例可以设置定时回调几次或者循环调用。后续可以继续实现按时间节点触发的定时器,比如每天上午8点,每周一零点。

特殊处理

通常注册一个定时器立马调用skynet.timeout,但是如果你的定时器需要取消,我觉得这样并不好,特别是你注册的时间较长,又会注销,过程中又触发注册很频繁的话,这样会浪费掉很多内存,因为skynet注册一个定时器就会占用一个lua携程直到定时器触发回调才释放。如果你注册触发时间为1天,那么会积压1天内注册的定时器。所以我没有直接调用skynet.timeout,而是用一个间隔60秒的check循环,如果中途注销了,循环就结束了,这样非常有效的解决了这个问题,虽然多一些定时器注册回调,但是换来了稳定性,使用者不用担心有内存暴涨的风险。

使用方式

  • 创建定时器
    timer:new()
    3个必传参数
    expire 回调时间,保留skynet.time_out的100等于1秒。
    timer 触发次数,0次表示循环触发。
    callback 回调函数。

    后面省略传参是回调函数的参数。

  • 取消定时器
    timeobj:cancel()

  • 延长定时器
    timeobj:extend(ex_expire)
    参数
    ex_expire 延长时间,如果创建定时器的时间为5秒,创建时间为:8:10:30,在定时器触发之前调用 timeobj:extend(100),定时器会再8:10:36秒触发,在定时器触发之后调用无效。

skynetfly源码地址


关于定时器的封装
https://huahua132.github.io/2023/07/02/skynet_fly_ss/timer/
作者
huahua132
发布于
2023年7月2日
许可协议