2011-11-11 8 views
11

Jaki byłby to dobry sposób, aby rozwiązać następujący problem w Qt:wielowątkowe przetwarzanie danych rurociągu w Qt

Mam klasy czujnika, który ciągle generuje dane. Na tych danych kilka operacji musi zostać przeprowadzonych po drugim, co może zająć dość długo. Do tego mam kilka dodatkowych zajęć. Zasadniczo, za każdym razem, gdy nagrywany jest nowy element danych, pierwsza klasa powinna uzyskać dane, przetworzyć je, przekazać je do następnego itd.

czujnik -> klasa 1 -> ... -> ostatnia klasa

chcę umieścić poszczególne klasy rurociągu do własnych wątków, tak że klasa 1 może już pracować na próbce n +1, gdy klasa 2 przetwarza próbkę n ...

Również, ponieważ poszczególne kroki mogą znacznie różnić się pod względem wydajności (np. Czujnik jest znacznie szybszy niż pozostałe) i nie interesują mnie przestarzałe dane, chcą, aby klasa 1 (i wszystko, co po niej) zawsze otrzymywało najnowsze dane od swojego poprzednika, odrzucając stare dane. Tak więc nie ma dużego bufora między etapami potoku.

Najpierw pomyślałem o używaniu Qt :: QueuedConnections dla sygnałów/gniazd, ale myślę, że to wprowadziłoby kolejkę pełną przestarzałych próbek czekających na przetworzenie przez wolniejsze części potoku?

Odpowiedz

3

To, z czym masz do czynienia, to wzór konsumencki. Ogólny przegląd tego można znaleźć tutaj. http://en.wikipedia.org/wiki/Producer-consumer_problem

Chcesz użyć QMutex, aby ograniczyć dostęp do danych do jednego wątku na raz. Użyj blokady QMutexLocker, aby ją zablokować.

za bardzo uproszczony przykład:

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); 
} 
5

Po prostu zbuduj własną, jednoczęściową klasę "kolejki". Powinien on posiadać:

A piece of data (or pointer to data) 
A Boolean "dataReady" 
A mutex 
A condition variable 

Funkcja "enqueue" to po prostu:

lock mutex 
Replace data with new data 
dataReady = true 
signal condition variable 

Funkcja "rozkolejkowania" to po prostu:

lock mutex 
while (!dataReady) cond_wait(condition, mutex) 
tmpData = data 
data = NULL (or zero) 
dataReady = false 
unlock mutext 
return tmpData 

rodzaju danych może być szablon parametr.