src/README.md: map the source folder, its threads and its locks - #3875
src/README.md: map the source folder, its threads and its locks#3875mcfnord wants to merge 6 commits into
Conversation
ann0see
left a comment
There was a problem hiding this comment.
I'd aim this at human contributors for now.
AGPL. But I think it's weird as is. I'd think that a HTML comment for the full license would be enough and a visible short link to the license file. But @pljones should judge. I really dislike a wall of text first just stating the license. Nobody reads it. |
| - [protocol.cpp](protocol.cpp) — `CProtocol`: protocol message framing, acknowledgement, and | ||
| retransmission of unacknowledged messages from `SendMessQueue`. The wire format itself is | ||
| described in [../docs/JAMULUS_PROTOCOL.md](../docs/JAMULUS_PROTOCOL.md). | ||
| - [channel.cpp](channel.cpp) — `CChannel`: one connection, holding the receive jitter buffer |
There was a problem hiding this comment.
I think you should probably not describe too much of the file content. Rather the brief this file holds class X which does Y. As in anyone can just read the file to get more info. So here: Implements the channel + jitter buffer used for Server and Client.
| | recorder thread | server with recording | `CJamController` | `CJamRecorder`, fed by queued `AudioFrame` signals from the frame cycle | | ||
| | `QThreadPool` global pool | client GUI | the connect dialog | one task per listed server for the ping/info fan-out (`QtConcurrent::run`) | | ||
|
|
||
| Three consequences that are easy to miss: |
I believe if we write for a human audience, we will dramatically improve LLM outcomes "for free". |
Applies @ann0see's review on jamulussoftware#3875: - Intro cut to two sentences; the paragraph about what the file does and does not assert is gone. - File list back to one line each: the SendMessQueue detail, the SockBuf and CProtocol members and the vecChannels name are all readable in the file itself. Kept "the client has one; the server an array of MAX_NUM_CHANNELS", which is in server.h, not channel.cpp. - The three-bullet block after the thread table is one paragraph. The CSoundBase QThread note moves to src/sound/README.md (jamulussoftware#3873), where a reader meets the class; the send/receive clocking bullet is dropped, as the table above already carries it. The parenthetical about how the thread identities were checked is dropped too: it describes the method, not the code, and the util.cpp TODO makes the point on its own. 122 lines to 105. No claim changed.
CSoundBase derives from QThread, so a reader can reasonably expect a sound thread. There is none: no override of run() and no call to start() exists in the sound layer -- the only two run() overrides in src/ are CHighPrecisionTimer (util.h) and CSocketThread (socket.h). Audio callbacks always arrive on driver-owned threads. Moved here from the src/README.md draft (jamulussoftware#3875), where it sat under the thread table; this is the file that introduces CSoundBase.
| locks — `MutexAudioProcessCallback`, `MutexDevProperties`, and the per-backend ones — are | ||
| covered in [sound/README.md](sound/README.md). | ||
|
|
||
| ## Not yet documented |
There was a problem hiding this comment.
I guess we could drop this section.
| * mcfnord | ||
| * The Jamulus Development Team | ||
|
|
||
| As of Jamulus 3.12.1dev (commit eb172d47): All new source code contributions must be licensed |
There was a problem hiding this comment.
Doesn't need these lines. This only applied to existing files. New files should only have the AGPL header.
| - [util.h](util.h) / [util.cpp](util.cpp) — `CHighPrecisionTimer`, the server's frame clock, and | ||
| assorted helpers. | ||
|
|
||
| Client only: [client.cpp](client.cpp) (`CClient`), the sound layer in [sound/](sound/), the GUI |
There was a problem hiding this comment.
Section, laid out as bullets like the shared code. Same for the following ones.
| | `CChannel::Mutex` | per-channel state: the enable flag, gain and pan tables, name | setters in protocol slots on the main thread; getters in the server's frame cycle | | ||
| | `CChannel::MutexConvBuf` | the send-side conversion buffer | `PrepAndSendPacket()` on the sending thread; re-init from the main thread | | ||
|
|
||
| Smaller ones: `CProtocol::Mutex` (the queue of sent but not yet acknowledged messages), |
There was a problem hiding this comment.
Again, bulleted list. Or table.
MY LLM WROTE:
Short description of changes
src/has no README. This adds one: a map for a reader new to the code — which class lives where, which threads exist at runtime, and which lock protects what. Same shape as the section recently proposed forsrc/sound/README.mdin #3873: it describes how the code behaves today, asserts no intent, and ends with an explicit list of what is still missing.What it covers:
CSocketThread, the audio driver threads,CHighPrecisionTimer's thread, theCThreadPoolworkers, the recorder thread, and the connect dialog's use of the global pool. Followed by the three facts easiest to miss: the server's complete frame cycle (CServer::OnTimer) executes on the main thread — theTimeCriticalPrioritytimer thread only paces a queuedemit timeout()(confirmed with a debugger on Linux, and the TODO inutil.cppsays the same);CSoundBaseinheritsQThreadbut that thread is never started; the client sends audio from inside the driver callback while receiving onCSocketThread.MutexSocketBuf,CSocket::Mutex,CServer::Mutexincluding exactly which part ofOnTimerholds it,CChannel::Mutex,MutexConvBuf), each with what it protects and the threads that take it, plus one line each for the smaller ones.The thread table is measured, not read: each identity was confirmed by breaking on the function in a release build under gdb on Linux and recording which thread hit (
CServer::OnTimerandCProtocol::ParseMessageBodyon the main thread,CServer::PutAudioDataandCChannel::PutAudioDataonCSocketThread,CClient::ProcessAudioDataInternon the JACK callback thread,CHighPrecisionTimer::runon its own thread).Two design choices, offered for discussion since later doc files could follow the pattern:
[channel.cpp](channel.cpp),[../docs/JAMULUS_PROTOCOL.md](../docs/JAMULUS_PROTOCOL.md). Rendered on GitHub, the map becomes browseable: every named file is one click away. Read raw in a terminal or an editor, each link degrades to the path plus punctuation, so the text still works for a reader without a browser.grepfinds them from either the rendered or the raw form.CHANGELOG: SKIP
Context: Fixes an issue?
No issue. Follows #3873, which starts the sound-layer half of the same documentation; this file links to it rather than repeating it.
Does this change need documentation? What needs to be documented and how?
This is the documentation. Developer-facing, so it belongs next to the code rather than on the website.
Status of this Pull Request
Working implementation. Every statement is checkable against the tree at the commit it was written on, and the thread identities were verified at runtime rather than inferred from the source.
What is missing until this pull request can be merged?
Review. One open question for reviewers: whether the license header on a brand-new documentation file should carry the full historical GPL paragraph or only the AGPL block used here.
Checklist
No checks run on this one:
autobuild.ymlcarriespaths-ignore: '**README.md'andcoding-style-check.ymlonly triggers on**.cpp/**.h, so the fourth box stays unticked rather than claiming a green run that never happened.