Poco - 安全地使用removeObserver

时间:2015-08-25 04:18:55

标签: c++ multithreading poco-libraries

我在活动主题中有一个通知中心:

Poco::NotificationCentre nc;   // publicly visible

// (thread main loop which will post notifications from time to time)

以及作用于通知的多个工作线程。但是,等待通知的那些线程也可能需要在外部发信号以便随时退出。所以我的工作线程中有以下内容(为了清晰起见,这是伪代码省略了一些细节)

Poco::Event event;
std::string s;
MyNotificationClass notifier{event, s};  // holds those by reference
Poco::NObserver<MyNotificationClass, MyNotification> obs(notifier, &MyNoficationClass::func);

nc.addObserver(obs);
event.wait();
nc.removeObserver(obs);

return s;

通知类是:

struct MyNotificationClass
{
    MyNotificationClass(Poco::Event &ev, std::string &s): ev(ev), s(s) {}
    void func(const Poco::AutoPtr<MyNotification> &p)
    {
        s = p->s;
        ev.set();
    }
    Poco::Event &ev;
    std::string &s;
};

我担心的是,即使在工作线程中调用removeObserver之后,通知中心也可能同时向其发布了通知,因此函数中的对象s只有return编辑的工作线程可能会在销毁之后被访问。

我的问题是:这是一个有效的问题,如果是这样,我该怎么做才能确保在return之后不会发出通知?

1 个答案:

答案 0 :(得分:1)

编辑:由于menudisabling被删除的观察者,因此上述代码是安全的。下面的答案留给记录以理解评论部分。

原始答案:

这是一个有效的问题 - 工作线程函数可以在add / removeObserver()调用之间被抢占。由于所有观察者指针的enter code here SELECT * FROM Table1 INNER JOIN Table2 ON Table1.user_id = Table2.user_id INNER JOIN Table3 ON Table2.[phone no] = Table3.[phone no] makes a copy *,如果有来自其他线程的多个通知,则在调用{{{{{{{{{{{{{{{{{ 1}}(甚至在函数返回后)。

现在,无需担心函数返回后被访问的观察者,因为NotificationCenter将cloned SharedPtr放入naked address。但是,有一个问题是当时正在调用通知处理程序,因为NObserver持有disarm。为了防止发生错误,请在从函数返回之前调用removeObserver() - 这将{{3}}以线程安全的方式处理任何待处理通知的通知。

* 出于性能原因 - 我们不希望在所有通知处理程序正在执行时阻止其余的NotificationCenter。