我正在迭代一组回调函数。函数在迭代期间被调用,并可能导致函数集的实际容器发生剧烈变化。
我现在正在做的是:
检查每个元素的存在是超级动态的,但似乎也很慢。
还有其他建议可以解决这个问题吗?
编辑:这是实际代码:
// => i = event id
template <class Param>
void dispatchEvent(int i, Param param) {
EventReceiverSet processingNow;
const EventReceiverSet& eventReceiverSet = eventReceiverSets[i];
std::copy(eventReceiverSet.begin(), eventReceiverSet.end(), std::inserter(processingNow, processingNow.begin()));
while (!processingNow.empty()) {
EventReceiverSet::iterator it = processingNow.begin();
IFunction<>* function = it->getIFunction(); /// get function before removing iterator
processingNow.erase(it);
// is EventReceiver still valid? (may have been removed from original set)
if (eventReceiverSet.find(ERWrapper(function)) == eventReceiverSet.end()) continue; // not found
function->call(param);
}
};
答案 0 :(得分:4)
我想到了两种基本方法:
使用基于任务的方法(将集合锁定,将任务推送到每个元素的队列中,然后释放所有各方以进行工作并等待完成)。在任务实际启动时,您仍然需要检查当前任务的元素是否仍然存在于当前任务中/当前任务中。
使用并发数据结构(我的意思是,一个适用于没有显式锁定的多线程访问)。以下库包含并发数据结构的实现:
(稍后添加链接)
答案 1 :(得分:3)
有一种方法可以分两步完成:首先,浏览原始集,然后制作一组操作项。然后浏览一组操作项,并将它们应用到原始集。
操作项是具有子类的基类。每个子类都接受一个集合,并对其执行特定操作,例如:
struct set_action {
virtual void act(std::set<int> mySet) const;
};
class del_action : public set_action {
private:
int item;
public:
del_action(int _item) : item(_item) {}
virtual void act(std::set<int> mySet) const {
// delete item from set
}
};
class upd_action : public set_action {
private:
int from, to;
public:
upd_action(int _from, int _to) : from(_from), to(_to) {}
virtual void act(std::set<int> mySet) const {
// delete [from], insert [to]
}
};
现在你可以在第一遍中创建set_action*
的集合,并在第二遍中运行它们。
答案 2 :(得分:3)
改变set
结构的操作是insert()
和erase()
。
迭代时,请考虑使用变异操作返回的迭代器。
it = myset.erase( it );