迭代一个不断变化的容器

时间:2012-02-06 19:02:40

标签: c++ dynamic iteration

我正在迭代一组回调函数。函数在迭代期间被调用,并可能导致函数集的实际容器发生剧烈变化。

我现在正在做的是:

  1. 制作原始集
  2. 的副本
  3. 迭代复制,但是对于每个元素检查它是否仍然存在于原始集合中
  4. 检查每个元素的存在是超级动态的,但似乎也很慢。

    还有其他建议可以解决这个问题吗?

    编辑:这是实际代码:

        // => 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);
            }
        };
    

3 个答案:

答案 0 :(得分:4)

我想到了两种基本方法:

  1. 使用基于任务的方法(将集合锁定,将任务推送到每个元素的队列中,然后释放所有各方以进行工作并等待完成)。在任务实际启动时,您仍然需要检查当前任务的元素是否仍然存在于当前任务中/当前任务中。

    • 这可以利用读写器锁进行检查,这通常比完全相互排斥更快(特别是读者多于作者)

  2. 使用并发数据结构(我的意思是,一个适用于没有显式锁定的多线程访问)。以下库包含并发数据结构的实现:

  3. (稍后添加链接)

答案 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 );

http://www.cplusplus.com/reference/stl/set/erase/