Skip to content

Real-time safety issues by using RwLock #2

Description

@CrushedPixel

Hey Jimmy,

first of all, let me thank you for writing these blog posts.
They are insanely helpful and got me started writing CLAP plugins in Rust! I now have my own framework on top of clack and it's all because you gave me a good starting point for this library, so thanks a ton. :)

Unfortunately, there is one major issue with what you're teaching in Part 2 - you are putting plugin state into the Shared struct, and wrap it in an RwLock to make it Send and Sync as per the requirements.

Using mutexes/locks is, however, not real-time safe! The audio thread must never wait for anything, especially not for a lower-priority thread such as the main thread. For a detailed explanation, please refer to this amazing article on real-time safety, paragraph "Locking": http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing

There are two alternatives:

  • using two lock-free queues (e.g. ringbuf) to transmit state changes between threads, and polling for changes in process and flush on the audio thread, and on_main_thread and flush on the main thread. You create the queues in activate and store the respective senders/receivers on the main and audio thread struct, and destroy them again in deactivate. In this scenario, there's no need for a Shared struct at all. This is what I am doing in my plugins.

  • using atomic floats (e.g. via the atomic_float crate) for each property, and storing them at the top level of your Shared struct. This is the variant that's a lot easier to implement in your existing code, but you'll have to get rid of your Envelope struct.

I think it would be good to amend your article to avoid teaching wrong patterns to less experienced developers.

Feel free to ask if you have any questions or if I can help in any way :)

Best,
Marius

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions