近日碰到一个很妖的问题:在调用ACE_Message_Queue的enqueue_tail的时候不返回。死锁。
我已经设置了超时为当前时间,但是它就是不返回。仔细查看ACE源码和说明都无结果。无奈之下动用聊天大法(当碰到问题一筹莫展的时候,找个人聊聊自己
的问题,经常会云开雾散)。将自己的问题跟同事王暾讲了讲,请他帮我看看问题的所在。王暾拿了代码之后,做了一个细微的修改,让死锁的位置发生了变化,
死锁在notify()函数处。有个这个线索,重新翻开ACE参考书《C++ Network Programming volume 2》,找到
ACE_Reactor的说明,赫然发现 Sidebar 17: Avoiding Reactor Notification
Mechanism Deadlock 。原来ACE_Reactor的notify是同步的,类似于windows的SendMessage函数,是
需要Reactor立即处理的,如果Notify在hand_input之类的函数里面被调用,则很容易形成死锁。解决办法有两个,一个是为
Notify函数设一个超时,另一个办法是修改代码避免在这些可能造成死锁的函数里面调用Notify。
对于我的情况enqueue_tail不返回,就是因为我给ACE_Message_Queue设了一个
ACE_Reactor_Notification_Strategy对象,它会自动调用reactor的Notify函数。
其实我要的是能够通知到reactor,并不要求它立刻处理,所以用mask_ops()或者schedule_wakeup()就可以了。这两个函数
会告知reactor事件唤起,但是会等到下一次handle_events()时才会真正分发事件,这能满足我的需求。
看来以后看书要看仔细点,例子也不能随便乱抄。在用一个东西的好处时,需要了解其使用的限制。就好像吃药,不能光看它的疗效,还要关注它的副作
用。 :)