forked from qt/qtbase
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Wait conditions example: fix an incorrect condition variable usage
3a449bb amended the code to remove acquiring a lock when waking up a condition variable. It is fine to not have a lock associated when waking a condition variable; what I misunderstood was the scope of the lock, which (and this underlines the importance of commenting _what exactly_ a lock protects, for each and ever lock) protected both the buffer as well as the counter of the buffer. This made my reasoning flawed: it is necessary to keep the lock while notifying, otherwise the counterpart could verify the condition isn't satisfied and wait (e.g. see numUsedBytes==0), missing the wake from the other thread (which could arrive between the check and the wait). Amends the previous commit. Change-Id: If7db2d045331f1b33b976fb6bf6aa9117c41678f Pick-to: 5.15 6.2 6.4 6.5 Reviewed-by: Morten Johan Sørvig <[email protected]>
- Loading branch information
Showing
2 changed files
with
16 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,6 @@ | |
// Copyright (C) 2022 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected], author Giuseppe D'Angelo <[email protected]> | ||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause | ||
|
||
#include <QAtomicInt> | ||
#include <QCoreApplication> | ||
#include <QMutex> | ||
#include <QMutexLocker> | ||
|
@@ -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 @@ class Producer : public QThread | |
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 @@ class Consumer : public QThread | |
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"); | ||
} | ||
|