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;
// Controller.h
private:
CustomDatabase * databaseConnectionForThread(const Qt::HANDLE threadID = QThread::currentThreadId());
QHash<Qt::HANDLE, CustomDatabase *> dbConnectionsByThread;
QMutex threadMutex, sqlMutex;
To copy to clipboard, switch view to plain text mode
// Controller.cpp
CustomDatabase * Controller::databaseConnectionForThread(const Qt::HANDLE threadID) {
static int numberForConnectionName = 0;
CustomDatabase *dbConnection;
if (dbConnectionsByThread.contains(threadID))
dbConnection = dbConnectionsByThread.value(threadID);
else {
dbConnection
= CustomDatabase
::create(QString::number(++numberForConnectionName
),
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() {
CustomDatabase *dbConnection = databaseConnectionForThread();
// do stuff
}
// 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(++numberForConnectionName), 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
}
To copy to clipboard, switch view to plain text mode
Thank you very much for your time.
Bookmarks