我正在将Poco用作C ++应用程序的一部分,但遇到了一个我不太了解的问题。该应用程序是从Obj-C翻译而来,并大量使用了Apple的NSNotificationCenter。
为使过渡尽可能轻松,我决定改用Poco的NotificationCenter。它工作正常,但我有一些用户报告了我现在要解决的死锁。
对于不熟悉NotificationCenter的人来说,请速览。您注册了这样的通知:
Poco::NotificationCenter& nc = Poco::NotificationCenter::defaultCenter();
nc.addObserver(Poco::NObserver<MyClass, MyNotification>(*this, &MyClass::onNotification));
并发布这样的通知:
Poco::NotificationCenter& nc = Poco::NotificationCenter::defaultCenter();
nc.postNotification(new MyNotification());
postNotification()方法的定义如下:
void NotificationCenter::postNotification(Notification::Ptr pNotification)
{
poco_check_ptr (pNotification);
ScopedLockWithUnlock<Mutex> lock(_mutex);
ObserverList observersToNotify(_observers);
lock.unlock();
for (ObserverList::iterator it = observersToNotify.begin(); it != observersToNotify.end(); ++it)
{
(*it)->notify(pNotification);
}
}
和NObserver :: notify()一样:
void notify(Notification* pNf) const
{
Poco::Mutex::ScopedLock lock(_mutex);
if (_pObject)
{
N* pCastNf = dynamic_cast<N*>(pNf);
if (pCastNf)
{
NotificationPtr ptr(pCastNf, true);
(_pObject->*_method)(ptr);
}
}
}
这真的很简单,并且不涉及任何黑魔法。
鉴于postNotification方法始终在所有观察者上进行迭代(在锁定了一个观察者之后,然后使用动态类型转换检查通知的类型是否匹配),我假设在发送通知时,此方法必须始终导致死锁从通知处理程序中获取,因为它还会尝试访问从中调用自身的观察者,并将永远在NObserver :: notify()的锁上等待? 从用户发送给我的过程样本来看,我的假设似乎是正确的。
但是由于某种原因,这在大多数情况下似乎并没有陷入僵局(我自己从未经历过)。我只是一步步调试器,无法使其锁定。有谁解释为什么仅在某些情况下才会锁定?