Seite 1 von 1

Multithreaded programmieren mit QWaitCondition

Verfasst: 16. Oktober 2008 13:31
von mnagl
Ist es möglich QWaitCondition.wait() in einer Methode eines Objekts aufzurufen, das von mehreren Threads angesprochen wird, um diese aufrufenden Threads warten zu lassen?

Code: Alles auswählen

class PacDataQueue
{
  public:
    ....
    void enqueue(PacWaveformChunk *w);
    PacWaveformChunk * dequeue()
    {
      mutex.lock();
      waitForData.wait(&mutex);
      if (q.isEmpty())
        return 0;
      return q.dequeue();
      mutex.unlock();
    }
  private:
    QQueue<PacWaveformChunk*> q;
    QMutex mutex;
    QWaitCondition waitForData;
};

PacDataQueue dataqueue;

class PacAnalyzerThread : public QThread
{
    Q_OBJECT
  public:
    ...
    void run()
    {
      PacWaveformChunk *data;
      forever {
        data=dataqueue.dequeue();
        processData(data);
      }
    }
};

Re: Multithreaded programmieren mit QWaitCondition

Verfasst: 16. Oktober 2008 16:47
von Ginsengelf
mnagl hat geschrieben:Ist es möglich QWaitCondition.wait() in einer Methode eines Objekts aufzurufen, das von mehreren Threads angesprochen wird, um diese aufrufenden Threads warten zu lassen?

Code: Alles auswählen

    PacWaveformChunk * dequeue()
    {
     (...)
      return q.dequeue();
      mutex.unlock();
    }
Moin, prinzipiell könnte das funktionieren, Versuch macht kluch, denke ich.
Aber: dein Mutex wird hier nie entsperrt, wenn das return davor kommt. Du könntest hier mit einem QMutexLocker arbeiten, der entsperrt das entsprechende Mutex, wenn der seinen Gültigkeitsbereich verlässt.

Ginsengelf

edit: du kriegst ein Problem, wenn mehrere Threads warten, dann geweckt werden, und jeder dequeue() aufruft, aber weniger Elemente als Threads da sind!

Verfasst: 17. Oktober 2008 14:20
von Superheftig
Der code sollte so aussehen

class PacDataQueue
{
public:
....
void enqueue(PacWaveformChunk *w) {
QMutexLocker locker(&mutex);
while (queue.size() > irgendein Maximum) {
queueFull.wait(&mutex);
}
q.enqueue(w);
waitForData.wakeAll();
}
PacWaveformChunk * dequeue()
{
QMutexLocker locker(&mutex); // Immer nen mutexlocker benutzten - sicherer
while (q.isEmpty()) {
waitForData.wait(&mutex); // Thread schlafen legen falls queue leer ist
}
q.dequeue();
queueFull.wakeAll();
}
private:
QQueue<PacWaveformChunk*> q;
QMutex mutex;
QWaitCondition waitForData;
QWaitCondition queueFull;
};


Damit können jetzt beliebig viele Threads sowohl lesen also auch schreiben ohne deadlocks und fehler in der synchronisation.
Deine Frage versteh ich allerdings nichts so ganz