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.