diff options
-rw-r--r-- | src/corelib/thread/qthreadpool.cpp | 37 | ||||
-rw-r--r-- | src/corelib/thread/qthreadpool.h | 9 | ||||
-rw-r--r-- | src/corelib/thread/qthreadpool_p.h | 13 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp | 92 |
4 files changed, 120 insertions, 31 deletions
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index 6d258af9df..b1f538fa43 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -163,7 +163,7 @@ void QThreadPoolThread::registerThreadInactive() /* \internal */ -QThreadPoolPrivate:: QThreadPoolPrivate() +QThreadPoolPrivate::QThreadPoolPrivate() { } bool QThreadPoolPrivate::tryStart(QRunnable *task) @@ -223,10 +223,8 @@ void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority) int QThreadPoolPrivate::activeThreadCount() const { - return (allThreads.count() - - expiredThreads.count() - - waitingThreads.count() - + reservedThreads); + return int(allThreads.count() - expiredThreads.count() - waitingThreads.count() + + reservedThreads); } void QThreadPoolPrivate::tryToStartMoreThreads() @@ -605,11 +603,15 @@ int QThreadPool::expiryTimeout() const void QThreadPool::setExpiryTimeout(int expiryTimeout) { Q_D(QThreadPool); - if (d->expiryTimeout == expiryTimeout) - return; d->expiryTimeout = expiryTimeout; } +QBindable<int> QThreadPool::bindableExpiryTimeout() +{ + Q_D(QThreadPool); + return &d->expiryTimeout; +} + /*! \property QThreadPool::maxThreadCount \brief the maximum number of threads used by the thread pool. @@ -631,11 +633,18 @@ void QThreadPool::setMaxThreadCount(int maxThreadCount) Q_D(QThreadPool); QMutexLocker locker(&d->mutex); - if (maxThreadCount == d->maxThreadCount) - return; - + const auto maxThreadCountChanged = maxThreadCount != d->maxThreadCount; + // Rewrite the value in any case, to make sure the binding is cleared. d->maxThreadCount = maxThreadCount; - d->tryToStartMoreThreads(); + + if (maxThreadCountChanged) + d->tryToStartMoreThreads(); +} + +QBindable<int> QThreadPool::bindableMaxThreadCount() +{ + Q_D(QThreadPool); + return &d->maxThreadCount; } /*! \property QThreadPool::activeThreadCount @@ -698,6 +707,12 @@ uint QThreadPool::stackSize() const return d->stackSize; } +QBindable<uint> QThreadPool::bindableStackSize() +{ + Q_D(QThreadPool); + return &d->stackSize; +} + /*! Releases a thread previously reserved by a call to reserveThread(). diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h index a559eff49a..3e601dd963 100644 --- a/src/corelib/thread/qthreadpool.h +++ b/src/corelib/thread/qthreadpool.h @@ -56,10 +56,10 @@ class Q_CORE_EXPORT QThreadPool : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QThreadPool) - Q_PROPERTY(int expiryTimeout READ expiryTimeout WRITE setExpiryTimeout) - Q_PROPERTY(int maxThreadCount READ maxThreadCount WRITE setMaxThreadCount) + Q_PROPERTY(int expiryTimeout READ expiryTimeout WRITE setExpiryTimeout BINDABLE bindableExpiryTimeout) + Q_PROPERTY(int maxThreadCount READ maxThreadCount WRITE setMaxThreadCount BINDABLE bindableMaxThreadCount) Q_PROPERTY(int activeThreadCount READ activeThreadCount) - Q_PROPERTY(uint stackSize READ stackSize WRITE setStackSize) + Q_PROPERTY(uint stackSize READ stackSize WRITE setStackSize BINDABLE bindableStackSize) friend class QFutureInterfaceBase; public: @@ -76,14 +76,17 @@ public: int expiryTimeout() const; void setExpiryTimeout(int expiryTimeout); + QBindable<int> bindableExpiryTimeout(); int maxThreadCount() const; void setMaxThreadCount(int maxThreadCount); + QBindable<int> bindableMaxThreadCount(); int activeThreadCount() const; void setStackSize(uint stackSize); uint stackSize() const; + QBindable<uint> bindableStackSize(); void reserveThread(); void releaseThread(); diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h index 4d73a480b5..019f24ce4d 100644 --- a/src/corelib/thread/qthreadpool_p.h +++ b/src/corelib/thread/qthreadpool_p.h @@ -58,6 +58,7 @@ #include "QtCore/qset.h" #include "QtCore/qqueue.h" #include "private/qobject_p.h" +#include "private/qproperty_p.h" QT_REQUIRE_CONFIG(thread); @@ -173,11 +174,17 @@ public: QList<QueuePage *> queue; QWaitCondition noActiveThreads; - int expiryTimeout = 30000; - int maxThreadCount = QThread::idealThreadCount(); + Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QThreadPoolPrivate, int, expiryTimeout, 30000) + + void setMaxThreadCount(int count) { q_func()->setMaxThreadCount(count); } + Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QThreadPoolPrivate, int, maxThreadCount, + &QThreadPoolPrivate::setMaxThreadCount, + QThread::idealThreadCount()) + int reservedThreads = 0; int activeThreads = 0; - uint stackSize = 0; + + Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QThreadPoolPrivate, uint, stackSize, 0) }; QT_END_NAMESPACE diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index 5960ac20a3..00c8a84ca7 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -104,8 +104,23 @@ private slots: void stressTest(); void takeAllAndIncreaseMaxThreadCount(); void waitForDoneAfterTake(); + void bindings(); private: + class WaitingTask : public QRunnable + { + public: + QSemaphore waitForStarted, waitToFinish; + + WaitingTask() { setAutoDelete(false); } + + void run() override + { + waitForStarted.release(); + waitToFinish.acquire(); + } + }; + QMutex m_functionTestMutex; }; @@ -471,20 +486,6 @@ void tst_QThreadPool::setMaxThreadCount() void tst_QThreadPool::setMaxThreadCountStartsAndStopsThreads() { - class WaitingTask : public QRunnable - { - public: - QSemaphore waitForStarted, waitToFinish; - - WaitingTask() { setAutoDelete(false); } - - void run() override - { - waitForStarted.release(); - waitToFinish.acquire(); - } - }; - QThreadPool threadPool; threadPool.setMaxThreadCount(1); @@ -1305,5 +1306,68 @@ void tst_QThreadPool::waitForDoneAfterTake() } +void tst_QThreadPool::bindings() +{ + { + QThreadPool pool; + + // expiryTimeout property + QProperty<int> expiryTimeout; + pool.bindableExpiryTimeout().setBinding(Qt::makePropertyBinding(expiryTimeout)); + expiryTimeout = 1000; + QCOMPARE(pool.expiryTimeout(), 1000); + + QProperty<int> expiryTimeoutObserver; + expiryTimeoutObserver.setBinding(pool.bindableExpiryTimeout().makeBinding()); + pool.setExpiryTimeout(100); + QCOMPARE(expiryTimeoutObserver, 100); + + // stackSize property + QProperty<uint> stackSize; + pool.bindableStackSize().setBinding(Qt::makePropertyBinding(stackSize)); + stackSize = 1000; + QCOMPARE(pool.stackSize(), 1000); + + QProperty<uint> stackSizeObserver; + stackSizeObserver.setBinding(pool.bindableStackSize().makeBinding()); + pool.setStackSize(100); + QCOMPARE(stackSizeObserver, 100); + } + + // maxThreadCount property + { + // Make sure changing the max thread count via binding starts new threads + QThreadPool pool; + WaitingTask task; + + pool.setMaxThreadCount(1); + pool.start(&task); + pool.start(&task); + QVERIFY(task.waitForStarted.tryAcquire(1, 1000)); + + // thread limit is 1, cannot start more tasks + QVERIFY(!task.waitForStarted.tryAcquire(1, 1000)); + QCOMPARE(pool.activeThreadCount(), 1); + + QProperty<int> maxThreadCount; + pool.bindableMaxThreadCount().setBinding(Qt::makePropertyBinding(maxThreadCount)); + + maxThreadCount = 2; + QCOMPARE(pool.maxThreadCount(), 2); + + // increasing thread count should allow starting more tasks + QVERIFY(task.waitForStarted.tryAcquire(1, 1000)); + QCOMPARE(pool.activeThreadCount(), 2); + + task.waitToFinish.release(2); + pool.waitForDone(); + + QProperty<int> maxThreadCountObserver; + maxThreadCountObserver.setBinding(pool.bindableMaxThreadCount().makeBinding()); + pool.setMaxThreadCount(10); + QCOMPARE(maxThreadCountObserver, 10); + } +} + QTEST_MAIN(tst_QThreadPool); #include "tst_qthreadpool.moc" |