Я большой поклонник архитектуры отправки сообщений / рассылки сообщений. Это основной метод, который 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;
}
}
Преимущества в том, что вы локализуете свою блокировку. Это огромно. Также до тех пор, пока параметры понимаются как явно новые отправителем и удаляются получателем, вам не нужно беспокоиться о доступе к общей памяти.
Есть много недостатков, латентность одна. Если вам нужно сразу узнать, что что-то изменилось, вам нужно создать эти общие данные и подумать о лучшей схеме блокировки. Если вам действительно нужно глобальное состояние, которое может быть обновлено в любое время с нескольких направлений, то в моей книге хорошо подходит синглтон. Этот дизайн действительно в основном подходит для данных, которые идут в одном направлении, вы можете попасть в условия гонки. Однако вы также можете реализовать блокировку геттеров для проверки одним потоком из другого, но для установки значения, которое вы должны публиковать. Есть много переменных, о которых стоит подумать, но, надеюсь, это поможет вам. Также вы можете забыть удалить параметры в сообщении.
Обновление на основе правки
Исходя из вашей информации, в зависимости от объема данных, публикация может очень хорошо работать. Профилирование вашего кода было бы важно. Если бы я был тобой, я бы поиграл с некоторыми доказательствами концепции и переключился бы на использование условных переменных для управления синхронностью. Если вы работаете на платформе Windows, обязательно используйте их насос сообщений.