From e12cd8d244ddc2740e1294d5d270c136fcd59366 Mon Sep 17 00:00:00 2001 From: jrd Date: Fri, 17 Jul 2026 22:44:19 +0000 Subject: [PATCH 1/2] Make cross-thread run/status flags std::atomic The socket, high-precision timer and sound threads are stopped by a plain bool written from another thread, and the jitter-buffer status flags are written and read/reset from different threads. Convert these six flags to std::atomic: - CSocketThread::bRun - CHighPrecisionTimer::bRun (Mac/Linux variant) - CSoundBase::bRun - CSoundBase::bCallbackEntered - CSocket::bJitterBufferOK - CClient::bJitterBufferOK The read-and-reset functions now use exchange() so a "not OK" written between a separate read and reset can no longer be lost. Addresses batches A and B of #3798. Co-Authored-By: Claude Fable 5 --- src/client.cpp | 6 ++---- src/client.h | 7 ++++--- src/socket.cpp | 15 ++++----------- src/socket.h | 7 ++++--- src/sound/soundbase.h | 9 +++++---- src/util.h | 7 ++++--- 6 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index fb9bab5478..b98a60c383 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -631,14 +631,12 @@ bool CClient::GetAndResetbJitterBufferOKFlag() // get the socket buffer put status flag and reset it const bool bSocketJitBufOKFlag = Socket.GetAndResetbJitterBufferOKFlag(); - if ( !bJitterBufferOK ) + // atomically read our own get status flag and reset it to OK + if ( !bJitterBufferOK.exchange ( true ) ) { // our jitter buffer get status is not OK so the overall status of the // jitter buffer is also not OK (we do not have to consider the status // of the socket buffer put status flag) - - // reset flag before returning the function - bJitterBufferOK = true; return false; } diff --git a/src/client.h b/src/client.h index fb77930723..c133d8d854 100644 --- a/src/client.h +++ b/src/client.h @@ -51,6 +51,7 @@ #include #include #include +#include #ifdef USE_OPUS_SHARED_LIB # include "opus/opus_custom.h" #else @@ -431,9 +432,9 @@ class CClient : public QObject bool bEnableAudioAlerts; bool bEnableOPUS64; - bool bJitterBufferOK; - bool bMuteMeInPersonalMix; - QMutex MutexDriverReinit; + std::atomic bJitterBufferOK; + bool bMuteMeInPersonalMix; + QMutex MutexDriverReinit; // server settings int iServerSockBufNumFrames; diff --git a/src/socket.cpp b/src/socket.cpp index 0a83922342..b02b3a655a 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -518,17 +518,10 @@ void CSocket::SendPacket ( const CVector& vecbySendBuf, const CHostAddr bool CSocket::GetAndResetbJitterBufferOKFlag() { - // check jitter buffer status - if ( !bJitterBufferOK ) - { - // reset flag and return "not OK" status - bJitterBufferOK = true; - return false; - } - - // the buffer was OK, we do not have to reset anything and just return the - // OK status - return true; + // atomically read the jitter buffer status and reset it to OK so that a + // "not OK" set by the socket thread between a separate read and reset + // cannot be lost + return bJitterBufferOK.exchange ( true ); } void CSocket::OnDataReceived() diff --git a/src/socket.h b/src/socket.h index 4cd80bb1a2..1727fae365 100644 --- a/src/socket.h +++ b/src/socket.h @@ -49,6 +49,7 @@ #include #include #include +#include #include #include "global.h" #include "protocol.h" @@ -124,7 +125,7 @@ class CSocket : public QObject bool bIsClient; - bool bJitterBufferOK; + std::atomic bJitterBufferOK; // This is a reference to CClient::bIPv6Available or CServer::bIPv6Available, // to inform the Client or Server which type of socket was created at startup. @@ -237,8 +238,8 @@ class CHighPrioSocket : public QObject } } - CSocket* pSocket; - bool bRun; + CSocket* pSocket; + std::atomic bRun; }; void Init() diff --git a/src/sound/soundbase.h b/src/sound/soundbase.h index ddf68e3275..32c727f999 100644 --- a/src/sound/soundbase.h +++ b/src/sound/soundbase.h @@ -49,6 +49,7 @@ #include #include #include +#include #ifndef HEADLESS # include #endif @@ -193,10 +194,10 @@ class CSoundBase : public QThread ( *fpProcessCallback ) ( psData, pProcessCallbackArg ); } - bool bRun; - bool bCallbackEntered; - QMutex MutexAudioProcessCallback; - QMutex MutexDevProperties; + std::atomic bRun; + std::atomic bCallbackEntered; + QMutex MutexAudioProcessCallback; + QMutex MutexDevProperties; QString strSystemDriverTechniqueName; int iCtrlMIDIChannel; diff --git a/src/util.h b/src/util.h index 1185c56936..6e8645ae8d 100644 --- a/src/util.h +++ b/src/util.h @@ -47,6 +47,7 @@ #pragma once #include #include +#include #ifdef _WIN32 # include # include @@ -1352,11 +1353,11 @@ class CHighPrecisionTimer : public QThread protected: virtual void run(); - bool bRun; + std::atomic bRun; # if defined( __APPLE__ ) || defined( __MACOSX ) - uint64_t Delay; - uint64_t NextEnd; + uint64_t Delay; + uint64_t NextEnd; # else long Delay; timespec NextEnd; From 4c2f6c0359d13624da82cf4e5592467c9f45a514 Mon Sep 17 00:00:00 2001 From: jrd Date: Sat, 18 Jul 2026 15:23:09 +0000 Subject: [PATCH 2/2] Drop CSocketThread::bRun conversion, superseded by #3788 softins already makes this member atomic in #3788 (which also removes CSocket::Close in favour of non-blocking reads). Keep only the bJitterBufferOK conversion in this file; the include moves to match #3788 so the two branches merge cleanly in either order. Co-Authored-By: Claude Fable 5 --- src/socket.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/socket.h b/src/socket.h index 1727fae365..3a08e85ae7 100644 --- a/src/socket.h +++ b/src/socket.h @@ -49,8 +49,8 @@ #include #include #include -#include #include +#include #include "global.h" #include "protocol.h" #include "util.h" @@ -238,8 +238,8 @@ class CHighPrioSocket : public QObject } } - CSocket* pSocket; - std::atomic bRun; + CSocket* pSocket; + bool bRun; }; void Init()