Многопоточный конвейер обработки данных в Qt
Что было бы хорошим способом решить следующую проблему в Qt:
У меня есть класс датчиков, который непрерывно производит данные. По этим данным несколько операций должны выполняться за другим, что может занять довольно много времени. Для этого у меня есть несколько дополнительных классов. В принципе, каждый раз, когда записывается новый элемент данных, первый класс должен получать данные, обрабатывать их, передавать их в следующий и т.д.
sensor → class 1 → ... → last class
Я хочу поместить отдельные классы конвейера в свои собственные потоки, так что класс 1 уже может работать с образцом n + 1, когда класс 2 обрабатывает образец n...
Кроме того, поскольку отдельные этапы могут значительно отличаться по производительности (например, датчик быстрее, чем остальные), и мне не нужны устаревшие данные, я хочу, чтобы класс 1 (и все после него) всегда получал новейшие данные от их предшественника, отбрасывающие старые данные. Таким образом, нет большого буфера между этапами конвейера.
Сначала я подумал об использовании Qt:: QueuedConnections для сигналов/слотов, но я предполагаю, что это приведет к появлению очереди с устаревшими образцами, ожидающими обработки более медленными частями конвейера?
Ответы
Ответ 1
То, с чем вы имеете дело, - образец потребителя-производителя. Вы можете найти общий обзор этого здесь. http://en.wikipedia.org/wiki/Producer-consumer_problem
Вы хотите использовать QMutex для ограничения доступа к данным в один поток за раз. Используйте QMutexLocker, чтобы заблокировать его.
Для ОЧЕНЬ упрощенного примера:
QList<quint32> data;
QMutex mutex;
// Consumer Thread calls this
int GetData()
{
quint32 result(-1); // if =1 is a valid value, you may have to return a bool and
// get the value through a reference to an int
// in the parameter list.
QMutexLocker lock(&mutex);
if (data.size())
{
result = data.front(); // or back
data.clear();
}
return result;
}
// Producer Thread calls this
void SetData(quint32 value)
{
QMutexLocker lock(&mutex);
data.push_back(value);
}
Ответ 2
Просто создайте собственный одноэлементный класс "queue". Он должен иметь:
A piece of data (or pointer to data)
A Boolean "dataReady"
A mutex
A condition variable
Функция "enqueue":
lock mutex
Replace data with new data
dataReady = true
signal condition variable
Функция "dequeue" справедлива:
lock mutex
while (!dataReady) cond_wait(condition, mutex)
tmpData = data
data = NULL (or zero)
dataReady = false
unlock mutext
return tmpData
Тип данных может быть параметром шаблона.