Многопоточный конвейер обработки данных в 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

Тип данных может быть параметром шаблона.