pub struct RingBuffer<T> { /* private fields */ }Expand description
pre-allocated ring buffer with runtime-configurable capacity.
the buffer stores events in a circular array. capacity must be a power of 2, which allows using bitwise AND instead of modulo for index calculations.
§type parameters
T- the event type to store
§example
use scatto::ringbuffer::RingBuffer;
// create a buffer for 1024 events
let buffer: RingBuffer<String> = RingBuffer::new(1024);
// with factory for pre-initialization
let buffer = RingBuffer::with_factory(1024, || String::with_capacity(256));Implementations§
Source§impl<T> RingBuffer<T>
impl<T> RingBuffer<T>
Sourcepub fn new(capacity: usize) -> Self
pub fn new(capacity: usize) -> Self
create a new ring buffer with the given capacity.
§arguments
capacity- number of slots (must be power of 2)
§panics
panics if capacity is not a power of 2 or is zero.
§example
use scatto::ringbuffer::RingBuffer;
let buffer: RingBuffer<u64> = RingBuffer::new(1024);
assert_eq!(buffer.capacity(), 1024);use scatto::ringbuffer::RingBuffer;
// this will panic - 100 is not a power of 2
let buffer: RingBuffer<u64> = RingBuffer::new(100);Sourcepub fn with_factory<F>(capacity: usize, factory: F) -> Selfwhere
F: Fn() -> T,
pub fn with_factory<F>(capacity: usize, factory: F) -> Selfwhere
F: Fn() -> T,
create a new ring buffer with pre-initialized slots.
the factory function is called once for each slot to initialize it.
this is useful for pre-allocating resources (e.g. Vec with capacity).
§arguments
capacity- number of slots (must be power of 2)factory- function to create initial values
§panics
panics if capacity is not a power of 2 or is zero.
§example
use scatto::ringbuffer::RingBuffer;
// Pre-allocate strings with capacity
let buffer = RingBuffer::with_factory(1024, || String::with_capacity(256));Sourcepub fn index(&self, sequence: i64) -> usize
pub fn index(&self, sequence: i64) -> usize
convert a sequence number to a slot index.
uses bitwise AND which is faster than modulo for power-of-2 sizes.
§example
use scatto::ringbuffer::RingBuffer;
let buffer: RingBuffer<u64> = RingBuffer::new(8);
assert_eq!(buffer.index(0), 0);
assert_eq!(buffer.index(7), 7);
assert_eq!(buffer.index(8), 0); // wraps around
assert_eq!(buffer.index(9), 1);Sourcepub unsafe fn get_ptr_mut(&self, sequence: i64) -> *mut T
pub unsafe fn get_ptr_mut(&self, sequence: i64) -> *mut T
get a raw mutable pointer to the slot at the given sequence.
§safety
the caller must ensure:
- exclusive access to this slot (no concurrent reads or writes)
- the slot index is valid
§example
use scatto::ringbuffer::RingBuffer;
let buffer: RingBuffer<u64> = RingBuffer::new(8);
unsafe {
let ptr = buffer.get_ptr_mut(0);
ptr.write(42);
}Sourcepub unsafe fn get_ptr(&self, sequence: i64) -> *const T
pub unsafe fn get_ptr(&self, sequence: i64) -> *const T
get a raw const pointer to the slot at the given sequence.
§safety
the caller must ensure:
- the slot has been initialized (written to)
- no concurrent writes to this slot
§example
use scatto::ringbuffer::RingBuffer;
let buffer: RingBuffer<u64> = RingBuffer::new(8);
unsafe {
buffer.write(0, 42);
let ptr = buffer.get_ptr(0);
assert_eq!(*ptr, 42);
}Sourcepub unsafe fn write(&self, sequence: i64, event: T)
pub unsafe fn write(&self, sequence: i64, event: T)
write an event to the slot at the given sequence.
this overwrites any existing value without dropping it.
for types that implement Drop, use write_and_drop.
§safety
the caller must ensure:
- exclusive access to this slot
- no concurrent reads while writing
§example
use scatto::ringbuffer::RingBuffer;
let buffer: RingBuffer<u64> = RingBuffer::new(8);
unsafe {
buffer.write(0, 100);
buffer.write(1, 200);
}Sourcepub unsafe fn write_and_drop(&self, sequence: i64, event: T)
pub unsafe fn write_and_drop(&self, sequence: i64, event: T)
write an event, dropping any existing value first.
use this for types that implement Drop when reusing slots.
§safety
the caller must ensure:
- exclusive access to this slot
- the slot was previously initialized (has a valid value to drop)
Sourcepub unsafe fn get(&self, sequence: i64) -> &T
pub unsafe fn get(&self, sequence: i64) -> &T
read a reference to the event at the given sequence.
§safety
the caller must ensure:
- the slot has been initialized
- no concurrent writes to this slot
- the returned reference does not outlive concurrent access constraints
§example
use scatto::ringbuffer::RingBuffer;
let buffer: RingBuffer<u64> = RingBuffer::new(8);
unsafe {
buffer.write(0, 42);
let value = buffer.get(0);
assert_eq!(*value, 42);
}Sourcepub unsafe fn get_mut(&self, sequence: i64) -> &mut T
pub unsafe fn get_mut(&self, sequence: i64) -> &mut T
get a mutable reference to the event at the given sequence.
this enables zero-copy in-place mutation.
§safety
the caller must ensure:
- exclusive access to this slot
- the slot has been initialized
- no concurrent reads or writes
§example
use scatto::ringbuffer::RingBuffer;
let buffer = RingBuffer::with_factory(8, || String::new());
unsafe {
// zero-copy: modify the event in place
let event = buffer.get_mut(0);
event.push_str("hello");
assert_eq!(buffer.get(0), "hello");
}Sourcepub unsafe fn read(&self, sequence: i64) -> T
pub unsafe fn read(&self, sequence: i64) -> T
read and move the event out of the slot.
this performs a ptr::read which moves ownership to the caller.
the slot is left in an uninitialized state.
§safety
the caller must ensure:
- she slot has been initialized
- no concurrent access to this slot
- the slot wont be read again without being rewritten