循环期间更改订阅的发布者/订阅者

问题描述

| 这更多是我的一般设计查询。我通过维护订户列表实现了一种发布/订阅模式。当要发布的事件发生时,我会遍历订阅者,并将事件依次推送到每个订阅者。 当由于该出版物,软件深度的某个地方,另一个组件或所描述的组件决定退订自己的事件而发生我的问题。这样做会使我的迭代器无效,并导致崩溃。 解决此问题的最佳方法是什么?我一直在考虑将整个发布循环包装到try catch块中,但这意味着某些订阅者会错过某人取消订阅的特定订阅,这似乎有点过头了。然后我尝试将其反馈给我将void publish调用转换为bool publish调用,该调用在订阅者想要删除时返回true,这种情况适用于这种情况,但如果另一个订阅者取消订阅则不然。然后,我考虑在某个地方“高速缓存”取消订阅请求,并在循环完成后释放它们,但这似乎有点过头了。然后,我考虑将迭代器存储为类成员,以便可以从外部操作迭代器,但这会造成混乱(例如,您取消订阅者1的订阅,迭代器指向2,而容器是向量-那么迭代器将必须减少)。我认为我可能更喜欢后两种解决方案之一,但两者似乎都不理想。 这是个常见的问题吗?有没有更优雅的解决方案?     

解决方法

您可以在发布期间禁止订阅操作,或者可以使用适当的数据结构来保存您的订阅列表,或同时使用两者。 假设您将订户保持在“ 0”,则可以这样运行循环:
for(iterator_type it = subs.begin(); it != subs.end(); ) {
    iterator_type next = it;
    ++next;
    it->notifier();
    it = next;
}
这样,如果当前项被删除,则
next
中仍然有一个有效的迭代器。当然,在发布过程中,您仍然不允许任意删除(如果删除了“ 2”,该怎么办?)。 要允许任意删除,请将一个项目标记为无效,然后将其列表删除推迟到安全为止:
... 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);
    

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...