QSemaphore: port non-futex case from (QWaitCondition, QMutex) to std::{condition_variable, mutex}

The std variant is faster and more compact.

Use the QtPrivate wrappers to avoid the Integrity mess.

Change-Id: I4a1b1626d29472af059fee55ca26c31d9522b179
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2019-09-13 15:18:39 +02:00 committed by Marc Mutz
parent 6608e63298
commit f1f29c35cb

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2018 Intel Corporation. ** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -39,12 +39,14 @@
****************************************************************************/ ****************************************************************************/
#include "qsemaphore.h" #include "qsemaphore.h"
#include "qmutex.h"
#include "qfutex_p.h" #include "qfutex_p.h"
#include "qwaitcondition.h"
#include "qdeadlinetimer.h" #include "qdeadlinetimer.h"
#include "qdatetime.h" #include "qdatetime.h"
#include "qdebug.h" #include "qdebug.h"
#include "qlocking_p.h"
#include "qwaitcondition_p.h"
#include <chrono>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -275,10 +277,10 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp
class QSemaphorePrivate { class QSemaphorePrivate {
public: public:
inline QSemaphorePrivate(int n) : avail(n) { } explicit QSemaphorePrivate(int n) : avail(n) { }
QMutex mutex; QtPrivate::mutex mutex;
QWaitCondition cond; QtPrivate::condition_variable cond;
int avail; int avail;
}; };
@ -330,9 +332,10 @@ void QSemaphore::acquire(int n)
return; return;
} }
QMutexLocker locker(&d->mutex); const auto sufficientResourcesAvailable = [this, n] { return d->avail >= n; };
while (n > d->avail)
d->cond.wait(locker.mutex()); auto locker = qt_unique_lock(d->mutex);
d->cond.wait(locker, sufficientResourcesAvailable);
d->avail -= n; d->avail -= n;
} }
@ -405,9 +408,9 @@ void QSemaphore::release(int n)
return; return;
} }
QMutexLocker locker(&d->mutex); const auto locker = qt_scoped_lock(d->mutex);
d->avail += n; d->avail += n;
d->cond.wakeAll(); d->cond.notify_all();
} }
/*! /*!
@ -421,7 +424,7 @@ int QSemaphore::available() const
if (futexAvailable()) if (futexAvailable())
return futexAvailCounter(u.loadRelaxed()); return futexAvailCounter(u.loadRelaxed());
QMutexLocker locker(&d->mutex); const auto locker = qt_scoped_lock(d->mutex);
return d->avail; return d->avail;
} }
@ -443,7 +446,7 @@ bool QSemaphore::tryAcquire(int n)
if (futexAvailable()) if (futexAvailable())
return futexSemaphoreTryAcquire<false>(u, n, 0); return futexSemaphoreTryAcquire<false>(u, n, 0);
QMutexLocker locker(&d->mutex); const auto locker = qt_scoped_lock(d->mutex);
if (n > d->avail) if (n > d->avail)
return false; return false;
d->avail -= n; d->avail -= n;
@ -468,22 +471,24 @@ bool QSemaphore::tryAcquire(int n)
*/ */
bool QSemaphore::tryAcquire(int n, int timeout) bool QSemaphore::tryAcquire(int n, int timeout)
{ {
Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative"); if (timeout < 0) {
acquire(n);
return true;
}
// We're documented to accept any negative value as "forever" if (timeout == 0)
// but QDeadlineTimer only accepts -1. return tryAcquire(n);
timeout = qMax(timeout, -1);
Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
if (futexAvailable()) if (futexAvailable())
return futexSemaphoreTryAcquire<true>(u, n, timeout); return futexSemaphoreTryAcquire<true>(u, n, timeout);
QDeadlineTimer timer(timeout); using namespace std::chrono;
QMutexLocker locker(&d->mutex); const auto sufficientResourcesAvailable = [this, n] { return d->avail >= n; };
while (n > d->avail && !timer.hasExpired()) {
if (!d->cond.wait(locker.mutex(), timer)) auto locker = qt_unique_lock(d->mutex);
return false; if (!d->cond.wait_for(locker, milliseconds{timeout}, sufficientResourcesAvailable))
}
if (n > d->avail)
return false; return false;
d->avail -= n; d->avail -= n;
return true; return true;