リソースのリストを処理し、結果のアイテムを各リソースのコンテナー (std::map) に配置する場合と配置しない場合があるスレッド化されたアプリケーションを作成しています。リソースの処理は複数のスレッドで行われます。
結果コンテナがトラバースされ、各アイテムは個別のスレッドによって処理されます。このスレッドは、アイテムを受け取り、(mysqlcppconn API を使用して) MySQL データベースを更新し、コンテナからアイテムを削除して続行します。
簡単にするために、ロジックの概要を次に示します。
queueWorker() - thread
getResourcesList() - seeds the global queue
databaseWorker() - thread
commitProcessedResources() - commits results to a database every n seconds
processResources() - thread x <# of processor cores>
processResource()
queueResultItem()
そして、私がやっていることを示すための疑似実装。
/* not the actual stucts, but just for simplicities sake */
struct queue_item_t {
int id;
string hash;
string text;
};
struct result_item_t {
string hash; // hexadecimal sha1 digest
int state;
}
std::map< string, queue_item_t > queue;
std::map< string, result_item_t > results;
bool processResource (queue_item_t *item)
{
result_item_t result;
if (some_stuff_that_doesnt_apply_to_all_resources)
{
result.hash = item->hash;
result.state = 1;
/* PROBLEM IS HERE */
queueResultItem(result);
}
}
void commitProcessedResources ()
{
pthread_mutex_lock(&resultQueueMutex);
// this can take a while since there
for (std::map< string, result_item_t >::iterator it = results.begin; it != results.end();)
{
// do mysql stuff that takes a while
results.erase(it++);
}
pthread_mutex_unlock(&resultQueueMutex);
}
void queueResultItem (result_item_t result)
{
pthread_mutex_lock(&resultQueueMutex);
results.insert(make_pair(result.hash, result));
pthread_mutex_unlock(&resultQueueMutex);
}
processResource() で示されているように、そこに問題があり、commitProcessedResources() が実行されていて、resultQueueMutex がロックされている場合、queueResultItem() が同じミューテックスをロックしようとするため、待機するため、ここで待機します。完了するまで、しばらく時間がかかる場合があります。
実行中のスレッドの数には明らかに制限があるため、すべてのスレッドが queueResultItem() の終了を待機するとすぐに、mutex が解放されて queueResultItem() で使用できるようになるまで、それ以上の作業は行われません。
それで、私の質問は、これを実装するにはどうすればよいですか? 同時に挿入および削除できる特定の種類の標準コンテナはありますか、それとも私が知らない何かが存在しますか?
ここでの std::map の場合のように、各キュー項目が独自の一意のキーを持つことが厳密に必要というわけではありませんが、いくつかのリソースが同じ結果を生成する可能性があり、一意の結果のみを送信することを好むので、私はそれを好みます。INSERT IGNORE を使用して重複を無視する場合でも、データベースに追加します。
私は C++ にかなり慣れていないので、残念ながら Google で何を探すべきかわかりません。:(