skynet自带定时器功能skynet-src/skynet_timer.c,在skynet启动时会创建一个线程专门跑定时器。每帧(0.0025秒/帧)调用skynet_updatetime()
1 // skynet-src/skynet_start.c
2
3 create_thread(&pid[1], thread_timer, m);
4
5 static void *
6 thread_timer(void *p) {
7 struct monitor * m = p;
8 skynet_initthread(THREAD_TIMER);
9 for (;;) {
10 skynet_updatetime();
11 CHECK_ABORT
12 wakeup(m,m->count-1);
13 usleep(2500); //2500微妙=0.0025秒
14 if (SIG) {
15 signal_hup();
16 SIG = 0;
17 }
18 }
19 ...
20 }
1. 设计思想
skynet的设计思想参考Linux内核动态定时器的机制,参考Linux动态内核定时器介绍http://www.cnblogs.com/leaven/archive/2010/08/19/1803382.html,
在skynet里,时间精度是0.01秒,这对于游戏服务器来说已经足够了,定义1滴答=0.01秒,1秒=100滴答。其核心思想是:每个定时器设置一个到期的滴答数,与当前系统的滴答数(启动时是0,然后1滴答1滴答往后跳)比较差值,如果差值interval比较小(0<=interval<=2^8-1),表示定时器即将到来,需要严格关注,把它们保存在2^8个定时器链表里;如果interval越大,表示定时器越远,可以不用太关注,划分成4个等级,2^8<=interval<=2^(8+6)-1,2^(8+6)<=interval<=2^(8+6+6),...,每个等级只需要2^6个定时器链表保存,比如对于2^8<=interval<=2^(8+6)-1的定时器,将interval>>8相同的值idx保存在第一个等级位置为idx的链表里。
这样做的优势是:不用为每一个interval创建一个链表,而只需要2^8+4*(2^6)个链表,大大节省了内存。
之后,在不同情况下,分配不同等级的定时器,