diff options
author | Thiago Macieira <[email protected]> | 2023-05-22 19:32:20 -0700 |
---|---|---|
committer | Thiago Macieira <[email protected]> | 2025-06-30 07:23:56 -0700 |
commit | 6679efd2a4cc23de4ed947ef567a799d474e2079 (patch) | |
tree | f873fb493b518f68994705329b73bd4babb7a278 | |
parent | 5bd58d67c14ac765a2a0abb7d5dbb499ac60f13b (diff) |
Replace one-shot uses of QSemaphore with QLatch
This commit replaces one-shot synchronization of threads that were using
QSemaphore with QLatch. QSemaphore is efficient on Linux and Windows,
but allocates memory elsewhere. Even on those platforms where we have
futex-like OS support, QSemaphore is heavier than what we really need
here.
All but one uses of QSemaphore in qtbase libraries (I didn't change
examples or tests) were replaced. The remaining use of QSemaphore in
qnetworkproxy_libproxy.cpp is a proper producer-consumer.
Change-Id: Ib5ce7a497e034ebabb2cfffd1761a4fcb2be9a6c
Reviewed-by: Volker Hilsheimer <[email protected]>
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 14 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 26 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 23 | ||||
-rw-r--r-- | src/dbus/qdbusintegrator.cpp | 15 | ||||
-rw-r--r-- | src/dbus/qdbusintegrator_p.h | 4 | ||||
-rw-r--r-- | src/dbus/qdbusthreaddebug_p.h | 20 | ||||
-rw-r--r-- | src/gui/image/qimage.cpp | 14 | ||||
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 38 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 8 | ||||
-rw-r--r-- | src/gui/painting/qimagescale.cpp | 8 | ||||
-rw-r--r-- | src/gui/painting/qimagescale_neon.cpp | 8 | ||||
-rw-r--r-- | src/gui/painting/qimagescale_sse4.cpp | 8 | ||||
-rw-r--r-- | src/network/kernel/qnetworkproxy_libproxy.cpp | 7 | ||||
-rw-r--r-- | tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp | 10 |
14 files changed, 90 insertions, 113 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 795cc531114..b48922daeab 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -17,7 +17,7 @@ #include <qthread.h> #include "private/qthread_p.h" #if QT_CONFIG(thread) -#include <qsemaphore.h> +#include "private/qlatch_p.h" #endif // for normalizeTypeInternal @@ -1748,9 +1748,9 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase * if (receiverInSameThread) qWarning("QMetaObject::invokeMethod: Dead lock detected"); - QSemaphore semaphore; - QCoreApplication::postEvent(object, new QMetaCallEvent(std::move(slot), nullptr, -1, argv, &semaphore)); - semaphore.acquire(); + QLatch latch(1); + QCoreApplication::postEvent(object, new QMetaCallEvent(std::move(slot), nullptr, -1, argv, &latch)); + latch.wait(); #endif // QT_CONFIG(thread) } else { qWarning("QMetaObject::invokeMethod: Unknown connection type"); @@ -2922,10 +2922,10 @@ auto QMetaMethodInvoker::invokeImpl(QMetaMethod self, void *target, return InvokeFailReason::DeadLockDetected; } - QSemaphore semaphore; + QLatch latch(1); QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction, - nullptr, -1, param, &semaphore)); - semaphore.acquire(); + nullptr, -1, param, &latch)); + latch.wait(); #endif // QT_CONFIG(thread) } return {}; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 38ded8117c0..888c71f5a49 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -27,7 +27,7 @@ #include <qscopeguard.h> #include <qset.h> #if QT_CONFIG(thread) -#include <qsemaphore.h> +#include <private/qlatch_p.h> #endif #include <private/qorderedmutexlocker_p.h> @@ -476,8 +476,8 @@ void QObjectPrivate::reinitBindingStorageAfterThreadMove() QAbstractMetaCallEvent::~QAbstractMetaCallEvent() { #if QT_CONFIG(thread) - if (semaphore_) - semaphore_->release(); + if (latch) + latch->countDown(); #endif } @@ -506,8 +506,8 @@ inline void QMetaCallEvent::allocArgs() QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction, const QObject *sender, int signalId, - void **args, QSemaphore *semaphore) - : QAbstractMetaCallEvent(sender, signalId, semaphore), + void **args, QLatch *latch) + : QAbstractMetaCallEvent(sender, signalId, latch), d({nullptr, args, callFunction, 0, method_offset, method_relative}), prealloc_() { @@ -521,8 +521,8 @@ QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, */ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, const QObject *sender, int signalId, - void **args, QSemaphore *semaphore) - : QAbstractMetaCallEvent(sender, signalId, semaphore), + void **args, QLatch *latch) + : QAbstractMetaCallEvent(sender, signalId, latch), d({QtPrivate::SlotObjUniquePtr{slotO}, args, nullptr, 0, 0, ushort(-1)}), prealloc_() { @@ -538,8 +538,8 @@ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, */ QMetaCallEvent::QMetaCallEvent(QtPrivate::SlotObjUniquePtr slotO, const QObject *sender, int signalId, - void **args, QSemaphore *semaphore) - : QAbstractMetaCallEvent(sender, signalId, semaphore), + void **args, QLatch *latch) + : QAbstractMetaCallEvent(sender, signalId, latch), d{std::move(slotO), args, nullptr, 0, 0, ushort(-1)}, prealloc_() { @@ -4198,18 +4198,18 @@ void doActivate(QObject *sender, int signal_index, void **argv) if (c->isSingleShot && !QObjectPrivate::removeConnection(c)) continue; - QSemaphore semaphore; + QLatch latch(1); { QMutexLocker locker(signalSlotLock(receiver)); if (!c->isSingleShot && !c->receiver.loadAcquire()) continue; QMetaCallEvent *ev = c->isSlotObject ? - new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &semaphore) : + new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &latch) : new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, - sender, signal_index, argv, &semaphore); + sender, signal_index, argv, &latch); QCoreApplication::postEvent(receiver, ev); } - semaphore.acquire(); + latch.wait(); continue; #endif } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 20c454506ab..dca9c1af932 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -328,16 +328,13 @@ bool QObjectPrivate::disconnect(const typename QtPrivate::FunctionPointer< Func1 &SignalType::Object::staticMetaObject); } -class QSemaphore; +class QLatch; class Q_CORE_EXPORT QAbstractMetaCallEvent : public QEvent { public: - QAbstractMetaCallEvent(const QObject *sender, int signalId, QSemaphore *semaphore = nullptr) - : QEvent(MetaCall), signalId_(signalId), sender_(sender) -#if QT_CONFIG(thread) - , semaphore_(semaphore) -#endif - { Q_UNUSED(semaphore); } + QAbstractMetaCallEvent(const QObject *sender, int signalId, QLatch *latch = nullptr) + : QEvent(MetaCall), signalId_(signalId), sender_(sender), latch(latch) + {} ~QAbstractMetaCallEvent(); virtual void placeMetaCall(QObject *object) = 0; @@ -348,25 +345,23 @@ public: private: int signalId_; const QObject *sender_; -#if QT_CONFIG(thread) - QSemaphore *semaphore_; -#endif + QLatch *latch; }; class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent { public: - // blocking queued with semaphore - args always owned by caller + // blocking queued with latch - args always owned by caller QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction, const QObject *sender, int signalId, - void **args, QSemaphore *semaphore); + void **args, QLatch *latch); QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signalId, - void **args, QSemaphore *semaphore); + void **args, QLatch *latch); QMetaCallEvent(QtPrivate::SlotObjUniquePtr slotObj, const QObject *sender, int signalId, - void **args, QSemaphore *semaphore); + void **args, QLatch *latch); // queued - args allocated by event, copied by caller QMetaCallEvent(ushort method_offset, ushort method_relative, diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index ed17dddbcf5..4c9736dea6d 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -6,6 +6,7 @@ #include <qcoreapplication.h> #include <qelapsedtimer.h> +#include <private/qlatch_p.h> #include <qloggingcategory.h> #include <qmetaobject.h> #include <qobject.h> @@ -1530,8 +1531,8 @@ void QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg) ObjectTreeNode result; int usedLength; QThread *objThread = nullptr; - QSemaphore sem; - bool semWait; + QLatch latch(1); + bool latchWait; { QDBusReadLocker locker(HandleObjectCallAction, this); @@ -1569,16 +1570,16 @@ void QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg) // synchronize with it postEventToThread(HandleObjectCallPostEventAction, result.obj, new QDBusActivateObjectEvent(QDBusConnection(this), this, result, - usedLength, msg, &sem)); - semWait = true; + usedLength, msg, &latch)); + latchWait = true; } else { // looped-back message, targeting current thread - semWait = false; + latchWait = false; } } // release the lock - if (semWait) - SEM_ACQUIRE(HandleObjectCallSemaphoreAction, sem); + if (latchWait) + latch.wait(); else activateObject(result, msg, usedLength); } diff --git a/src/dbus/qdbusintegrator_p.h b/src/dbus/qdbusintegrator_p.h index 9c5fa1b061f..ac9adf02100 100644 --- a/src/dbus/qdbusintegrator_p.h +++ b/src/dbus/qdbusintegrator_p.h @@ -107,8 +107,8 @@ class QDBusActivateObjectEvent: public QAbstractMetaCallEvent public: QDBusActivateObjectEvent(const QDBusConnection &c, QObject *sender, const QDBusConnectionPrivate::ObjectTreeNode &n, - int p, const QDBusMessage &m, QSemaphore *s = nullptr) - : QAbstractMetaCallEvent(sender, -1, s), connection(c), node(n), + int p, const QDBusMessage &m, QLatch *l = nullptr) + : QAbstractMetaCallEvent(sender, -1, l), connection(c), node(n), pathStartPos(p), message(m), handled(false) { } ~QDBusActivateObjectEvent() override; diff --git a/src/dbus/qdbusthreaddebug_p.h b/src/dbus/qdbusthreaddebug_p.h index a1d3a420ec6..bcbd1efb494 100644 --- a/src/dbus/qdbusthreaddebug_p.h +++ b/src/dbus/qdbusthreaddebug_p.h @@ -129,25 +129,5 @@ struct QDBusWriteLocker: QDBusLockerBase } }; -#if QDBUS_THREAD_DEBUG -# define SEM_ACQUIRE(action, sem) \ - do { \ - QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::BeforeAcquire, this); \ - sem.acquire(); \ - QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::AfterAcquire, this); \ - } while (false) - -# define SEM_RELEASE(action, sem) \ - do { \ - QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::BeforeRelease, that); \ - sem.release(); \ - QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::AfterRelease, that); \ - } while (false) - -#else -# define SEM_ACQUIRE(action, sem) sem.acquire() -# define SEM_RELEASE(action, sem) sem.release() -#endif - #endif // QT_NO_DBUS #endif diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 840bff26e53..1413e611270 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -38,7 +38,7 @@ #include <private/qfont_p.h> #if QT_CONFIG(qtgui_threadpool) -#include <qsemaphore.h> +#include <private/qlatch_p.h> #include <qthreadpool.h> #include <private/qthreadpool_p.h> #endif @@ -5342,17 +5342,17 @@ void QImage::applyColorTransform(const QColorTransform &transform) segments = std::min(segments, height()); QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool(); if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { - QSemaphore semaphore; + QLatch latch(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (height() - y) / (segments - i); threadPool->start([&, y, yn]() { transformSegment(y, y + yn); - semaphore.release(1); + latch.countDown(); }); y += yn; } - semaphore.acquire(segments); + latch.wait(); } else #endif transformSegment(0, height()); @@ -5832,17 +5832,17 @@ QImage QImage::colorTransformed(const QColorTransform &transform, QImage::Format segments = std::min(segments, height()); QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool(); if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { - QSemaphore semaphore; + QLatch latch(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (height() - y) / (segments - i); threadPool->start([&, y, yn]() { transformSegment(y, y + yn); - semaphore.release(1); + latch.countDown(); }); y += yn; } - semaphore.acquire(segments); + latch.wait(); } else #endif transformSegment(0, height()); diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 43f3cca09e0..521d71796ea 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -14,7 +14,7 @@ #include <qendian.h> #include <qrgbafloat.h> #if QT_CONFIG(thread) -#include <qsemaphore.h> +#include <private/qlatch_p.h> #include <qthreadpool.h> #include <private/qthreadpool_p.h> #endif @@ -215,17 +215,17 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread())) return convertSegment(0, src->height); - QSemaphore semaphore; + QLatch latch(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (src->height - y) / (segments - i); threadPool->start([&, y, yn]() { convertSegment(y, y + yn); - semaphore.release(1); + latch.countDown(); }); y += yn; } - semaphore.acquire(segments); + latch.wait(); #else convertSegment(0, src->height); #endif @@ -270,17 +270,17 @@ void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::Ima if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread())) return convertSegment(0, src->height); - QSemaphore semaphore; + QLatch latch(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (src->height - y) / (segments - i); threadPool->start([&, y, yn]() { convertSegment(y, y + yn); - semaphore.release(1); + latch.countDown(); }); y += yn; } - semaphore.acquire(segments); + latch.wait(); #else convertSegment(0, src->height); #endif @@ -324,17 +324,17 @@ void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::I if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread())) return convertSegment(0, src->height); - QSemaphore semaphore; + QLatch latch(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (src->height - y) / (segments - i); threadPool->start([&, y, yn]() { convertSegment(y, y + yn); - semaphore.release(1); + latch.countDown(); }); y += yn; } - semaphore.acquire(segments); + latch.wait(); #else convertSegment(0, src->height); #endif @@ -435,17 +435,17 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im segments = std::min(segments, data->height); QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool(); if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { - QSemaphore semaphore; + QLatch latch(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (data->height - y) / (segments - i); threadPool->start([&, y, yn]() { convertSegment(y, y + yn); - semaphore.release(1); + latch.countDown(); }); y += yn; } - semaphore.acquire(segments); + latch.wait(); if (data->bytes_per_line != params.bytesPerLine) { // Compress segments to a continuous block y = 0; @@ -529,17 +529,17 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for segments = std::min(segments, data->height); QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool(); if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { - QSemaphore semaphore; + QLatch latch(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (data->height - y) / (segments - i); threadPool->start([&, y, yn]() { convertSegment(y, y + yn); - semaphore.release(1); + latch.countDown(); }); y += yn; } - semaphore.acquire(segments); + latch.wait(); if (data->bytes_per_line != params.bytesPerLine) { // Compress segments to a continuous block y = 0; @@ -624,17 +624,17 @@ bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_f segments = std::min(segments, data->height); QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool(); if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { - QSemaphore semaphore; + QLatch latch(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (data->height - y) / (segments - i); threadPool->start([&, y, yn]() { convertSegment(y, y + yn); - semaphore.release(1); + latch.countDown(); }); y += yn; } - semaphore.acquire(segments); + latch.wait(); if (data->bytes_per_line != params.bytesPerLine) { // Compress segments to a continuous block y = 0; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 8aefba86ee7..b109e9a5a20 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -28,7 +28,7 @@ #include <qmath.h> #if QT_CONFIG(qtgui_threadpool) -#include <qsemaphore.h> +#include <private/qlatch_p.h> #include <qthreadpool.h> #include <private/qthreadpool_p.h> #endif @@ -3970,17 +3970,17 @@ static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP b QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool(); \ if (segments > 1 && qPixelLayouts[data->rasterBuffer->format].bpp >= QPixelLayout::BPP8 \ && threadPool && !threadPool->contains(QThread::currentThread())) { \ - QSemaphore semaphore; \ + QLatch latch(segments); \ int c = 0; \ for (int i = 0; i < segments; ++i) { \ int cn = (count - c) / (segments - i); \ threadPool->start([&, c, cn]() { \ function(c, c + cn); \ - semaphore.release(1); \ + latch.countDown(); \ }, 1); \ c += cn; \ } \ - semaphore.acquire(segments); \ + latch.wait(); \ } else \ function(0, count) #else diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp index 1bbfcf07a0a..15ef5f57dc7 100644 --- a/src/gui/painting/qimagescale.cpp +++ b/src/gui/painting/qimagescale.cpp @@ -11,7 +11,7 @@ #include "qrgbafloat.h" #if QT_CONFIG(qtgui_threadpool) -#include <qsemaphore.h> +#include <private/qlatch_p.h> #include <qthreadpool.h> #include <private/qguiapplication_p.h> #include <private/qthreadpool_p.h> @@ -290,17 +290,17 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con segments = std::min(segments, dh); QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool(); if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { - QSemaphore semaphore; + QLatch latch(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (dh - y) / (segments - i); threadPool->start([&, y, yn]() { scaleSection(y, y + yn); - semaphore.release(1); + latch.countDown(); }); y += yn; } - semaphore.acquire(segments); + latch.wait(); return; } #else diff --git a/src/gui/painting/qimagescale_neon.cpp b/src/gui/painting/qimagescale_neon.cpp index 1fc1070dc0d..81e04e8f082 100644 --- a/src/gui/painting/qimagescale_neon.cpp +++ b/src/gui/painting/qimagescale_neon.cpp @@ -7,7 +7,7 @@ #include <private/qsimd_p.h> #if QT_CONFIG(qtgui_threadpool) -#include <qsemaphore.h> +#include <private/qlatch_p.h> #include <qthreadpool.h> #include <private/qguiapplication_p.h> #include <private/qthreadpool_p.h> @@ -27,17 +27,17 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con segments = std::min(segments, dh); QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool(); if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { - QSemaphore semaphore; + QLatch semaphore(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (dh - y) / (segments - i); threadPool->start([&, y, yn]() { scaleSection(y, y + yn); - semaphore.release(1); + semaphore.countDown(); }); y += yn; } - semaphore.acquire(segments); + semaphore.wait(); return; } #endif diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp index 5d4c3a4e7c2..740f1570345 100644 --- a/src/gui/painting/qimagescale_sse4.cpp +++ b/src/gui/painting/qimagescale_sse4.cpp @@ -7,7 +7,7 @@ #include <private/qsimd_p.h> #if QT_CONFIG(qtgui_threadpool) -#include <qsemaphore.h> +#include <private/qlatch_p.h> #include <qthreadpool.h> #include <private/qguiapplication_p.h> #include <private/qthreadpool_p.h> @@ -27,17 +27,17 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con segments = std::min(segments, dh); QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool(); if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) { - QSemaphore semaphore; + QLatch latch(segments); int y = 0; for (int i = 0; i < segments; ++i) { int yn = (dh - y) / (segments - i); threadPool->start([&, y, yn]() { scaleSection(y, y + yn); - semaphore.release(1); + latch.countDown(); }); y += yn; } - semaphore.acquire(segments); + latch.wait(); return; } #endif diff --git a/src/network/kernel/qnetworkproxy_libproxy.cpp b/src/network/kernel/qnetworkproxy_libproxy.cpp index da1e8fdbd4a..b17d46ea96a 100644 --- a/src/network/kernel/qnetworkproxy_libproxy.cpp +++ b/src/network/kernel/qnetworkproxy_libproxy.cpp @@ -10,6 +10,7 @@ #include <QtCore/QMutex> #include <QtCore/QSemaphore> #include <QtCore/QUrl> +#include <QtCore/private/qlatch_p.h> #include <QtCore/private/qeventdispatcher_unix_p.h> #include <QtCore/private/qthread_p.h> #include <QtCore/qapplicationstatic.h> @@ -61,7 +62,7 @@ private: // we leave the conversion to/from QUrl to the calling thread const char *url; char **proxies; - QSemaphore replyReady; + QLatch replyReady{1}; }; void run() override; @@ -119,7 +120,7 @@ QList<QUrl> QLibProxyWrapper::getProxies(const QUrl &url) requestReady.release(); // wait for the reply - data.replyReady.acquire(); + data.replyReady.wait(); } else { // non-threaded mode data.proxies = px_proxy_factory_get_proxies(factory, data.url); @@ -147,7 +148,7 @@ void QLibProxyWrapper::run() if (isInterruptionRequested()) break; request->proxies = px_proxy_factory_get_proxies(factory, request->url); - request->replyReady.release(); + request->replyReady.countDown(); } px_proxy_factory_free(factory); diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 851fef2e05a..a293023f2c6 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -10,7 +10,7 @@ #endif #include <QScopeGuard> #include <QVersionNumber> -#include <QSemaphore> +#include <private/qlatch_p.h> #include <qcoreapplication.h> #include <qfileinfo.h> @@ -1926,13 +1926,13 @@ void tst_QUdpSocket::readyReadConnectionThrottling() QUdpSocket receiver; QVERIFY(receiver.bind(QHostAddress(QHostAddress::LocalHost), 0)); - QSemaphore semaphore; + QLatch latch(1); // Repro-ing deterministically eludes me, so we are bruteforcing it: // The thread acts as a remote sender, flooding the receiver with datagrams, // and at some point the receiver would get into the broken state mentioned // earlier. - std::unique_ptr<QThread> thread(QThread::create([&semaphore, port = receiver.localPort()]() { + std::unique_ptr<QThread> thread(QThread::create([&latch, port = receiver.localPort()]() { QUdpSocket sender; sender.connectToHost(QHostAddress(QHostAddress::LocalHost), port); QCOMPARE(sender.state(), QUdpSocket::ConnectedState); @@ -1940,7 +1940,7 @@ void tst_QUdpSocket::readyReadConnectionThrottling() constexpr qsizetype PayloadSize = 242; const QByteArray payload(PayloadSize, 'a'); - semaphore.acquire(); // Wait for main thread to be ready + latch.wait(); // Wait for main thread to be ready while (true) { // We send 100 datagrams at a time, then sleep. // This is mostly to let the main thread catch up between bursts so @@ -1975,7 +1975,7 @@ void tst_QUdpSocket::readyReadConnectionThrottling() }, Qt::QueuedConnection); - semaphore.release(); + latch.countDown(); constexpr qsizetype MaxCount = 500; QVERIFY2(QTest::qWaitFor([&] { return count >= MaxCount; }, 10s), QByteArray::number(count).constData()); |