BBQueue Storage Work
Use cases
Current: "Embedded Use Case"
- Statically allocate storage
- BBBuffer lives forever
- User uses Producer and Consumer
Future:
- Have the STORAGE for BBBuffer be provided seperately
- Allow for uses like:
- Statically allocated storage (like now)
- Heap Allocation provided storage (Arc, etc.)
- User provided storage (probably
unsafe
)
Sample Code for Use Cases
Static Buffer
static BB_QUEUE: BBQueue<OwnedBBBuffer<1024>> = BBQueue::new(OwnedBBBuffer::new()); fn main() { let (prod, cons) = BB_QUEUE.try_split().unwrap(); // ... }
Heap Allocation provided storage
Choice A: Simple
fn main() { // BBQueue<Arc<BBBuffer<1024>> // Producer<Arc<BBBuffer<1024>>, Consumer<Arc<BBBuffer<1024>> // // Storage is dropped when `prod` and `cons` are BOTH dropped. let (prod, cons) = BBQueue::new_arc::<1024>(); }
Choice B: Explicit
fn main() { // EDIT: This is sub-par, because this would require `arc_queue`, // `prod`, and `storage` to ALL be dropped // before the buffer is dropped. let arc_queue: BBQueue<Arc<BBBuffer<1024>> = BBStorage::new_arc(); let (prod, cons) = arc_queue.try_split().unwrap(); }
NOTE: This is not yet possible as of the current state of the repo. I do intent do support it.
User provided storage
Choice A: Naive
EDIT: Not this. See below
static mut UNSAFE_BUFFER: [u8; 1024] = [0u8; 1024]; fn main() { let borrowed = unsafe { // TODO: Make sure BBQueue has lifetime shorter // than `'borrowed` here? In this case it is // 'static, but may not always be. BBStorageBorrowed::new(&mut UNSAFE_BUFFER); }; let bbqueue = BBQueue::new(borrowed); // NOTE: This is NOT good, because the bound lifetime // of prod and cons will be that of `bbqueue`, which // is probably not suitable (non-'static). In many cases, we want // the producer and consumer to also have `Producer<'static>` lifetime let (prod, cons) = bbqueue.try_split().unwrap(); }
Choice B: "loadable" storage?
This would require EITHER:
- The BBStorage methods are failable
- The split belongs to the BBStorage item
- (Could be an inherent or trait method)
- Loadable storage panics on a split if not loaded
static mut UNSAFE_BUFFER: [u8; 1024] = [0u8; 1024]; static LOADABLE_BORROWED: BBStorageLoadBorrow::new(); fn main() { // This could probably be shortened to a single "store and take header" action. // Done in multiple steps here for clarity. let mut_buf = unsafe { &mut UNSAFE_BUFFER }; let old = LOADABLE_BORROWED.store(); // -> Result<Option<&mut [u8]>> // Result: Err if already taken // Option: Some if other buffer already stored assert_eq!(Ok(None), old); let bbqueue = BBQueue::new(LOADABLE_BORROWED.take_header().unwrap()); // Here prod and cons are <'static>, because LOADABLE_BORROWED is static. // BUUUUUT we still probably allow access of BBStorage methods, which would be totally unsafe // // EDIT: Okay, sealing the trait DOES prevent outer usage, so we're good on this regard! let (prod, cons) = bbqueue.try_split().unwrap(); }
NOTE: This is not yet possible as of the current state of the repo. I do intent do support it.