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>
This commit is contained in:
parent
46ad7fe966
commit
b4c63b89df
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user