Based on the previously asked question and the answer found to it, I created a global static mutex, with which I regulate multithreaded access to the static methods of the QSqlDatabase class: addDatabase() , database() and removeDatabase() .
#include <QtCore/QGlobalStatic> #include <QtCore/QMutex> Q_GLOBAL_STATIC(QMutex, _g_mutex) static QSqlDatabase addDatabase(const QString &conn_name) { QMutexLocker locker(_g_mutex); return QSqlDatabase::addDatabase(QLatin1String(DB_DRIVER), conn_name); } static QSqlDatabase database(const QString &conn_name) { QMutexLocker locker(_g_mutex); return QSqlDatabase::database(conn_name, false); } static void closeDatabase(const QString &conn_name) { QSqlDatabase db = database(conn_name); if(db.isValid() && db.isOpen()) db.close(); } static void removeDatabase(const QString &conn_name) { QMutexLocker locker(_g_mutex); QSqlDatabase::removeDatabase(conn_name); } It works without errors, there are no inter-thread conflicts, however, in my opinion, the number of locks executed by the mutex becomes excessive, in my opinion. The fact is that the QSqlDatabase object is implicit shared and is distributed on the stack, and to execute the query to the database, you must first get it. And when a QSqlQuery object is QSqlQuery , it has to call its own static database() method presented above each time. For example:
bool MyDatabase::query(const QString &qstr) { QSqlQuery query(database(connectionName())); if(!query.exec(qstr)) return false; ... return true; } The MyDatabase::query() method is called multithreaded, and from this comes a lot of forced mutex locks, which, in theory, could have been avoided if we had a QSqlDatabase object existing between MyDatabase::query() calls. For example:
class MyDatabase { public: MyDatabase() {} bool query(const QString &qstr); private: QSqlDatabase _db; }; In this case, we get the ideal option, when once we open a connection to the database, we block the mutex for a short time, and then we use the QSqlDatabase object without any locks and related brakes.
But here the problem is again: none of the QSqlDatabase objects associated with a specific database connection should exist immediately before closing the connection itself. The following are examples from Qt Help.
Wrong option:
QSqlDatabase db = QSqlDatabase::database("sales"); QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db); QSqlDatabase::removeDatabase("sales"); ... and correct:
{ QSqlDatabase db = QSqlDatabase::database("sales"); QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db); } QSqlDatabase::removeDatabase("sales"); It turns out that there is no way out except how to create a QSqlDatabase object on the heap so that, when it is no longer needed, it is correctly deleted. But how correct is this option? I think it would be against the idea of using QSqlDatabase . I would appreciate assistance in resolving the current dilemma. It is also possible that there is an alternative path that is not obvious to me.