【问题标题】:Iterating a changing container迭代一个不断变化的容器
【发布时间】:2012-02-28 06:08:30
【问题描述】:

我正在迭代一组回调函数。函数在迭代过程中被调用,可能会导致函数集的实际容器发生巨大变化。

我现在做的是:

  1. 复制原始集
  2. 遍历副本,但对每个元素检查它是否仍然存在于原始集合中

检查每个元素的存在是超级动态的,但似乎也很慢。

是否有其他建议可以解决此案?

编辑:这是实际代码:

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

【问题讨论】:

  • “设置”是指std::set&lt;&gt;?如果不是,实际的容器类型是什么?
  • 好吧,我想保留这个通用的,但是是的,它是一个 std::set

标签: c++ dynamic iteration


【解决方案1】:

我想到了两种基本方法:

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

    • 这可以利用读写器锁进行检查,这通常比完全互斥更快(尤其是在读者多于作者的情况下)

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

(稍后添加链接)

【讨论】:

    【解决方案2】:

    有一种方法可以分两步完成:首先,通过原始集合,并制作一组操作项。然后遍历操作项集,并将它们应用于原始集。

    操作项是具有子类的基类。每个子类都接受一个集合,并对其执行特定的操作,例如:

    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*s 的集合,并在第二轮中运行它们。

    【讨论】:

      【解决方案3】:

      改变set结构的操作是insert()erase()

      在迭代时,考虑使用变异操作返回的迭代器

      it = myset.erase( it );
      

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

      【讨论】:

      • 你引用的链接说:void set::erase (iterator position);
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 1970-01-01
      相关资源
      最近更新 更多