SPMC Buffer: Triple-buffering for multiple consumers

On crates.io On docs.rs

What is this?

This is an extension of my earlier work on triple buffering, which supports readout from multiple consumers at the cost of some extra memory and CPU overhead. You may find it useful for the following class of thread synchronization problems:

It is currently used as follows:

```rust // Create an SPMC buffer of any Clone type use spmc_buffer::SPMCBuffer; let buf = SPMCBuffer::new(2, 1.0);

// Split it into an input and output interface let (mut bufinput, mut bufoutput) = buf.split();

// Create as many extra output interfaces as needed let mut bufoutput2 = bufoutput.clone();

// The producer can move a value into the buffer at any time buf_input.write(4.2);

// A consumer can access the latest value from the producer at any time let mut latestvalueref = bufoutput.read(); asserteq!(latest_value_ref, 4.2); let latest_value_ref2 = buf_output2.read(); assert_eq!(latestvalueref2, 4.2); ```

Give me details! How does it compare to alternatives?

Compared to a triple buffer an SPMC buffer...

In short, SPMC buffering is what you're after in scenarios where a shared memory location is updated frequently by a single writer, read by multiple reader who only wants the latest version, and you can spare some RAM.

How do I know your unsafe lock-free code is working?

By running the tests, of course! Which is unfortunately currently harder than I'd like it to be.

First of all, we have sequential tests, which are very thorough but obviously do not check the lock-free/synchronization part. You run them as follows:

$ cargo test --release

Then we have concurrent tests, where we fire up concurrent readers and writer threads and check that the readers can never observe an inconsistent buffer state. These tests are more important, but they are also harder to run because one must first check some assumptions:

Taking this and the relatively long run time (~10 s) into account, these tests are ignored by default.

Finally, we have benchmarks, which allow you to test how well the code is performing on your machine. Because cargo bench has not yet landed in Stable Rust, these benchmarks masquerade as tests, which make them a bit unpleasant to run. I apologize for the inconvenience.

To run the concurrent tests and the benchmarks, make sure no one is eating CPU in the background and do:

$ cargo test --release -- --ignored --test-threads=1

Here is a guide to interpreting the benchmark results:

On my laptop's CPU (Intel Core i7-4720HQ), typical results are as follows:

License

This crate is distributed under the terms of the LGPLv3 license. See the LICENSE-LGPL-3.0.md file for details.

More relaxed licensing (Apache, MIT, BSD...) may also be negociated, in exchange of a financial contribution. Contact me for details at knightsofni AT gmx DOTCOM.