私は、メッセージ投稿/メッセージ ポンプ アーキテクチャの大ファンです。これは、スレッド間でデータを通信するために MFC/Win32 が提供する主な方法です。このアーキテクチャはスレッド メッセージからイベント駆動されるため、受信スレッドがスレッド メッセージを処理している場合、スレッド間の通信用に明示的に新しく作成されたデータを処理しています (以下の例を参照)。
これを自分で実装し、ロックを各スレッドのスレッド メッセージの個別のリストにローカライズできます。したがって、あるスレッドが別のスレッドにメッセージを送信したい場合は、おおよそ次のようにします。
PostThreadMessage(msg, void* param, int paramSize)
{
lock(msgQueueLock);
// may wish to copy param
char paramCpy = malloc
msgQueue.Queue(msg, pparam, paramSize);
unlock(msgQueueLock);
}
スレッドのメインループはただ
// thread's msg pump
while (1)
{
// can also use condition var to wait for queue to change...
lock(msgQueueLock);
HandleMsgLocally(msgQueue.Deque())
unlock(msgQueueLock);
}
とにかく、MVC に戻ると、モデルで何かが変更された場合、ビューに投稿して特定のフィールドを更新することができます。
// Well known msg name
int msgName = MODEL_FIELD_A_UPDATED
...
void Model::UpdateFieldA(int newVal)
{
int* valToCommunicate = new int(newVal)
PostThreadMessage(MODEL_FIELD_A_UPDATED, valToCommunicate, sizeof(int))
}
...
void HandleMsgLocally(...void * param,)
{
if (msg == MODEL_FIELD_A_UPDATED)
{
int* val = reinterpret_cast<int*>(param);
//... process param
delete val;
}
}
利点は、ロックをローカライズできることです。これは巨大です。また、パラメーターが送信者によって明示的に新規作成され、受信者によって削除されることが理解されている限り、共有メモリへのアクセスについて心配する必要はありません。
これには多くの欠点がありますが、レイテンシーはその 1 つです。何かが変わったことをすぐに知る必要がある場合は、実際にその共有データを作成し、最適なロック スキームを考える必要があります。複数の方向からいつでも更新できるグローバルな状態が本当に必要な場合は、この場合、私の本ではシングルトンで問題ありません。この設計は、一方向のデータに最も適しています。競合状態になる可能性があります。ただし、あるスレッドから別のスレッドへのインスペクション用にロッキング ゲッターを実装することもできますが、投稿する値を設定する必要があります。考えるべき変数はたくさんありますが、うまくいけば、これがあなたの助けになるでしょう。また、メッセージ内のパラメーターを削除するのを忘れることがあります。
編集に基づいて更新
あなたの情報に基づいて、データの量に応じて、投稿は非常にうまくいく可能性があります。コードのプロファイリングは重要です。私があなただったら、いくつかの概念実証を試して、条件変数を使用して同期性を管理することに切り替えます。Windows プラットフォームを使用している場合は、必ずメッセージ ポンプを使用してください。