У меня есть один основной поток, который создает массив объектов класса SlowData
. Этими объектами относительно медленно манипулировать. Вот почему, когда я их изначально загружаю, они заполнены данными заглушки.
Сразу после загрузки каждого объекта в массиве я могу отобразить массив в пользовательском интерфейсе. Параллельно с этим я запускаю вычисления по массиву. Объекту SlowDataComputation
поручено сообщать результаты в пользовательский интерфейс (который, в свою очередь, визуализирует изменение конкретного объекта SlowData
).
Вот как это будет выглядеть:
void main()
{
std::vector<SlowData> aData;
aData.reserve(1000000); // one million instances
Fast_PopulateVector(aData);
DataUi aUi;
SlowDataComputation aCalc;
aCalc.SetUiCallback(aUi); // instruct the object to periodically
// report computation results to the UI
aCalc.Slow_ComputeInSeveralThreads(aData);
aUi.VisualizeInMessageLoop(aData); // message loop that exits upon user signal
if ( aCalc.StillWorking() )
aCalc.Stop(); // terminate threads gradually
// after VisualizeInMessageLoop returns, aData will then be destroyed
}
Я хочу, чтобы SlowDataComputation
запустил несколько потоков, каждый из которых обрабатывал бы определенный сегмент в массиве:
class SlowDataComputation
{
std::vector<SlowData> * myData;
DataUi * myUI;
public:
void Slow_ComputeInSeveralThreads(std::vector<SlowData> & theV)
{
myData = &theV;
size_t aSize = myData->size();
size_t aNumThreads = 10;
size_t aBlockSize = aSize / aNumThreads;
for (size_ti = 0; i < aNumThreads; i++)
{
ComputationThread aThr(myData);
aThr.SetBoundary(i * aBlockSize, (i+1) * aBlockSize);
aThr.SetUiCallback(myUI);
aThr.Run(); // process a given segment in the array
}
}
};
Наконец, вот несколько псевдокодов для пользовательского интерфейса:
class DataUi
{
std::vector<SlowData> * myData;
public:
void VisualizeInMessageLoop()
{
Message aMsg;
while ( HasMessage(aMsg) )
if (aMsg.Code == Message::MSG_PROGRAM_QUIT)
SignalQuit(); // next time, HasMessage will return false
// return from message loop
}
};
Вопрос в : как обезопасить уничтожение SlowData
экземпляров, чтобы, если какой-либо из десяти вычислительных потоков в настоящее время работает с объектом, уничтожение должно ждать пока не завершится каждый из этих вычислительных потоков (либо потому, что он завершил обработку, либо потому, что был вызван метод SlowDataComputation::Stop
)? Какой примитив синхронизации наиболее подходит для этой задачи?
Мне удалось решить эту проблему с помощью одного вычислительного потока. Я использовал Критические Разделы. Но это решение плохо масштабируется для нескольких вычислительных потоков.