使用Poco :: NotificationCenter

时间:2019-01-11 19:48:22

标签: c++ deadlock poco-libraries notificationcenter

我正在将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()的锁上等待? 从用户发送给我的过程样本来看,我的假设似乎是正确的。

但是由于某种原因,这在大多数情况下似乎并没有陷入僵局(我自己从未经历过)。我只是一步步调试器,无法使其锁定。有谁解释为什么仅在某些情况下才会锁定?

0 个答案:

没有答案