ネットワークスレッドが実行するすべてのフレームの最後に出力オブジェクトが作成されるマルチスレッドフレームワークを実装しようとしています。これにより、別のスレッドがそのフレームの開始時に最新の「完了した出力」ポインターを取得できます。また、出力オブジェクト内に保存されているデータへの安全で完全な読み取り専用アクセスがあることを知っています。
これに対する私の(非常に初期の)アプローチには、主に次のコードブロックが含まれます。
NetworkHandler -
void NetworkHandler::Tick()
{
// Tick on our io_service
m_ios.poll();
// Assemble new output data
this->AssembleOutput();
}
ClientNetworkHandler -
void ClientNetworkHandler::AssembleOutput()
{
std::tr1::shared_ptr<crusade::task::TaskOutput> newOutput(new crusade::task::TaskOutput());
newOutput->m_outputElements["connected"] = std::tr1::shared_ptr<crusade::task::TaskOutputElement>(new NetworkConnectedTaskOutputElement(this->m_isConnected));
this->m_latestOutput.swap(newOutput);
}
PyCruHandler -
void PyCruHandler::Tick()
{
printf("PyCruHandler\n");
// Get any necessary inputs from other threads
m_latestNetworkOutput.swap(crusade::task::THManager::GetInstance()->GetTaskHandler(crusade::task::THManager::TH_NETWORK)->GetLatestOutput());
// Other unrelated processing to go here
}
基本的に、ClientNetworkHandler と PyCruHandler は別々のスレッドで独立して実行されます。PyCruHandler は m_latestNetworkOutput のコピーに対して実際には何もしません。何らかの方法でアクセスされる他のすべてのインスタンスをコメントアウトしましたが、まだ次の問題があります。
両方のスレッドが swap (または同等の operator=) を呼び出せるようにすると、最終的に (通常は実行から 2 秒以内ですが、数分かかることもあります)、オペレーターの新規またはアロケーターの削除のいずれかで次のエラーが発生します。選別:
「ヒープ: 解放された後に 2bab3dc で変更されたヒープ ブロック 2bab3b0 を解放する Windows がブレークポイントをトリガーしました。
これはヒープの破損が原因である可能性があり、これはバグを示しています...など."
私は初心者にすぎませんが、これは、shared_ptr オブジェクト間のスレッドセーフとタイミングに敏感なアクセスの問題に関するある種の問題を示しているようです。ただし、shared_ptr スレッド セーフのニュアンスの説明 (ここと他の場所の両方) に当惑するほど混乱してきました。参照カウントがスレッド セーフであることを示す読み取りがあるため、shared_ptrs をコピーしても安全です (ただし、その内部オブジェクト)。スレッド セーフにはなりません)、その他の読み物は、shared_ptr には有用なスレッド セーフが実質的に存在しないことを示しています。shared_ptrs のスレッド セーフに関するブースト ドキュメントを読みましたが、これが私のコードで問題になるかどうかはまだわかりませんでした。
私の質問は、ここにいる誰かが私がしていることの明らかな欠陥を見つけることができますか? 私の目標は、所有スレッドによってまだ保存されている最新の出力オブジェクトにアクセスできるようにすることです。その後、出力のすべてのユーザーがそれを処理するまで、そのオブジェクトは (所有スレッドが後の出力に移動した後でも) 削除されません。同じように。私の頭の中では、共有ポインターはこれに最適なように思えました...しかし、これに頭をぶつけて3時間後、私は疑問に思い始めています...
事前にどうもありがとうございました。これを誤って投稿した場合はお詫び申し上げます。ここに来るのは初めてで、プロトコルに関する限り、FAQ はかなりのんびりしているように見えました。