2011-01-11 6 views
1

私はオブジェクトのポインタを格納するunordered_mapのunordered_mapを持っています。順序付けられていないマップは、複数のスレッドによって共有されています。私は各オブジェクトを反復し、時間のかかる操作(ネットワークなどを介して送信するなど)を実行する必要があります。 unordered_mapをロックして、それが長時間ブロックされないようにするにはどうすればよいですか?ロック内のSTLコンテナで時間のかかる操作を実行する

typedef std::unordered_map<string, classA*>MAP1; 
typedef std::unordered_map<int, MAP1*>MAP2; 
MAP2 map2; 
pthread_mutex_lock(&mutexA) //how could I lock the maps? Could I reduce the lock granularity? 
for(MAP2::iterator it2 = map2.begin; it2 != map2.end; it2++) 
{ 
    for(MAP1::iterator it1 = *(it2->second).begin(); it1 != *(it2->second).end(); it1++) 
    { 
    //perform some time consuming operation on it1->second eg 
    sendToNetwork(*(it1->second)); 
    } 
} 
pthread_mutex_unlock(&mutexA) 

答えて

0

リストのような他の構造にこれらのオブジェクトをすべて格納し、マップをロックする必要がないように反復することができます。

データのコピーを作成してコピーで作業することもできます。この方法で、コピーの作業中にマップを変更できます。

0

あなたの質問に具体的に対応するdr dobbsのarticle by herb sutterをご覧ください。

一般的な考え方は、リソースをカプセル化するオブジェクトの内部にスレッドを持つことです。スレッドはリソース上でアクションを実行する要求を受け入れ、呼び出し元が要求をプッシュしてから実行し、内部スレッドに要求を実行させます。

また、pthreadの代わりにboost.threadを直接使用することをお勧めしますが、それははるかに苦痛です。

0

通常、長い間ミューテックスを保持するのは良い方法ではありません。すでにここで言及している共通のアプローチは、ワーカースレッドのオブジェクトを読み込んで処理するオブジェクトキューを持つことです。

std::vector<MAP1*> map1Queue; 
pthread_mutex_lock(&mutexA); 
for(MAP2::iterator it2 = map2.begin; it2 != map2.end; ++it2) { 
    map1Queue.push_back(it2->second); 
} 
pthread_mutex_unlock(&mutexA); 
// Now you can process objects from map1Queue in worker thread 

唯一の問題は、あなたがMAP1 *はまだであることを保証する必要がある:あなたの例mutexAで

あなたはこのような何かを行うことができ、あなたはそれを反復している間に変更されることからMAP2を保護しています有効で、おそらくraw_pointersの代わりにboos :: shared_ptrを使用します。

+0

ロック解除後にmap2アイテムの一部が消去されるとどうなりますか? – 9dan

+0

あなたの例では、MAP2とMAP1の関係はMAP2にMAP1要素のポインタが含まれているため、MAP2要素の削除によってMAP1要素が削除されないことに注意してください。 – Ismael