diff options
author | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2023-02-12 20:09:16 +0100 |
---|---|---|
committer | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2024-04-25 08:27:21 +0200 |
commit | b4c63b89dfe136d0579bf1b6422c4d878cdd74ab (patch) | |
tree | 6b45d551222abfe9d742674fd13c9d4903d8c8c4 | |
parent | 46ad7fe966f6c191ff2123e95c3b6373f7b24287 (diff) |
QSqlDatabase: add moveToThread()/currentThread()
Add QSqlDatabase::moveToThread() to be able to move the driver instance
to another thread.
[ChangeLog][Sql][QSqLDatabase] QSqlDatabase gained two new functions
moveToThread() and currentThread() to be able to use it in another
thread than the one it was created in.
Fixes: QTBUG-39957
Change-Id: I9cb51358f73a3a2fa72813bfdbe059279d388bd7
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/sql/kernel/qsqldatabase.cpp | 49 | ||||
-rw-r--r-- | src/sql/kernel/qsqldatabase.h | 3 | ||||
-rw-r--r-- | tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp | 29 |
3 files changed, 81 insertions, 0 deletions
diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 81c0aeec03..fdbb16a589 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -7,6 +7,7 @@ #include "qcoreapplication.h" #include "qreadwritelock.h" #include "qsqldriver.h" +#include "qsqldriver_p.h" #include "qsqldriverplugin.h" #include "qsqlindex.h" #include "QtCore/qapplicationstatic.h" @@ -282,6 +283,10 @@ void QSqlDatabasePrivate::disable() QSqlDriver. Alternatively, you can subclass your own database driver from QSqlDriver. See \l{How to Write Your Own Database Driver} for more information. + A QSqlDatabase instance must only be accessed by the thread it + was created in. Therefore you have to make sure to create them + in the correct context. Alternatively you can change the context + with QSqlDatabase::moveToThread(). Create a connection (i.e., an instance of QSqlDatabase) by calling one of the static addDatabase() functions, where you specify @@ -1333,6 +1338,50 @@ QSql::NumericalPrecisionPolicy QSqlDatabase::numericalPrecisionPolicy() const return d->precisionPolicy; } +/*! + \since 6.8 + + Changes the thread affinity for QSqlDatabase and its associated driver. + This function returns \c true when the function succeeds. Event processing + will continue in the \a targetThread. + + During this operation you have to make sure that there is no QSqlQuery + bound to this instance otherwise the QSqlDatabase will not be moved to + the given thread and the function returns \c false. + + Since the associated driver is derived from QObject, all constraints for + moving a QObject to another thread also apply to this function. + + \sa QObject::moveToThread(), {Threads and the SQL Module} +*/ +bool QSqlDatabase::moveToThread(QThread *targetThread) +{ + if (auto drv = driver()) { + if (drv != QSqlDatabasePrivate::shared_null()->driver) { + // two instances are alive - the one here and the one in dbDict() + if (d->ref.loadRelaxed() > 2) { + qWarning("QSqlDatabasePrivate::moveToThread: connection '%ls' is still in use " + "in the current thread.", qUtf16Printable(d->connName)); + return false; + } + return drv->moveToThread(targetThread); + } + } + return false; +} + +/*! + \since 6.8 + + Returns a pointer to the associated QThread instance. +*/ +QThread *QSqlDatabase::currentThread() const +{ + if (auto drv = driver()) + return drv->thread(); + return nullptr; +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QSqlDatabase &d) diff --git a/src/sql/kernel/qsqldatabase.h b/src/sql/kernel/qsqldatabase.h index 10019c7d5c..5059dbba83 100644 --- a/src/sql/kernel/qsqldatabase.h +++ b/src/sql/kernel/qsqldatabase.h @@ -18,6 +18,7 @@ class QSqlIndex; class QSqlRecord; class QSqlQuery; class QSqlDatabasePrivate; +class QThread; class Q_SQL_EXPORT QSqlDriverCreatorBase { @@ -80,6 +81,8 @@ public: QString connectionName() const; void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy); QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const; + bool moveToThread(QThread *targetThread); + QThread *currentThread() const; QSqlDriver* driver() const; diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp index 1b762abc68..19afacf6f9 100644 --- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp @@ -104,6 +104,8 @@ private slots: void infinityAndNan(); void multipleThreads_data() { generic_data(); } void multipleThreads(); + void moveToThread_data() { generic_data(); } + void moveToThread(); void db2_valueCacheUpdate_data() { generic_data("QDB2"); } void db2_valueCacheUpdate(); @@ -2335,5 +2337,32 @@ void tst_QSqlDatabase::multipleThreads() QTRY_VERIFY(t.isFinished()); } +void tst_QSqlDatabase::moveToThread() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + auto clonedDb = QSqlDatabase::cloneDatabase(db, "clonedDb"); + auto mainThread = QThread::currentThread(); + CHECK_DATABASE(db); + QCOMPARE(db.currentThread(), mainThread); + QCOMPARE(clonedDb.currentThread(), mainThread); + std::unique_ptr<QThread> t(QThread::create([&] { + db.moveToThread(mainThread); + QThread::currentThread()->exit(); + })); + db.moveToThread(t.get()); + QCOMPARE(db.currentThread(), t.get()); + QCOMPARE(clonedDb.currentThread(), mainThread); + t->start(); + QTRY_VERIFY(t->isRunning()); + QTRY_VERIFY(t->wait(30000)); + QCOMPARE(db.currentThread(), mainThread); + QCOMPARE(clonedDb.currentThread(), mainThread); + db = QSqlDatabase(); + clonedDb = QSqlDatabase(); + QSqlDatabase::removeDatabase("clonedDb"); +} + + QTEST_MAIN(tst_QSqlDatabase) #include "tst_qsqldatabase.moc" |