gpt4 book ai didi

c++ - 在循环期间更改订阅的发布者/订阅者

转载 作者:太空宇宙 更新时间:2023-11-04 12:18:58 26 4
gpt4 key购买 nike

这更像是我的一般设计查询。我通过维护订阅者列表实现了发布/订阅模式。当要发布的事件发生时,我会遍历订阅者并将事件依次推送给每个订阅者。

我的问题发生在由于该出版物、软件深度的某个地方、另一个组件或事件所描述的组件决定自行取消订阅时。通过这样做,他们使我的迭代器无效并导致崩溃。

解决这个问题的最佳方法是什么?我一直在考虑将整个发布循环包装到一个 try catch block 中,但这意味着一些订阅者会错过某人取消订阅的特定订阅,而且似乎有点过头了。然后我试着把它喂回去,例如我将 void publish 调用变成了 bool publish 调用,当订阅者想要删除时返回 true,这适用于这种情况,但如果另一个订阅者取消订阅则不行。然后我想在某处“缓存”取消订阅请求并在循环完成时释放它们,但这似乎有点过分。然后我在考虑将迭代器存储为类成员,这样我就可以从外部操作迭代器,但这会变得困惑(假设您取消订阅订阅者 1,迭代器指向 2,并且容器是一个 vector - 然后是迭代器必须递减)。我想我可能更喜欢后两种解决方案中的一种,但两者似乎都不理想。

这是一个常见问题吗?有没有更优雅的解决方案?

最佳答案

您可以在发布期间禁止订阅操作,或者您可以使用适当的数据结构来保存您的订阅列表,或者两者兼而有之。

假设您将订阅者保存在 std::list 中,您可以这样运行循环:

for(iterator_type it = subs.begin(); it != subs.end(); ) {
iterator_type next = it;
++next;
it->notifier();
it = next;
}

那样的话,如果当前项被删除,您在next 中仍然有一个有效的迭代器。当然,您仍然不能允许在发布期间任意删除(如果 next 被删除怎么办?)。

要允许任意删除,将项目标记为无效并推迟其列表删除,直到这样做是安全的:

... publication loop ...
dontRemoveItems = true;
for(iterator_type it = subs.begin(); it != subs.end(); ++it) {
if(it->valid)
it->notifier();
}
std::erase(std::remove_if(...,, IsNotValid),...);
dontRemoveItems = false;

别处,

... removal code:
if(dontRemoveItems) item->valid = false;
else subs.erase(item);

关于c++ - 在循环期间更改订阅的发布者/订阅者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6139753/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com