call_out()函数小结
2021/4/7 11:43:54

转:(我也不知道哪年从internat上 copy save下来的)
因为reallove的帖子,我算是第一次较为仔细的看了一遍call_out()在driver中的机理,也明确了不少以前似是而非的概念。现整理如下:
 
1. 关于call_out()的driver级宏开关有两个(均在options.h当中):
 
    a. THIS_PLAYER_IN_CALL_OUT
 
    该宏被define时,我们可以在被延时呼叫的函数中肆无忌惮的使用this_player()来找到call_out定义时的this_player(),反之则无法找到准确的this_player()(也就是说,可能找到一个谁,但这个“谁”应该与定义call_out时的“谁”毫无瓜葛,肯定不是我们希望的那一个就对了)
 
    b. CALLOUT_HANDLES
 
    该宏被定义时,call_out()原型变成了 int call_out(function foo,int delay, ..),返回值是该call_out的唯一句柄,我们可以在remove_call_out()时以此为参数清理掉“这一个”而非“这一类”call_outs
 
 
 
2. 关于call_out的作用时机和delay的详细含义:
 
    已知call_out记录是以链表与delay的某个余数分类的形式进行存储的。
 
    call_out会在每个系统心跳(不是每个人的心跳,而是说,系统每次呼叫完所有心跳)之后进入对call_out们的处理(仔细的说,driver中call_out.c中的call_out()函数就是干这个事情的)。
 
    因此,就我现在阅读driver代码得到的结论,可以确定的说,call_out一定在心跳点上发作,但会有累积发作的模式。
 
   
 
  在解释delay之前,有几个“时间”需要说明:
 
  a. heart_beat()的发作时间:driver通过一个alarm/singal事件来设置hb的标志位,并在backend()的大循环当中不停检查该标志位的状态以决定是否应该触发hb,因此通常可以认为hb的发作较为准确。虽然从代码中看,在不同系统下的编译中,driver使用了alarm和ualarm两种不同方式进行按秒或按微秒级别的触发事件,但不那么精确的描述下,还是可以认为心跳的准时程度较高,更接近与真实系统时间。
 
  b. call_out被插入和判断是否被执行(注意不是是否进入call_out执行过程,而是进入后的“判断”),依据的是另外一个时间标记current_time。该标记在系统启动的时候被设置为当前时间的秒数(unix_time,也就是我们常看到的1239xxxxxxxx这种),其后只在系统心跳时被重置为“当前”。因此这个时间标并不总是等于真实的时间。特别是在hb大于1秒的情况下,如果以真实的秒为ticker来审视它,可能会是:0,0,0,[1,2,3],3,3,3,[4,5,6]这样的情况,即很多秒不变化,然后在同一个时间点上依次++直到追上真实时间。
 
 
 
    于是,关于delay有如下看法:
 
    a.在插入一条新的call_out时,delay看起来是从“现在”加上delay秒数后执行被呼叫函数,但这个“现在”是current_time指定的现在,hb>1sec时,他通常指的是过去。。。,因此当我们call_out(foo,3)的时候,他不一定指的是现在+3秒,而是指time()+3秒,他也不一定真的在三秒后执行。不考虑毫秒位的话,通常只有hb为1秒的时候,上面的描述才较为精确。但另外一个方面,delay的含义更倾向于秒,而不是hb。。。(我觉得我已经无法用人类的语言解释清楚这个破玩意儿了。。。。)
 
    b.如前述,call_out被执行一定是在hb的执行点上,具体的执行方式是:在某个HB执行点上,系统扫描小于current_time的call_out记录,然后依次执行(链表的原因,对于应该在“同一个时间点被执行的callout”,先入先执行)。然后系统对current_time++,继续上一步操作,知道current_time追赶上“现在”。
 
 
 
    所以说,如果你期

下一页
返回列表
返回首页
©2022 MUD游戏网_文字mud 电脑版
Powered by iwms