diff --git a/examples/corelib/threads/doc/src/waitconditions.qdoc b/examples/corelib/threads/doc/src/waitconditions.qdoc index 7715bd8ab63..ae9e767c138 100644 --- a/examples/corelib/threads/doc/src/waitconditions.qdoc +++ b/examples/corelib/threads/doc/src/waitconditions.qdoc @@ -75,16 +75,13 @@ that the condition \c bufferNotEmpty is true, since \c numUsedBytes is necessarily greater than 0. - The QWaitCondition::wait() function accepts a + We guard all accesses to the \c numUsedBytes variable with a + mutex. In addition, the QWaitCondition::wait() function accepts a mutex as its argument. This mutex is unlocked before the thread is put to sleep and locked when the thread wakes up. Furthermore, the transition from the locked state to the wait state is atomic, to prevent race conditions from occurring. - Accesses to the \c numUsedBytes variable do not need mutex - protection, as that variable is a QAtomicInt; atomic variables - do not participate in data races. - \section1 Consumer Class Let's turn to the \c Consumer class: diff --git a/examples/corelib/threads/waitconditions/waitconditions.cpp b/examples/corelib/threads/waitconditions/waitconditions.cpp index 36f02f78968..bdc24acd8c2 100644 --- a/examples/corelib/threads/waitconditions/waitconditions.cpp +++ b/examples/corelib/threads/waitconditions/waitconditions.cpp @@ -2,7 +2,6 @@ // Copyright (C) 2022 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#include #include #include #include @@ -18,13 +17,12 @@ constexpr int DataSize = 100000; constexpr int BufferSize = 8192; -QMutex mutex; // protects the buffer +QMutex mutex; // protects the buffer and the counter char buffer[BufferSize]; +int numUsedBytes; QWaitCondition bufferNotEmpty; QWaitCondition bufferNotFull; - -QAtomicInt numUsedBytes; //! [0] //! [1] @@ -43,14 +41,17 @@ private: for (int i = 0; i < DataSize; ++i) { { const QMutexLocker locker(&mutex); - while (numUsedBytes.loadAcquire() == BufferSize) + while (numUsedBytes == BufferSize) bufferNotFull.wait(&mutex); } buffer[i % BufferSize] = "ACGT"[QRandomGenerator::global()->bounded(4)]; - numUsedBytes.fetchAndAddRelease(1); - bufferNotEmpty.wakeAll(); + { + const QMutexLocker locker(&mutex); + ++numUsedBytes; + bufferNotEmpty.wakeAll(); + } } } }; @@ -72,14 +73,17 @@ private: for (int i = 0; i < DataSize; ++i) { { const QMutexLocker locker(&mutex); - while (numUsedBytes.loadAcquire() == 0) + while (numUsedBytes == 0) bufferNotEmpty.wait(&mutex); } fprintf(stderr, "%c", buffer[i % BufferSize]); - numUsedBytes.fetchAndAddRelease(-1); - bufferNotFull.wakeAll(); + { + const QMutexLocker locker(&mutex); + --numUsedBytes; + bufferNotFull.wakeAll(); + } } fprintf(stderr, "\n"); }