Link to home
Start Free TrialLog in
Avatar of rkreddy_kbs
rkreddy_kbs

asked on

QWaitCondition

Hello
I want to implement 2 threads (Producer/Consumer) in Qt 4.6.2  that interact with each other using QWaitCondition (i.e., wait/notify meaning T1 does something, notifies T2 and goes to wait again . The thread T2 who until now was waiting, when notified by T1, wakes up, does something and then notifies T1 and so on..)

Is QWaitCondition the right choice or is there something else.. I implemented the code but it gets into some deadlock. Here is my code :-

class DemoApp : public QMainWindow {
    Q_OBJECT
public:
    DemoApp(QWidget *parent = 0);
    ~DemoApp();

    QMutex wmutex, rmutex;

    QWaitCondition permitToWrite;
    QWaitCondition permitToRead;

private:    
    WriterThread *wthread; // this is our writer thread
    ReaderThread *rthread; // this is our reader thread
}

void DemoApp::on_StartButton_clicked()
{
    wthread = new WriterThread(this);
    wthread->start(); 

    rthread = new ReaderThread(this);
    rthread->start(); 

    permitToWrite.wakeAll();
}

//Writer Thread
WriterThread::WriterThread(QObject *parent)
    : QThread(parent)
{

    myParent = (DemoApp*)parent;
}

void WriterThread::run()
{
    while(1){
        {
	  myParent->wmutex.lock();
          myParent->permitToWrite.wait(&myParent->wmutex);
 	  writeSomething();
	  myParent->wmutex.unlock();
	  myParent->permitToRead.wakeAll();
	}
}

//Reader Thread
ReaderThread::ReaderThread(QObject *parent)
    : QThread(parent)
{

    myParent = (DemoApp*)parent;
}

void ReaderThread::run()
{
    while(1){
        {
	  myParent->rmutex.lock();
          myParent->permitToRead.wait(&myParent->rmutex);
 	  readSomething();
	  myParent->rmutex.unlock();
	  myParent->permitToWrite.wakeAll();
	}
}

Open in new window

Avatar of rkreddy_kbs
rkreddy_kbs

ASKER


For most of the iterations, they work correctly as follows :-

The W (writer) writesSomething, unlocks wmutex, wakes Reader, locks wmutex and then waits on permitToWrite.
The reader R is scheduled and it does its sequence as readSomething, unlock rmutex, wakes Writer, lock rmutex and then waits on permitToRead

the above steps repeat but after some time, the sequence gets disturbed as follows :-

The W (writer) writesSomething, unlocks wmutex, wakes Reader.
Now the reader is scheduled
The reader does its sequence as readSomething, unlock rmutex, wakes Writer, lock rmutex and then waits on permitToRead. Note here that the writer has been woken up but it was never waiting.
Now the writer is scheduled and it continues from where it left i.e. unlock wmutex and then waits on permitToWrite and it waits indefinitely here.

So now both reader and writer are waiting indefinitely for their respective permits.

Should I be using the same mutex instead of two mutexes. I tried but it did not work either.. pls advise.
I made the following changes and it seems to be working :-

Firstly use only mutex instead of wmutex and rmutex

void WriterThread::run()
{
    while(1){
        {
	  myParent->mutex.tryLock();
          myParent->permitToWrite.wait(&myParent->mutex);
 	  writeSomething();
	  myParent->permitToRead.wakeAll();
	}
}

void ReaderThread::run()
{
    while(1){
        {
	  myParent->mutex.tryLock();
          myParent->permitToRead.wait(&myParent->mutex);
 	  readSomething();
	  myParent->permitToWrite.wakeAll();
	}
} 

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of HappyCactus
HappyCactus
Flag of Italy image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial