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 "qcoreapplication.h"
|
||||||
#include "qreadwritelock.h"
|
#include "qreadwritelock.h"
|
||||||
#include "qsqldriver.h"
|
#include "qsqldriver.h"
|
||||||
|
#include "qsqldriver_p.h"
|
||||||
#include "qsqldriverplugin.h"
|
#include "qsqldriverplugin.h"
|
||||||
#include "qsqlindex.h"
|
#include "qsqlindex.h"
|
||||||
#include "QtCore/qapplicationstatic.h"
|
#include "QtCore/qapplicationstatic.h"
|
||||||
@ -282,6 +283,10 @@ void QSqlDatabasePrivate::disable()
|
|||||||
QSqlDriver. Alternatively, you can subclass your own database
|
QSqlDriver. Alternatively, you can subclass your own database
|
||||||
driver from QSqlDriver. See \l{How to Write Your Own Database
|
driver from QSqlDriver. See \l{How to Write Your Own Database
|
||||||
Driver} for more information.
|
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
|
Create a connection (i.e., an instance of QSqlDatabase) by calling
|
||||||
one of the static addDatabase() functions, where you specify
|
one of the static addDatabase() functions, where you specify
|
||||||
@ -1333,6 +1338,50 @@ QSql::NumericalPrecisionPolicy QSqlDatabase::numericalPrecisionPolicy() const
|
|||||||
return d->precisionPolicy;
|
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
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
QDebug operator<<(QDebug dbg, const QSqlDatabase &d)
|
QDebug operator<<(QDebug dbg, const QSqlDatabase &d)
|
||||||
|
@ -18,6 +18,7 @@ class QSqlIndex;
|
|||||||
class QSqlRecord;
|
class QSqlRecord;
|
||||||
class QSqlQuery;
|
class QSqlQuery;
|
||||||
class QSqlDatabasePrivate;
|
class QSqlDatabasePrivate;
|
||||||
|
class QThread;
|
||||||
|
|
||||||
class Q_SQL_EXPORT QSqlDriverCreatorBase
|
class Q_SQL_EXPORT QSqlDriverCreatorBase
|
||||||
{
|
{
|
||||||
@ -80,6 +81,8 @@ public:
|
|||||||
QString connectionName() const;
|
QString connectionName() const;
|
||||||
void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy);
|
void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy);
|
||||||
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const;
|
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const;
|
||||||
|
bool moveToThread(QThread *targetThread);
|
||||||
|
QThread *currentThread() const;
|
||||||
|
|
||||||
QSqlDriver* driver() const;
|
QSqlDriver* driver() const;
|
||||||
|
|
||||||
|
@ -104,6 +104,8 @@ private slots:
|
|||||||
void infinityAndNan();
|
void infinityAndNan();
|
||||||
void multipleThreads_data() { generic_data(); }
|
void multipleThreads_data() { generic_data(); }
|
||||||
void multipleThreads();
|
void multipleThreads();
|
||||||
|
void moveToThread_data() { generic_data(); }
|
||||||
|
void moveToThread();
|
||||||
|
|
||||||
void db2_valueCacheUpdate_data() { generic_data("QDB2"); }
|
void db2_valueCacheUpdate_data() { generic_data("QDB2"); }
|
||||||
void db2_valueCacheUpdate();
|
void db2_valueCacheUpdate();
|
||||||
@ -2335,5 +2337,32 @@ void tst_QSqlDatabase::multipleThreads()
|
|||||||
QTRY_VERIFY(t.isFinished());
|
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)
|
QTEST_MAIN(tst_QSqlDatabase)
|
||||||
#include "tst_qsqldatabase.moc"
|
#include "tst_qsqldatabase.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user