异步的程序基本上离不开回调函数。如果回调函数出现递归,可能会导致不良效果。所以,我们应该避免回调函数的递归,不过是通过改变程序逻辑还是采用某些手段,甚至是粗暴的终止进程都行。先说说递归的出现情况。
回调函数如下
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等)中被调用。这可以算作是回调的调度安排的处理方式。
阅读(3446) | 评论(0) | 转发(0) |