C++ Poco-安全使用removeObserver

C++ Poco-安全使用removeObserver,c++,multithreading,poco-libraries,C++,Multithreading,Poco Libraries,我在活动线程中有一个通知中心: Poco::NotificationCentre nc; // publicly visible // (thread main loop which will post notifications from time to time) 以及多个工作线程,它们根据通知进行操作。但是,那些等待通知的线程可能还需要在外部发出信号,以便随时退出。因此,我在我的工作线程中得到了以下内容(同样,这是伪代码,为了清晰起见,省略了一些细节) Poco::事件; std:

我在活动线程中有一个通知中心:

Poco::NotificationCentre nc;   // publicly visible

// (thread main loop which will post notifications from time to time)
以及多个工作线程,它们根据通知进行操作。但是,那些等待通知的线程可能还需要在外部发出信号,以便随时退出。因此,我在我的工作线程中得到了以下内容(同样,这是伪代码,为了清晰起见,省略了一些细节)

Poco::事件;
std::字符串s;
MyNotificationClass通知程序{event,s};//通过引用保存这些文件
Poco::NObserver obs(通知程序和MyNoficationClass::func);
nc.addObserver(obs);
event.wait();
nc.远程观察者(obs);
返回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;
};
struct MyNotificationClass
{
MyNotificationClass(Poco::Event&ev,std::string&s):ev(ev),s(s){}
void func(常量Poco::AutoPtr&p)
{
s=p->s;
ev.set();
}
Poco::事件和ev;
std::string&s;
};
我担心的是,即使在worker线程中调用了
removeObserver
,通知中心也可能同时向其发布了通知,因此,工作线程刚刚从中返回的函数中的对象
s
在被销毁后可能会被访问


我的问题是:这是一个有效的问题吗?如果是,我应该做些什么来确保
返回后不会出现通知?

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


原始答复:

这是一个值得关注的问题-辅助线程函数可能在add/removeObserver()调用之间被抢占。由于所有观察者指针中的
postNotification()
*,如果有来自其他线程的多个通知,则在调用
removeObserver()
后(甚至在函数返回后),指向观察者的指针可能仍在一个或多个副本列表中

现在,不必担心函数返回后会访问观察器,因为NotificationCenter会将其放入一个新的视图中。然而,由于NObserver持有通知处理程序,因此在当时调用通知处理程序时存在一个问题。为了防止不好的事情发生,请在从函数返回之前调用
obs.disable()
,这将以线程安全的方式为任何挂起的通知提供通知处理



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

对不起,我在哪里调用
disable()
?在
事件之后的任何位置。wait()
,可能最好尽快。您的意思是
obs.disable()
?好啊您提到NotificationCenter会复制观察者,因此仍然会有一个机会窗口,通知可能已经在NotificationCenter中启动(可能当前正在通知另一个线程,但尚未发送给该工作人员),并且已经复制了一份,所以它仍然会认为这个工作者的观察者没有被禁用?是的,很抱歉,它是
observer
,而不是
notifier.disable()
。我会在答案中修正它。至于问题的第二部分,
NObserver::disable/notify()
受互斥锁保护,因此如果线程正在执行
notify()
disable()
将等待。好的,考虑到互斥锁,它应该可以正常工作。谢谢,我试试看
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;
};