extern crate lock_free_multi_produce_single_consume_ring_buffer; use ::lock_free_multi_produce_single_consume_ring_buffer::*; let (ring_buffer_consumer, ring_buffer_producers) = RingBuffer::new(capacity, number_of_producers); // For each producer thread. let ring_buffer_producer = ring_buffer_producers.get(0); let result = ring_buffer_producer.acquire(length); // result is `None` if length was too much; try a shorter length. let slice_guard = result.unwrap(); // Dereferences to a slice. // slice_guard = some_value; // Produce (relinquishes the slice). drop(slice_guard); ring_buffer_producer.produce(); // For each consumer thread. let slice_guard = ring_buffer_consumer.consume(); // Iterate, move out, etc. println!("should be `some_value`", slice_guard.move_out(slice_guard.len())); // Releases the slice so producers can now use it. drop(slice_guard);
Once all the producers and the consumer are dropped then the memory underlying the ring buffer is freed and any unconsumed items in it are safely
Atomic multi-producer single-consumer ring buffer, which supports contiguous range operations and which can be conveniently used for message passing.
There are three offsets ("think of clock hands"):-
NEXT: marks the beginning of the available space,
WRITTEN: the point up to which the data is actually written.
READY: point up to which data is ready to be written.
Observe and save the 'next' offset, then request
N bytes from the ring buffer by atomically advancing the
Once the data is written into the "reserved" buffer space, the thread clears the saved value; these observed values are used to compute the
Writes the data between
ready offsets and updates the
The consumer thread scans for the lowest seen value by the producers.
Producers cannot go beyond the
Producers are not allowed to catch up with the consumer.
Only the consumer is allowed to catch up with the producer, ie set the
written offset to be equal to the
If the producer cannot acquire the requested length due to little available space at the end of the buffer, then it will wraparound.
next offset is used to lock the
There is an ABA problem if one producer stalls while a pair of producer and consumer would both successfully wrap-around and set the
next offset to the stale value of the first producer, thus letting it to perform a successful compare-and-swap (CAS) violating the invariant.
A counter in the
next offset (masked by
WrapCounter) is used to prevent from this problem.
It is incremented on wraparounds.
The same ABA problem could also cause a stale
ready offset, which could be observed by the consumer.
The algorithm sets
WrapLockBit in the
seen value before advancing the
next and clears this bit after the successful advancing; this ensures that only the stable
ready observed by the consumer.
A ring buffer for sending lock-less bursts of messages.
A ring buffer consumer for receiving lock-less bursts of messages.
Use this to consume.
Produces bursts of messages to put into the ring buffer.
Use this to produce.