Poco - 安全地使用 removeObserver
Poco - using removeObserver safely
我在 Activity 线程中有一个通知中心:
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;
通知class是:
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
之后不会出现通知?
编辑:因为removeObserver()
是disabling移除的观察者,上面的代码是安全的。下面的答案留作记录,以便理解评论部分。
原回答:
这是一个合理的担忧 - 工作线程函数可以在 add/removeObserver() 调用之间被抢占。由于 postNotification()
makes a copy* 所有观察者的指针,如果有来自其他线程的多个通知,您的观察者的指针可能在您调用 removeObserver()
(甚至在函数 returns 之后)。
现在,无需担心在函数 returns 之后访问观察者,因为它 cloned into a SharedPtr by the NotificationCenter. There is, however, a concern about the notification handler being called at that time because NObserver holds its naked address. To prevent bad things happen, call obs.disable()
before returning from the function - that will disarm 以线程安全的方式处理任何未决通知。
* 出于性能原因 - 我们不想在所有通知处理程序执行时阻塞通知中心的其余部分。
我在 Activity 线程中有一个通知中心:
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;
通知class是:
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
之后不会出现通知?
编辑:因为removeObserver()
是disabling移除的观察者,上面的代码是安全的。下面的答案留作记录,以便理解评论部分。
原回答:
这是一个合理的担忧 - 工作线程函数可以在 add/removeObserver() 调用之间被抢占。由于 postNotification()
makes a copy* 所有观察者的指针,如果有来自其他线程的多个通知,您的观察者的指针可能在您调用 removeObserver()
(甚至在函数 returns 之后)。
现在,无需担心在函数 returns 之后访问观察者,因为它 cloned into a SharedPtr by the NotificationCenter. There is, however, a concern about the notification handler being called at that time because NObserver holds its naked address. To prevent bad things happen, call obs.disable()
before returning from the function - that will disarm 以线程安全的方式处理任何未决通知。
* 出于性能原因 - 我们不想在所有通知处理程序执行时阻塞通知中心的其余部分。