Hi everyone,
I'm trying to implement a data structure of consecutive ring-buffers. Each ring buffer consists of a head and tail index, and a variable number of elements T. At any point in time, all ring-buffers contain the same capacity of elements.
I want the ring-buffers to sit consecutively in contiguous memory. So it should look something like this in memory: [ {head, tail}, MaybeUninit<T>, MaybeUninit<T>, MaybeUninit<T>, MaybeUninit<T>, {head, tail}, MaybeUninit<T>, MaybeUninit<T>, MaybeUninit<T>, MaybeUninit<T>, ... ]
. You could reason about this as a mixed-type vector, but I'm not sure if that's helpful.
I'm reaching out because I'm stumped on how to implement this data structure in Rust. I'm not sure how to do it safely, and also not sure how to do it unsafely.
Does anyone have any pointers or advice? If I were to do it unsafely, would I just go about doing it the way I would do it in C? If there are reference implementations in the wild of something similar, I would love to take a look.
I understand I can trivially implement this as a Vec<{head, tail, Vec<T>}>
, but I need to eliminate the pointers (Vec<T>
) to cut down on cache misses. I've also implemented a version like this: { offsets: Vec<{head, tail}>, data: Vec<T>}
, but we want the head and tail indexes to be co-located with their relevant data for cache locality. I'm currently benchmarking the two previous implementations to check these assumptions.
If I recall C correctly, I would need the following to be successful:
- pointer to allocated memory region
- size of memory region
- size of head and tail indexes
- size of data T
- number of elements T per ring-buffer
I could then use pointer arithmetic to access any individual ring-buffer in the region.
Thank you for reading all of this, I really appreciate it. I'm also happy to provide further explanations for my requirements.