VolumetricCondensed

Back To Schedule

Wait-Free Thread Synchronisation With the SeqLock

10:00 - 10:50 UTC | Wednesday 13th November 2024 | Bristol 2
Advanced

When developing real-time audio processing applications in C++, the following problem arises almost inevitably: how can we share data between the real-time audio thread and the other threads (such as a GUI thread) in a way that is real-time safe? How can we synchronise reads and writes to C++ objects across threads, and manage the lifetime of these objects, while remaining wait-free on the real-time thread?

This talk is the second in a series of talks about thread synchronisation in a real-time context. In the first episode, given at ADC 2022, we focused on the case where the real-time thread needs to read a sufficiently large, persistent object that is simultaneously mutated on another thread. In this second episode, we focus on the reverse case: the real-time thread needs to write the value while remaining wait-free, and while other (non-real-time) threads are reading it.

The traditional solution for this problem in audio processing code today is double buffering. This strategy works well in certain cases, but like every algorithm it has certain tradeoffs. If we look beyond the audio industry, it turns out there is actually another strategy that has more favourable tradeoffs for some use cases: the SeqLock.

We describe the general idea of the SeqLock, discuss the different parts of the algorithm, and show a working reference implementation. It turns out that in order to implement a SeqLock portably and without introducing undefined behaviour, we need to reconcile the algorithm with the C++ memory model, which presents an interesting challenge. In order to make it work and be efficient, we need to be very careful with our use of memory fences, memory ordering, and atomic vs. non-atomic memory accesses. Along the way we will learn useful things about writing lock-free code in Standard C++.

Finally, we compare the tradeoffs between SeqLock and other approaches to this problem, offer some guidelines on which approach to use when, and present a proposal to add the SeqLock algorithm to the C++ Standard.

Timur Doumler

Timur Doumler is the co-host of CppCast and an active member of the ISO C++ standard committee, where he is currently co-chair of SG21, the Contracts study group. Timur started his journey into C++ in computational astrophysics, where he was working on cosmological simulations. He then moved into the audio and music technology industry, where he has spent over a decade of his career, worked on projects such as NI Kontakt and the JUCE framework, and co-founded the music tech startup Cradle. In the past, Timur also worked for JetBrains, first as a developer on CLion's C++ parser and later as a Developer Advocate for C++ developer tools. Currently, Timur lives in Finland, where he organises the monthly C++ Helsinki meetup and works as an independent C++ consultant. Timur is passionate about clean code, good tools, low latency, and the evolution of the C++ language.