Chinaunix首页 | 论坛 | 博客
  • 博客访问: 929165
  • 博文数量: 201
  • 博客积分: 8078
  • 博客等级: 中将
  • 技术积分: 2162
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-20 17:22
文章分类

全部博文(201)

文章存档

2013年(3)

2012年(11)

2011年(34)

2010年(25)

2009年(51)

2008年(77)

分类: WINDOWS

2009-10-13 13:20:59

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

回调函数如下

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) |
给主人留下些什么吧!~~