std::future Is Not the Future
C++20 Coroutines for Audio Developers
Concurrency is hard. But does it need to be?
Audio applications and plugins constantly deal with asynchronous work: loading files, fetching resources or performing unbounded network operations just to name a few.
Traditionally and painfully, this leads to:
- the infamous spinning beach ball of death,
- blocking calls and stuttering UI updates,
- tangled callbacks,
- fragile state machines or
- ad-hoc thread management.
C++20 introduced coroutines, but in a very C++ way: not as a ready-made library feature, but as a confusing low-level language feature with a few keywords and plenty of sharp edges.
Other ecosystems are seemingly ahead of us. Swift, Kotlin, C#, Rust with tokio and also JavaScript have some incarnation of the async/await pattern.
But there is hope for us poor C++ devs as well!
Let's make sense of this and look at what coroutines actually provide, how existing libraries and patterns make them practical, and where they fit into real-world application software.
Let's explore how coroutines can help eliminate unnecessary thread blocking while still keeping CPUs busy doing actual work, replace nested callback chains with linear-looking code and proper exception propagation, and enable structured concurrency patterns that make async workflows easier to reason about.
The goal is not to turn audio developers into coroutine library authors, but to show how coroutines can simplify UI tasks, background jobs, file I/O or networking.
Takeaways:
- How coroutines can make async code easier to reason about
- How to banish the spinning beach ball of death by effortlessly offloading work—while keeping ownership and control flow crystal clear
- Which coroutine frameworks and libraries are practical today
- Which pitfalls and footguns to spot and avoid
Konrad Glas
Individual Contractor
Muse Group
Konrad Glas has been building professional music software since 2013. At Vienna Symphonic Library, he has held central engineering roles across the entire software stack—from sampling engines and audio processing to user interfaces—for products including Vienna Synchron Player, Vienna MIR Pro 3D, and Vienna Ensemble Pro.
He later joined StaffPad as a contractor and, following its acquisition by Muse Group, became the principal developer of MuseSampler—the playback engine behind MuseScore’s sampled instruments.
Recent projects involving network-loaded instruments and increasingly complex asynchronous systems introduced him to the less charming side of concurrency: blocked threads, missing exceptions, tangled callback chains, mysterious deadlocks, and background tasks that simply wandered off and never returned. Looking for a better way led him down the rabbit hole of C++20 coroutines. He has yet to find the bottom.