2012-02-06 15 views
9

私はコールバック関数のセットを反復処理しています。関数は反復中に呼び出され、関数セットの実際のコンテナに大幅な変更をもたらす可能性があります。変更コンテナの反復

  1. 反復コピー以上のオリジナルセットのコピーを作成しますが、すべての要素のために、それはまだ元のセット

チェックに存在するかどうかをチェックします。

私が今やっていることですすべての要素の存在が超ダイナミックですが、かなり遅いようです。

このケースに取り組む他の提案はありますか?

編集:

// => 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

+0

まあ、私はこの一般的なままにしたかったが、はい、それは標準です:: set –

答えて

4

2つの基本的なアプローチが頭に浮かぶ:ここで実際のコードがある

  1. キューのためにロックコレクション、プッシュタスクとタスクベースのアプローチを(使用すべての関係者を解放して完了するまで待ちます)。タスクが実際に開始しているときに、現在のタスクの要素がコレクションにまだ存在するかどうかを確認する必要があります。

    • これは

  2. (特に作家よりも多くの読者と)fullblown相互排除よりも通常より高速であるチェック用リーダライタロックを活用することができ(私は意味同時データ構造を使用します、明示的なロックなしでマルチスレッドアクセスに適したもの)。

(すぐにリンクを追加すること)、それを行う方法があり

3

:以下のライブラリは、同時のデータ構造の実装が含まれています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*のコレクションを作成し、2パス目でそれらを実行することができます。

3

set構造を突然変異させる操作は、insert()およびerase()である。

反復処理中に、によって返されたイテレータを使用して、を検討してください。 "設定" により、

it = myset.erase(it); 

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

+0

あなたが引用したリンクの意味: void set :: erase(iterator position); –