PDA

View Full Version : New to QMutex



durbrak
12th March 2009, 18:39
Hello there,

I'm new to the whole Multithreaded programming and I'm having issues.

functions.h

namespace Functions
{
bool existsInDB(int id);
}functions.cpp

#include "functions.h"
#include <QMutex>
#include [...]

QMutex mutex(QMutex::Recursive);

bool Functions::existsInDB(int id)
{
static QList<int> cache;

QMutexLocker lock(&mutex);

if(cached.contains(id))
return true;
else
{
cached.append(id);

QSqlQuery query;
query.prepare("SELECT COUNT(id) FROM customers WHERE id=?;");
query.addBindValue(id);
query.exec();
query.next();

return (query.value(0).toInt() > 0)
}
}

Now I have a subclass of QThread:

void myThread::run()
{
bool exists = Functions::existsInDB(data->id);
if(exists) {...}
}

As you can see it calls existsInDB(). Now in the main-thread (GUI-Thread) there a sometimes also calls to existsInDB() which causes the following errors to occur in the console (can't remember the exact words):

QSqlQuery::value not positioned on a valid row

If I remove the existsInDB() call in the GUI thread the error disappears. If I remove the existsInDB() call in myThread the error also disappears. So I guess the problem is that both threads are trying to access that function at the same time or something but I can't wrap my head around that whole QMutex story and how to make it work? Can someone point me in the right direction?

Thank you.

wysota
12th March 2009, 21:25
You can't use the same database connection from threads other than that where it was created. The design is incorrect - each thread needs its own database connection (and of course the mutex won't be needed anymore).

durbrak
12th March 2009, 21:40
Ahh, thank you wysota. I didn't even know each thread needs its own database connection.
But I don't quite understand how I am supposed to rewrite my code. The function is used by both threads (they share the data in static QList<int> cache;).
And I'm having a little issue understanding - the call to Function::existsInDB() "lives" in the myThread-thread because it was called inside myThread::run()?
How can I rewrite my function so that it works correctly? Passing the QSqlDatabase-pointer on each function call doesn't seem like such a good option.

wysota
12th March 2009, 22:16
Each thread should have its own connection stored in its private storage and when this function is called, it need to use the connection associated with the thread that has called the function. You can "name" threads and store the names as values in a map that is keyed with QThread::currentThread(). You can also "name" connections with the names you have given to threads so that you can retrieve the connection name based on the result of currentThread().