回调函数应该避免递归。

3479阅读 0评论2009-10-13 pagx
分类:WINDOWS

异步的程序基本上离不开回调函数。如果回调函数出现递归,可能会导致不良效果。所以,我们应该避免回调函数的递归,不过是通过改变程序逻辑还是采用某些手段,甚至是粗暴的终止进程都行。先说说递归的出现情况。

回调函数如下

void callback(void *p)
{
   do_frame_call();
}

假如在调用 do_frame_call() 中再次触发callback函数, 并且函数的调用并没有进行调度安排,而是直接或者间接调用,那么这种情况下递归就会产生。严重的就会导致堆栈的破坏(相当于无限的递归调用)。即使没有导致堆栈破坏,也会使得 do_frame_call() 的实现变的不可靠(变得麻烦), 比如在遍历列表时因为 do_frame_call的再次调用可能会删除列表的元素导致上层do_frame_call的迭代子变得无效。

对于这个问题如何检测和避免。检测很简单,设置一个标志就可以搞掂。至于如何避免,可以有两种方案,第一种是要求调用者不能在callback中再次调用do_frame_call(), 一旦检测出来程序直接终止。第二种方案是对callback的调用进行调度安排,只有程序在离开do_frame_call时才对callback进行直接的调用,否则只是把它放进调度队列里面。另外作为第二种的变形和简化,可以把callback放到一个独立的线程中运行,只需要注意与do_frame_call()的同步即可。

操作系统的信号处理,一般也是在内核返回用户空间时被投递。windows的APC仅仅在若干函数(SleepEx等)中被调用。这可以算作是回调的调度安排的处理方式。
上一篇:windows 下的自动更新
下一篇:GetLastInput 使用