Urthas
17th October 2015, 01:39
Hello,
As many of you are probably aware, Qt docs are quite clear about instances of QSqlDatabase and threads:
A connection can only be used from within the thread that created it. Moving connections between threads or creating queries from a different thread is not supported.
After migrating from raw MySQL libraries to a QSql-based approach, my application started behaving oddly. Evidently the raw MySQL does not have the cited constraint: my application indeed uses exactly two threads: the main thread, and a thread that receives sensor data. Under the current implementation, both threads do work with the database.
The following illustrates the current solution to the problem, which takes a lazy-loading approach. Everything appears to work, but I would welcome any and all constructive criticism.
// Controller.h
private:
CustomDatabase * databaseConnectionForThread(const Qt::HANDLE threadID = QThread::currentThreadId());
QHash<Qt::HANDLE, CustomDatabase *> dbConnectionsByThread;
QMutex threadMutex, sqlMutex;
// Controller.cpp
CustomDatabase * Controller::databaseConnectionForThread(const Qt::HANDLE threadID) {
QMutexLocker locker(&threadMutex);
static int numberForConnectionName = 0;
CustomDatabase *dbConnection;
if (dbConnectionsByThread.contains(threadID))
dbConnection = dbConnectionsByThread.value(threadID);
else {
dbConnection = CustomDatabase::create(QString::number(++numberFor ConnectionName), this); // create() initializes and opens the connection it returns
if (!dbConnection->isOpen())
exitWithError(QString("Controller::databaseConnectionForThread() - Failed: %1!").arg(dbConnection->lastError()));
dbConnectionsByThread.insert(threadID, dbConnection);
}
return dbConnection;
}
void Controller::doStuffWithDatabase() {
QMutexLocker locker(&sqlMutex);
CustomDatabase *dbConnection = databaseConnectionForThread();
// do stuff
}
Thank you very much for your time.
As many of you are probably aware, Qt docs are quite clear about instances of QSqlDatabase and threads:
A connection can only be used from within the thread that created it. Moving connections between threads or creating queries from a different thread is not supported.
After migrating from raw MySQL libraries to a QSql-based approach, my application started behaving oddly. Evidently the raw MySQL does not have the cited constraint: my application indeed uses exactly two threads: the main thread, and a thread that receives sensor data. Under the current implementation, both threads do work with the database.
The following illustrates the current solution to the problem, which takes a lazy-loading approach. Everything appears to work, but I would welcome any and all constructive criticism.
// Controller.h
private:
CustomDatabase * databaseConnectionForThread(const Qt::HANDLE threadID = QThread::currentThreadId());
QHash<Qt::HANDLE, CustomDatabase *> dbConnectionsByThread;
QMutex threadMutex, sqlMutex;
// Controller.cpp
CustomDatabase * Controller::databaseConnectionForThread(const Qt::HANDLE threadID) {
QMutexLocker locker(&threadMutex);
static int numberForConnectionName = 0;
CustomDatabase *dbConnection;
if (dbConnectionsByThread.contains(threadID))
dbConnection = dbConnectionsByThread.value(threadID);
else {
dbConnection = CustomDatabase::create(QString::number(++numberFor ConnectionName), this); // create() initializes and opens the connection it returns
if (!dbConnection->isOpen())
exitWithError(QString("Controller::databaseConnectionForThread() - Failed: %1!").arg(dbConnection->lastError()));
dbConnectionsByThread.insert(threadID, dbConnection);
}
return dbConnection;
}
void Controller::doStuffWithDatabase() {
QMutexLocker locker(&sqlMutex);
CustomDatabase *dbConnection = databaseConnectionForThread();
// do stuff
}
Thank you very much for your time.