Question

I am having some trouble resolving a race condition that arises when acquiring a lock. I have a large computation that is triggered asynchronously. I need my previous synchronous task to end before the large task begins. The large task launches and waits on a condition variable and, in an ideal world, the small tasks will notify the condition variable when they are done. My problem comes from the large task starting too soon, and the small tasks trigger a condition variable that has yet to full initialize and thus does not actually trigger, causing the program to be locked.

I have boiled it down to this minimal example.

I would assume this is a common problem. How can I check that my condition variable has actually got hold of a mutex and is locked?

#include <QCoreApplication>
#include <QObject>
#include <QFuture>
#include <QtConcurrent/QtConcurrent>
#include <QFutureWatcher>
#include <QWaitCondition>

class workUnit: public QObject
{
    Q_OBJECT

    public:
    workUnit(QObject *parent)
    {
        m = new QMutex();
        m->lock();
        w=new QWaitCondition();
    }
    QWaitCondition* w;
    QMutex* m;

public slots:
    void runMe()
    {
        w->wait(m);
        m->unlock();
        //perform long computation
    }
};


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    workUnit* mUnit=new workUnit(&a);
    QFutureWatcher<void> w;
    QObject::connect(&w, SIGNAL(finished()), &a, SLOT(quit()));
    QFuture<void> f = QtConcurrent::run(mUnit,&workUnit::runMe);
    w.setFuture(f);
    _sleep(1000);//with this delay it works, without the delay it doesn't
    mUnit->w->wakeAll();//This would be triggered by another process
    return a.exec();
}
Was it helpful?

Solution

The documentation for QWaitCondition::wait states that:

The mutex must be initially locked by the calling thread.

You should remove m->lock(); from the constructor and put it in the runMe() function before the call to wait.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top