Skip to content

Experiment: make cross-thread run/status flags std::atomic (#3798 batches A/B)#3800

Draft
mcfnord wants to merge 1 commit into
jamulussoftware:mainfrom
mcfnord:atomic-flags-3798-ab
Draft

Experiment: make cross-thread run/status flags std::atomic (#3798 batches A/B)#3800
mcfnord wants to merge 1 commit into
jamulussoftware:mainfrom
mcfnord:atomic-flags-3798-ab

Conversation

@mcfnord

@mcfnord mcfnord commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

This follows up on the discussion in #3786 and covers batches A and B of the audit in #3798 — the thread-lifecycle bRun flags and the jitter-buffer status flags. Offering it as an experiment: it is the least invasive slice of #3798, intended to establish the std::atomic pattern in the codebase and let us observe it through CI and normal use before deciding whether the more involved findings (C–F) are worth touching.

What changes

Six members become std::atomic<bool>, keeping plain operator syntax at every call site (per the conclusion in #3786 that the overloaded operators are simplest, and the default sequentially-consistent operations cost nothing at these rates):

Member Written by Read by
CSocketThread::bRun main thread (Stop()) socket thread loop
CHighPrecisionTimer::bRun (Mac/Linux variant) main thread (Start()/Stop()) timer thread loop; socket thread via IsRunning()
CSoundBase::bRun main thread (Start()/Stop()) audio callback thread (JACK/CoreAudio/Oboe/ASIO)
CSoundBase::bCallbackEntered audio callback thread GUI sound-device check
CSocket::bJitterBufferOK socket thread GUI read-and-reset
CClient::bJitterBufferOK sound thread GUI read-and-reset

The only non-declaration change: the two GetAndResetbJitterBufferOKFlag() functions now use exchange ( true ) instead of a separate read and reset. Behavior is the same, and it closes a small lost-update window — a "not OK" written by the socket/sound thread between the read and the reset used to be dropped silently.

Behavior

No intended behavior change. On x86 these compile to essentially the same instructions; the difference is that the compiler may no longer cache the flag across loop iterations, and on weakly-ordered CPUs (Apple Silicon, Android, ARM Linux servers) the cross-thread store is guaranteed to become visible and correctly ordered.

Tested

  • Full Linux client+server build (Qt 5.15, JACK enabled): compiles with no new warnings.
  • Headless server smoke test: starts, runs, exits cleanly on SIGTERM — this exercises the modified Stop() paths of the socket and timer threads.
  • macOS / Windows / Android builds not tested locally (relying on CI); the touched accesses in those backends are plain reads/writes covered by the operator overloads.

🤖 Generated with Claude Code

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<bool>:

- 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 jamulussoftware#3798.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread src/socket.h
CSocket* pSocket;
bool bRun;
CSocket* pSocket;
std::atomic<bool> bRun;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this one is already addressed as part of #3788, which is just awaiting a second approval.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants