midir icon indicating copy to clipboard operation
midir copied to clipboard

Add example for multithread

Open hughrawlinson opened this issue 4 years ago • 4 comments

Hi! I'm having a hard time using midir in a threaded context. I'm using threads to model polyphony, as is typical in many synth implementations I've seen. I specifically don't know what is safe to share using Arc/Mutex. If nothing, I'm not sure how to be confident that I spin up a connection to the same port on a new thread. It looks like I can't share MidiOutputPorts between different instances of MidiOutput.

Or is it better to not use threading at all, and just keep a single thread, and handle scheduling of events?

Thanks for any insight!

hughrawlinson avatar Sep 08 '20 04:09 hughrawlinson

I specifically don't know what is safe to share using Arc/Mutex.

@hughrawlinson You should not need to worry about that. If your multi-threaded code compiles (and doesn't make use of unsafe), it is guaranteed by the library to be safe.

If you have problems getting your code to compile in multiple threads you can use the following strategy:

  • If an operation on an object consumes &self and the object is Sync wrap your object it in an Arc<_>.
  • If an operation on an object consumes &mut self or the object isn't Sync wrap your object in an Arc<Mutex<_>>

As a reference you can check out my synthesizer project https://crates.io/crates/microwave.

Woyten avatar Oct 23 '20 22:10 Woyten

Is there any question still open? Otherwise I'd close this issue.

Boddlnagg avatar Oct 31 '20 13:10 Boddlnagg

Thanks for getting back to me. That clarifies things a bit - although, I'm not sure exactly what the library guarantees to be safe. One remaining question is:

If I get a MidiOutputPort on the main thread, and pass it into another thread in the manner you described, and then I unplug the midi device, does that reference break somehow? If so, how do I catch that? Or is that not the kind of guarantee that the library makes?

I also think it would be good to have an example of this - either a specific contrived example like the other examples, or perhaps a link out to the crate you mentioned?

Thanks! 😄

hughrawlinson avatar Nov 02 '20 05:11 hughrawlinson

If I get a MidiOutputPort on the main thread, and pass it into another thread in the manner you described, and then ....

@hughrawlinson yeah, you should be able to safely run it on another thread and pass the messages somewhere else. I did a small example of this with tungstenite-rs server: https://github.com/snapview/tungstenite-rs/issues/122#issuecomment-733396645 . I am more familiar with functional languages than traditional systems programming, so if you have that background too it might help.

To be more specific I am shoveling the midi messages from midir to tungstenite, and everything works smoothly, no crashes etc. It uses all of 4MB of RAM when it's running and I'm just testing locally.

If I unplug the midi device, does that reference break somehow?

It's not currently possible to detect disconnected devices. In theory this can be added (at least on Linux). See #35 for more on unplugging the device.

avindra avatar Dec 01 '20 07:12 avindra