I just spent the last few days trawling through someone else's multi-threaded C++ Linux audio code, so I thought I'd share a few of my experiences.
First: The commit.
That code converts direct audio hardware access via ALSA into newer plugin-based output. It also fixes a race condition that occurs at the seam of the two subsystems involved: the client code provided a mixer callback that used a buffer that is initialised immediately after the server spawns the thread that needs it. It's a mistake made by the code's author, but to be fair I wouldn't have spotted it either if the code hadn't segfaulted on me.
If you ever find yourself in this situation, here are some tips:
Print statements really work. Yes, even with threads. Especially with C++, where control flow isn't obvious.
In threaded code, if you just insert print statements and behaviour changes, that's almost certainly a sign of a race condition.
C++ is harder to grep through than C, but it still works, if less effectively. C++ adds a lot of context that makes individual identifiers less useful on the isolated lines printed by grep.
Persistence pays. Even if the best programmers in the world say that threaded debugging is difficult, it can still be done.
If you're in college/university and going the computer/software route, take the Operating Systems course(s). Threads and concurrency get a lot of good exposure in them.
Read more »