2012-02-06 92 views
9

我正在遍历一组回调函数。在迭代过程中调用函数,并可能导致函数集的实际容器发生剧烈变化。迭代更换容器

我现在正在做的是:

  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); 
     } 
    }; 
+0

通过 “设置” 你的意思是'的std ::设为<>'?如果不是,那么实际的容器类型是什么? – ildjarn 2012-02-06 19:04:10

+0

嗯,我想离开这个泛型,但是,是的,它是一个std :: set – 2012-02-06 19:08:26

回答

4

的两种基本方法来记:

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

    • 这可以利用的检查,这通常比茂盛的互斥更快的读写锁(尤其是比作家更多的读者)

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

(添加链接不久)

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*个集合,并在第二次运行它们。

3

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

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

it = myset.erase(it); 

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

+0

你引用的链接说: void set :: erase(iterator position); – 2012-02-07 18:24:45