From fc66dbce60ffd38a2094339a18953e017a3d48ad Mon Sep 17 00:00:00 2001 From: ZK Date: Mon, 25 May 2020 23:17:08 +0100 Subject: [PATCH 1/4] First pass at trying BBQueue at supporting a generic type Tests seem to be passing when type is u8, plain old data or Clone --- bbqtest/src/benches.rs | 4 +- bbqtest/src/lib.rs | 20 +-- bbqtest/src/multi_thread.rs | 10 +- bbqtest/src/ring_around_the_senders.rs | 59 ++++---- bbqtest/src/single_thread.rs | 89 +++++++++++- core/src/bbbuffer.rs | 184 ++++++++++++++----------- core/src/framed.rs | 8 +- 7 files changed, 246 insertions(+), 128 deletions(-) diff --git a/bbqtest/src/benches.rs b/bbqtest/src/benches.rs index 689607b..123cd0a 100644 --- a/bbqtest/src/benches.rs +++ b/bbqtest/src/benches.rs @@ -17,7 +17,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { c.bench_function("bbq 2048/4096", |bench| bench.iter(|| chunky(&data, 2048))); - let buffy: BBBuffer = BBBuffer::new(); + let buffy: BBBuffer = BBBuffer::new(); let (mut prod, mut cons) = buffy.try_split().unwrap(); c.bench_function("bbq 8192/65536", |bench| { @@ -196,7 +196,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { use crossbeam_utils::thread; fn chunky(data: &[u8], chunksz: usize) { - let buffy: BBBuffer = BBBuffer::new(); + let buffy: BBBuffer = BBBuffer::new(); let (mut prod, mut cons) = buffy.try_split().unwrap(); thread::scope(|sc| { diff --git a/bbqtest/src/lib.rs b/bbqtest/src/lib.rs index ec9d3b4..8f4c6fc 100644 --- a/bbqtest/src/lib.rs +++ b/bbqtest/src/lib.rs @@ -11,7 +11,7 @@ mod tests { #[test] fn deref_deref_mut() { - let bb: BBBuffer = BBBuffer::new(); + let bb: BBBuffer = BBBuffer::new(); let (mut prod, mut cons) = bb.try_split().unwrap(); let mut wgr = prod.grant_exact(1).unwrap(); @@ -34,8 +34,8 @@ mod tests { #[test] fn static_allocator() { // Check we can make multiple static items... - static BBQ1: BBBuffer = BBBuffer(ConstBBBuffer::new()); - static BBQ2: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BBQ1: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BBQ2: BBBuffer = BBBuffer(ConstBBBuffer::new()); let (mut prod1, mut cons1) = BBQ1.try_split().unwrap(); let (mut _prod2, mut cons2) = BBQ2.try_split().unwrap(); @@ -55,8 +55,8 @@ mod tests { #[test] fn release() { // Check we can make multiple static items... - static BBQ1: BBBuffer = BBBuffer(ConstBBBuffer::new()); - static BBQ2: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BBQ1: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BBQ2: BBBuffer = BBBuffer(ConstBBBuffer::new()); let (prod1, cons1) = BBQ1.try_split().unwrap(); let (prod2, cons2) = BBQ2.try_split().unwrap(); @@ -93,7 +93,7 @@ mod tests { #[test] fn direct_usage_sanity() { // Initialize - let bb: BBBuffer = BBBuffer::new(); + let bb: BBBuffer = BBBuffer::new(); let (mut prod, mut cons) = bb.try_split().unwrap(); assert_eq!(cons.read(), Err(BBQError::InsufficientSize)); @@ -178,7 +178,7 @@ mod tests { #[test] fn zero_sized_grant() { - let bb: BBBuffer = BBBuffer::new(); + let bb: BBBuffer = BBBuffer::new(); let (mut prod, mut _cons) = bb.try_split().unwrap(); let size = 1000; @@ -191,7 +191,7 @@ mod tests { #[test] fn frame_sanity() { - let bb: BBBuffer = BBBuffer::new(); + let bb: BBBuffer = BBBuffer::new(); let (mut prod, mut cons) = bb.try_split_framed().unwrap(); // One frame in, one frame out @@ -238,7 +238,7 @@ mod tests { #[test] fn frame_wrap() { - let bb: BBBuffer = BBBuffer::new(); + let bb: BBBuffer = BBBuffer::new(); let (mut prod, mut cons) = bb.try_split_framed().unwrap(); // 10 + 1 used @@ -304,7 +304,7 @@ mod tests { #[test] fn frame_big_little() { - let bb: BBBuffer = BBBuffer::new(); + let bb: BBBuffer = BBBuffer::new(); let (mut prod, mut cons) = bb.try_split_framed().unwrap(); // Create a frame that should take 3 bytes for the header diff --git a/bbqtest/src/multi_thread.rs b/bbqtest/src/multi_thread.rs index a9aff77..d420fc7 100644 --- a/bbqtest/src/multi_thread.rs +++ b/bbqtest/src/multi_thread.rs @@ -13,6 +13,8 @@ mod tests { const RPT_IVAL: usize = ITERS / 100; + // Data type + type DataTy = u8; // These two should be the same type QueueSizeTy = U1024; const QUEUE_SIZE: usize = 1024; @@ -29,7 +31,7 @@ mod tests { println!("RTX: Generating Test Data..."); let gen_start = Instant::now(); let mut data = Vec::with_capacity(ITERS); - (0..ITERS).for_each(|_| data.push(rand::random::())); + (0..ITERS).for_each(|_| data.push(rand::random::())); let mut data_rx = data.clone(); let mut trng = thread_rng(); @@ -50,7 +52,7 @@ mod tests { #[cfg(feature = "verbose")] println!("RTX: Running test..."); - static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); let (mut tx, mut rx) = BB.try_split().unwrap(); let mut last_tx = Instant::now(); @@ -142,7 +144,7 @@ mod tests { #[test] fn sanity_check() { - static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); let (mut tx, mut rx) = BB.try_split().unwrap(); let mut last_tx = Instant::now(); @@ -236,7 +238,7 @@ mod tests { #[test] fn sanity_check_grant_max() { - static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); let (mut tx, mut rx) = BB.try_split().unwrap(); #[cfg(feature = "verbose")] diff --git a/bbqtest/src/ring_around_the_senders.rs b/bbqtest/src/ring_around_the_senders.rs index c689a2d..5834ea5 100644 --- a/bbqtest/src/ring_around_the_senders.rs +++ b/bbqtest/src/ring_around_the_senders.rs @@ -1,18 +1,22 @@ #[cfg(test)] mod tests { + use core::convert::TryFrom; + use core::fmt::Debug; + use bbqueue::{ consts::*, ArrayLength, BBBuffer, ConstBBBuffer, Consumer, GrantR, GrantW, Producer, }; - enum Potato<'a, N> + enum Potato<'a, T, N> where - N: ArrayLength, + T: Sized + TryFrom, + N: ArrayLength, { - Tx((Producer<'a, N>, u8)), - Rx((Consumer<'a, N>, u8)), - TxG(GrantW<'a, N>), - RxG(GrantR<'a, N>), + Tx((Producer<'a, T, N>, u8)), + Rx((Consumer<'a, T, N>, u8)), + TxG(GrantW<'a, T, N>), + RxG(GrantR<'a, T, N>), Idle, Done, } @@ -28,9 +32,10 @@ mod tests { const BYTES_PER_GRANT: usize = 129; type BufferSize = U4096; - impl<'a, N> Potato<'a, N> + impl<'a, T, N> Potato<'a, T, N> where - N: ArrayLength, + T: Sized + TryFrom + Debug + PartialEq, + N: ArrayLength, { fn work(self) -> (Self, Self) { match self { @@ -66,7 +71,7 @@ mod tests { gr_w.iter_mut() .take(BYTES_PER_GRANT) .enumerate() - .for_each(|(i, by)| *by = i as u8); + .for_each(|(i, by)| *by = T::try_from(i).ok().expect("can construct from usize")); gr_w.commit(BYTES_PER_GRANT); (Self::Idle, Self::Idle) } @@ -74,7 +79,7 @@ mod tests { gr_r.iter() .take(BYTES_PER_GRANT) .enumerate() - .for_each(|(i, by)| assert_eq!(*by, i as u8)); + .for_each(|(i, by)| assert_eq!(*by, T::try_from(i).ok().expect("can construct from usize"))); gr_r.release(BYTES_PER_GRANT); (Self::Idle, Self::Idle) } @@ -84,31 +89,37 @@ mod tests { } } - static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); + // Data type + type DataTy = u8; + static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); use std::sync::mpsc::{channel, Receiver, Sender}; use std::thread::spawn; #[test] fn hello() { - let (prod, cons) = BB.try_split().unwrap(); + generic_hello::(&BB); + } + + fn generic_hello(bb: &'static BBBuffer) where T: Sized + TryFrom + Debug + PartialEq { + let (prod, cons) = bb.try_split().unwrap(); // create the channels let (tx_1_2, rx_1_2): ( - Sender>, - Receiver>, + Sender>, + Receiver>, ) = channel(); let (tx_2_3, rx_2_3): ( - Sender>, - Receiver>, + Sender>, + Receiver>, ) = channel(); let (tx_3_4, rx_3_4): ( - Sender>, - Receiver>, + Sender>, + Receiver>, ) = channel(); let (tx_4_1, rx_4_1): ( - Sender>, - Receiver>, + Sender>, + Receiver>, ) = channel(); tx_1_2.send(Potato::Tx((prod, 3))).unwrap(); @@ -116,7 +127,7 @@ mod tests { let thread_1 = spawn(move || { let mut count = TOTAL_RINGS; - let mut me: Potato<'static, BufferSize> = Potato::Idle; + let mut me: Potato<'static, T, BufferSize> = Potato::Idle; loop { if let Potato::Idle = me { @@ -168,9 +179,9 @@ mod tests { }); let closure_2_3_4 = - move |rx: Receiver>, - tx: Sender>| { - let mut me: Potato<'static, BufferSize> = Potato::Idle; + move |rx: Receiver>, + tx: Sender>| { + let mut me: Potato<'static, T, BufferSize> = Potato::Idle; let mut count = 0; loop { diff --git a/bbqtest/src/single_thread.rs b/bbqtest/src/single_thread.rs index 9f8ee52..bcab0cb 100644 --- a/bbqtest/src/single_thread.rs +++ b/bbqtest/src/single_thread.rs @@ -1,16 +1,97 @@ #[cfg(test)] mod tests { + use std::fmt::Debug; + use core::convert::TryFrom; + use bbqueue::{consts::*, BBBuffer}; #[test] - fn sanity_check() { - let bb: BBBuffer = BBBuffer::new(); + fn sanity_check_u8() { + generic_sanity_check::(); + } + + #[test] + fn sanity_check_pod() { + generic_sanity_check::(); + generic_sanity_check::(); + } + + #[derive(Debug, Clone, Copy, PartialEq)] + struct U8Sized(u8); + + impl From for U8Sized { + fn from(v: u8) -> Self { + U8Sized(v) + } + } + + // TODO: tailor this to address specific error cases if any + #[derive(Debug, Clone, Copy, PartialEq)] + struct PodStruct { + array: [u8; 32], + variants: PodEnum, + } + + impl From for PodStruct { + fn from(v: u8) -> Self { + PodStruct { + array: [v; 32], + variants: PodEnum::from(v), + } + } + } + + #[derive(Debug, Clone, Copy, PartialEq)] + enum PodEnum { + Empty, + Tuple((u64, i64, usize)), + Array([i16; 16]) + } + + impl From for PodEnum { + fn from(v: u8) -> Self { + if v == 0 { + Self::Empty + } else if v < 128 { + Self::Tuple((v as u64, (v + 1) as i64, (v + 2) as usize)) + } else { + Self::Array([v as i16; 16]) + } + } + } + + #[test] + fn sanity_check_ptr() { + generic_sanity_check::(); + } + + #[derive(Debug, Clone, PartialEq)] + struct RefStruct { + vec: Vec, + maybe_boxed: Option>, + } + + impl From for RefStruct { + fn from(v: u8) -> Self { + let mut vec = Vec::with_capacity(v as usize); + vec.iter_mut().for_each(|e| *e = v); + + let maybe_boxed = Some(Box::new(RefStruct{ vec: vec.clone(), maybe_boxed: None })); + RefStruct { + vec, + maybe_boxed + } + } + } + + fn generic_sanity_check() where T: Sized + TryFrom + Debug + PartialEq + Clone { + let bb: BBBuffer = BBBuffer::new(); let (mut prod, mut cons) = bb.try_split().unwrap(); const ITERS: usize = 100000; for i in 0..ITERS { - let j = (i & 255) as u8; + let j = T::try_from((i & 255) as u8).ok().expect("can construct type from u8"); #[cfg(feature = "extra-verbose")] println!("==========================="); @@ -27,7 +108,7 @@ mod tests { #[cfg(feature = "extra-verbose")] println!("GRANT: {:?}", bb); - wgr[0] = j; + wgr[0] = j.clone(); #[cfg(feature = "extra-verbose")] println!("WRITE: {:?}", bb); diff --git a/core/src/bbbuffer.rs b/core/src/bbbuffer.rs index b2ee285..b6d8bcc 100644 --- a/core/src/bbbuffer.rs +++ b/core/src/bbbuffer.rs @@ -22,16 +22,18 @@ use generic_array::{ArrayLength, GenericArray}; /// A backing structure for a BBQueue. Can be used to create either /// a BBQueue or a split Producer/Consumer pair -pub struct BBBuffer>( +#[derive(Debug)] +pub struct BBBuffer>( // Underlying data storage - #[doc(hidden)] pub ConstBBBuffer>, + #[doc(hidden)] pub ConstBBBuffer>, ); unsafe impl Sync for ConstBBBuffer {} -impl<'a, N> BBBuffer +impl<'a, T, N> BBBuffer where - N: ArrayLength, + T: Sized, + N: ArrayLength, { /// Attempt to split the `BBBuffer` into `Consumer` and `Producer` halves to gain access to the /// buffer. If buffer has already been split, an error will be returned. @@ -64,7 +66,7 @@ where /// # bbqtest(); /// # } /// ``` - pub fn try_split(&'a self) -> Result<(Producer<'a, N>, Consumer<'a, N>)> { + pub fn try_split(&'a self) -> Result<(Producer<'a, T, N>, Consumer<'a, T, N>)> { if atomic::swap(&self.0.already_split, true, AcqRel) { return Err(Error::AlreadySplit); } @@ -92,23 +94,6 @@ where } } - /// Attempt to split the `BBBuffer` into `FrameConsumer` and `FrameProducer` halves - /// to gain access to the buffer. If buffer has already been split, an error - /// will be returned. - /// - /// NOTE: When splitting, the underlying buffer will be explicitly initialized - /// to zero. This may take a measurable amount of time, depending on the size - /// of the buffer. This is necessary to prevent undefined behavior. If the buffer - /// is placed at `static` scope within the `.bss` region, the explicit initialization - /// will be elided (as it is already performed as part of memory initialization) - /// - /// NOTE: If the `thumbv6` feature is selected, this function takes a short critical - /// section while splitting. - pub fn try_split_framed(&'a self) -> Result<(FrameProducer<'a, N>, FrameConsumer<'a, N>)> { - let (producer, consumer) = self.try_split()?; - Ok((FrameProducer { producer }, FrameConsumer { consumer })) - } - /// Attempt to release the Producer and Consumer /// /// This re-initializes the buffer so it may be split in a different mode at a later @@ -144,9 +129,9 @@ where /// ``` pub fn try_release( &'a self, - prod: Producer<'a, N>, - cons: Consumer<'a, N>, - ) -> CoreResult<(), (Producer<'a, N>, Consumer<'a, N>)> { + prod: Producer<'a, T, N>, + cons: Consumer<'a, T, N>, + ) -> CoreResult<(), (Producer<'a, T, N>, Consumer<'a, T, N>)> { // Note: Re-entrancy is not possible because we require ownership // of the producer and consumer, which are not cloneable. We also // can assume the buffer has been split, because @@ -183,6 +168,28 @@ where Ok(()) } +} + +impl<'a, N> BBBuffer +where + N: ArrayLength, +{ + /// Attempt to split the `BBBuffer` into `FrameConsumer` and `FrameProducer` halves + /// to gain access to the buffer. If buffer has already been split, an error + /// will be returned. + /// + /// NOTE: When splitting, the underlying buffer will be explicitly initialized + /// to zero. This may take a measurable amount of time, depending on the size + /// of the buffer. This is necessary to prevent undefined behavior. If the buffer + /// is placed at `static` scope within the `.bss` region, the explicit initialization + /// will be elided (as it is already performed as part of memory initialization) + /// + /// NOTE: If the `thumbv6` feature is selected, this function takes a short critical + /// section while splitting. + pub fn try_split_framed(&'a self) -> Result<(FrameProducer<'a, N>, FrameConsumer<'a, N>)> { + let (producer, consumer) = self.try_split()?; + Ok((FrameProducer { producer }, FrameConsumer { consumer })) + } /// Attempt to release the Producer and Consumer in Framed mode /// @@ -210,6 +217,7 @@ where /// scope, and is generally never used directly. This process is necessary to /// work around current limitations in `const fn`, and will be replaced in /// the future. +#[derive(Debug)] pub struct ConstBBBuffer { buf: UnsafeCell>, @@ -322,19 +330,21 @@ impl ConstBBBuffer { /// /// See [this github issue](/~https://github.com/jamesmunns/bbqueue/issues/38) for a /// discussion of grant methods that could be added in the future. -pub struct Producer<'a, N> +pub struct Producer<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { - bbq: NonNull>, + bbq: NonNull>, pd: PhantomData<&'a ()>, } -unsafe impl<'a, N> Send for Producer<'a, N> where N: ArrayLength {} +unsafe impl<'a, T, N> Send for Producer<'a, T, N> where T: Sized, N: ArrayLength {} -impl<'a, N> Producer<'a, N> +impl<'a, T, N> Producer<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { /// Request a writable, contiguous section of memory of exactly /// `sz` bytes. If the buffer size requested is not available, @@ -368,7 +378,7 @@ where /// # bbqtest(); /// # } /// ``` - pub fn grant_exact(&mut self, sz: usize) -> Result> { + pub fn grant_exact(&mut self, sz: usize) -> Result> { let inner = unsafe { &self.bbq.as_ref().0 }; if atomic::swap(&inner.write_in_progress, true, AcqRel) { @@ -417,7 +427,7 @@ where // This is sound, as UnsafeCell, MaybeUninit, and GenericArray // are all `#[repr(Transparent)] - let start_of_buf_ptr = inner.buf.get().cast::(); + let start_of_buf_ptr = inner.buf.get().cast::(); let grant_slice = unsafe { from_raw_parts_mut(start_of_buf_ptr.offset(start as isize), sz) }; @@ -465,7 +475,7 @@ where /// # bbqtest(); /// # } /// ``` - pub fn grant_max_remaining(&mut self, mut sz: usize) -> Result> { + pub fn grant_max_remaining(&mut self, mut sz: usize) -> Result> { let inner = unsafe { &self.bbq.as_ref().0 }; if atomic::swap(&inner.write_in_progress, true, AcqRel) { @@ -519,7 +529,7 @@ where // This is sound, as UnsafeCell, MaybeUninit, and GenericArray // are all `#[repr(Transparent)] - let start_of_buf_ptr = inner.buf.get().cast::(); + let start_of_buf_ptr = inner.buf.get().cast::(); let grant_slice = unsafe { from_raw_parts_mut(start_of_buf_ptr.offset(start as isize), sz) }; @@ -531,19 +541,21 @@ where } /// `Consumer` is the primary interface for reading data from a `BBBuffer`. -pub struct Consumer<'a, N> +pub struct Consumer<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { - bbq: NonNull>, + bbq: NonNull>, pd: PhantomData<&'a ()>, } -unsafe impl<'a, N> Send for Consumer<'a, N> where N: ArrayLength {} +unsafe impl<'a, T, N> Send for Consumer<'a, T, N> where T: Sized, N: ArrayLength {} -impl<'a, N> Consumer<'a, N> +impl<'a, T, N> Consumer<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { /// Obtains a contiguous slice of committed bytes. This slice may not /// contain ALL available bytes, if the writer has wrapped around. The @@ -575,7 +587,7 @@ where /// # bbqtest(); /// # } /// ``` - pub fn read(&mut self) -> Result> { + pub fn read(&mut self) -> Result> { let inner = unsafe { &self.bbq.as_ref().0 }; if atomic::swap(&inner.read_in_progress, true, AcqRel) { @@ -615,7 +627,7 @@ where // This is sound, as UnsafeCell, MaybeUninit, and GenericArray // are all `#[repr(Transparent)] - let start_of_buf_ptr = inner.buf.get().cast::(); + let start_of_buf_ptr = inner.buf.get().cast::(); let grant_slice = unsafe { from_raw_parts(start_of_buf_ptr.offset(read as isize), sz) }; Ok(GrantR { @@ -625,9 +637,10 @@ where } } -impl BBBuffer +impl BBBuffer where - N: ArrayLength, + T: Sized, + N: ArrayLength, { /// Returns the size of the backing storage. /// @@ -654,9 +667,10 @@ where } } -impl BBBuffer +impl BBBuffer where - N: ArrayLength, + T: Sized, + N: ArrayLength, { /// Create a new bbqueue /// @@ -690,15 +704,16 @@ where /// If the `thumbv6` feature is selected, dropping the grant /// without committing it takes a short critical section, #[derive(Debug, PartialEq)] -pub struct GrantW<'a, N> +pub struct GrantW<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { - pub(crate) buf: &'a mut [u8], - bbq: NonNull>, + pub(crate) buf: &'a mut [T], + bbq: NonNull>, } -unsafe impl<'a, N> Send for GrantW<'a, N> where N: ArrayLength {} +unsafe impl<'a, T, N> Send for GrantW<'a, T, N> where T: Sized, N: ArrayLength {} /// A structure representing a contiguous region of memory that /// may be read from, and potentially "released" (or cleared) @@ -709,19 +724,21 @@ unsafe impl<'a, N> Send for GrantW<'a, N> where N: ArrayLength {} /// If the `thumbv6` feature is selected, dropping the grant /// without releasing it takes a short critical section, #[derive(Debug, PartialEq)] -pub struct GrantR<'a, N> +pub struct GrantR<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { - pub(crate) buf: &'a [u8], - bbq: NonNull>, + pub(crate) buf: &'a [T], + bbq: NonNull>, } -unsafe impl<'a, N> Send for GrantR<'a, N> where N: ArrayLength {} +unsafe impl<'a, T, N> Send for GrantR<'a, T, N> where T: Sized, N: ArrayLength {} -impl<'a, N> GrantW<'a, N> +impl<'a, T, N> GrantW<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { /// Finalizes a writable grant given by `grant()` or `grant_max()`. /// This makes the data available to be read via `read()`. This consumes @@ -760,7 +777,7 @@ where /// # bbqtest(); /// # } /// ``` - pub fn buf(&mut self) -> &mut [u8] { + pub fn buf(&mut self) -> &mut [T] { self.buf } @@ -775,8 +792,8 @@ where /// /// Additionally, you must ensure that a separate reference to this data is not created /// to this data, e.g. using `DerefMut` or the `buf()` method of this grant. - pub unsafe fn as_static_mut_buf(&mut self) -> &'static mut [u8] { - transmute::<&mut [u8], &'static mut [u8]>(self.buf) + pub unsafe fn as_static_mut_buf(&mut self) -> &'static mut [T] { + transmute::<&mut [T], &'static mut [T]>(self.buf) } #[inline(always)] @@ -826,9 +843,10 @@ where } } -impl<'a, N> GrantR<'a, N> +impl<'a, T, N> GrantR<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { /// Release a sequence of bytes from the buffer, allowing the space /// to be used by later writes. This consumes the grant. @@ -846,6 +864,7 @@ where forget(self); } + #[allow(dead_code)] pub(crate) fn shrink(&mut self, len: usize) { self.buf = &self.buf[..len]; } @@ -879,7 +898,7 @@ where /// # bbqtest(); /// # } /// ``` - pub fn buf(&self) -> &[u8] { + pub fn buf(&self) -> &[T] { self.buf } @@ -894,8 +913,8 @@ where /// /// Additionally, you must ensure that a separate reference to this data is not created /// to this data, e.g. using `Deref` or the `buf()` method of this grant. - pub unsafe fn as_static_buf(&self) -> &'static [u8] { - transmute::<&[u8], &'static [u8]>(self.buf) + pub unsafe fn as_static_buf(&self) -> &'static [T] { + transmute::<&[T], &'static [T]>(self.buf) } #[inline(always)] @@ -912,49 +931,54 @@ where } } -impl<'a, N> Drop for GrantW<'a, N> +impl<'a, T, N> Drop for GrantW<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { fn drop(&mut self) { self.commit_inner(0) } } -impl<'a, N> Drop for GrantR<'a, N> +impl<'a, T, N> Drop for GrantR<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { fn drop(&mut self) { self.release_inner(0) } } -impl<'a, N> Deref for GrantW<'a, N> +impl<'a, T, N> Deref for GrantW<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { - type Target = [u8]; + type Target = [T]; fn deref(&self) -> &Self::Target { self.buf } } -impl<'a, N> DerefMut for GrantW<'a, N> +impl<'a, T, N> DerefMut for GrantW<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { - fn deref_mut(&mut self) -> &mut [u8] { + fn deref_mut(&mut self) -> &mut [T] { self.buf } } -impl<'a, N> Deref for GrantR<'a, N> +impl<'a, T, N> Deref for GrantR<'a, T, N> where - N: ArrayLength, + T: Sized, + N: ArrayLength, { - type Target = [u8]; + type Target = [T]; fn deref(&self) -> &Self::Target { self.buf diff --git a/core/src/framed.rs b/core/src/framed.rs index 2daf8a1..e2db4eb 100644 --- a/core/src/framed.rs +++ b/core/src/framed.rs @@ -88,7 +88,7 @@ pub struct FrameProducer<'a, N> where N: ArrayLength, { - pub(crate) producer: Producer<'a, N>, + pub(crate) producer: Producer<'a, u8, N>, } impl<'a, N> FrameProducer<'a, N> @@ -113,7 +113,7 @@ pub struct FrameConsumer<'a, N> where N: ArrayLength, { - pub(crate) consumer: Consumer<'a, N>, + pub(crate) consumer: Consumer<'a, u8, N>, } impl<'a, N> FrameConsumer<'a, N> @@ -156,7 +156,7 @@ pub struct FrameGrantW<'a, N> where N: ArrayLength, { - grant_w: GrantW<'a, N>, + grant_w: GrantW<'a, u8, N>, hdr_len: u8, } @@ -169,7 +169,7 @@ pub struct FrameGrantR<'a, N> where N: ArrayLength, { - grant_r: GrantR<'a, N>, + grant_r: GrantR<'a, u8, N>, hdr_len: u8, } From 8cb6e117278af5bff194a4fed66af3123213aab3 Mon Sep 17 00:00:00 2001 From: ZK Date: Mon, 25 May 2020 23:30:46 +0100 Subject: [PATCH 2/4] Fix doctests --- core/src/bbbuffer.rs | 20 ++++++++++---------- core/src/framed.rs | 2 +- core/src/lib.rs | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/src/bbbuffer.rs b/core/src/bbbuffer.rs index b6d8bcc..893456c 100644 --- a/core/src/bbbuffer.rs +++ b/core/src/bbbuffer.rs @@ -53,7 +53,7 @@ where /// use bbqueue::{BBBuffer, consts::*}; /// /// // Create and split a new buffer - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: BBBuffer = BBBuffer::new(); /// let (prod, cons) = buffer.try_split().unwrap(); /// /// // Not possible to split twice @@ -108,7 +108,7 @@ where /// use bbqueue::{BBBuffer, consts::*}; /// /// // Create and split a new buffer - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: BBBuffer = BBBuffer::new(); /// let (prod, cons) = buffer.try_split().unwrap(); /// /// // Not possible to split twice @@ -261,7 +261,7 @@ impl ConstBBBuffer { /// ```rust,no_run /// use bbqueue::{BBBuffer, ConstBBBuffer, consts::*}; /// - /// static BUF: BBBuffer = BBBuffer( ConstBBBuffer::new() ); + /// static BUF: BBBuffer = BBBuffer( ConstBBBuffer::new() ); /// /// fn main() { /// let (prod, cons) = BUF.try_split().unwrap(); @@ -360,7 +360,7 @@ where /// use bbqueue::{BBBuffer, consts::*}; /// /// // Create and split a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: BBBuffer = BBBuffer::new(); /// let (mut prod, cons) = buffer.try_split().unwrap(); /// /// // Successfully obtain and commit a grant of four bytes @@ -450,7 +450,7 @@ where /// use bbqueue::{BBBuffer, consts::*}; /// /// // Create and split a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: BBBuffer = BBBuffer::new(); /// let (mut prod, mut cons) = buffer.try_split().unwrap(); /// /// // Successfully obtain and commit a grant of four bytes @@ -568,7 +568,7 @@ where /// use bbqueue::{BBBuffer, consts::*}; /// /// // Create and split a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: BBBuffer = BBBuffer::new(); /// let (mut prod, mut cons) = buffer.try_split().unwrap(); /// /// // Successfully obtain and commit a grant of four bytes @@ -652,7 +652,7 @@ where /// use bbqueue::{BBBuffer, consts::*}; /// /// // Create a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: BBBuffer = BBBuffer::new(); /// assert_eq!(buffer.capacity(), 6); /// # // bbqueue test shim! /// # } @@ -682,7 +682,7 @@ where /// use bbqueue::{BBBuffer, consts::*}; /// /// // Create a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: BBBuffer = BBBuffer::new(); /// # // bbqueue test shim! /// # } /// # @@ -762,7 +762,7 @@ where /// use bbqueue::{BBBuffer, consts::*}; /// /// // Create and split a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: BBBuffer = BBBuffer::new(); /// let (mut prod, mut cons) = buffer.try_split().unwrap(); /// /// // Successfully obtain and commit a grant of four bytes @@ -877,7 +877,7 @@ where /// use bbqueue::{BBBuffer, consts::*}; /// /// // Create and split a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: BBBuffer = BBBuffer::new(); /// let (mut prod, mut cons) = buffer.try_split().unwrap(); /// /// // Successfully obtain and commit a grant of four bytes diff --git a/core/src/framed.rs b/core/src/framed.rs index e2db4eb..5804d93 100644 --- a/core/src/framed.rs +++ b/core/src/framed.rs @@ -13,7 +13,7 @@ //! # fn bbqtest() { //! use bbqueue::{BBBuffer, consts::*}; //! -//! let bb: BBBuffer = BBBuffer::new(); +//! let bb: BBBuffer = BBBuffer::new(); //! let (mut prod, mut cons) = bb.try_split_framed().unwrap(); //! //! // One frame in, one frame out diff --git a/core/src/lib.rs b/core/src/lib.rs index ed7048e..b109c0d 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -26,7 +26,7 @@ //! # use bbqueue::cm_mutex::{BBBuffer, consts::*}; //! # //! // Create a buffer with six elements -//! let bb: BBBuffer = BBBuffer::new(); +//! let bb: BBBuffer = BBBuffer::new(); //! let (mut prod, mut cons) = bb.try_split().unwrap(); //! //! // Request space for one byte @@ -58,7 +58,7 @@ //! # use bbqueue::cm_mutex::{BBBuffer, ConstBBBuffer, consts::*}; //! # //! // Create a buffer with six elements -//! static BB: BBBuffer = BBBuffer( ConstBBBuffer::new() ); +//! static BB: BBBuffer = BBBuffer( ConstBBBuffer::new() ); //! //! fn main() { //! // Split the bbqueue into producer and consumer halves. From 00582f3f9de38b5b3b77c033a916970a7ad818dd Mon Sep 17 00:00:00 2001 From: ZK Date: Tue, 26 May 2020 00:57:23 +0100 Subject: [PATCH 3/4] Cargo fmt --- bbqtest/src/ring_around_the_senders.rs | 15 +++++++++--- bbqtest/src/single_thread.rs | 23 ++++++++++------- core/src/bbbuffer.rs | 34 ++++++++++++++++++++------ 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/bbqtest/src/ring_around_the_senders.rs b/bbqtest/src/ring_around_the_senders.rs index 5834ea5..f4d7be3 100644 --- a/bbqtest/src/ring_around_the_senders.rs +++ b/bbqtest/src/ring_around_the_senders.rs @@ -3,7 +3,7 @@ mod tests { use core::convert::TryFrom; use core::fmt::Debug; - + use bbqueue::{ consts::*, ArrayLength, BBBuffer, ConstBBBuffer, Consumer, GrantR, GrantW, Producer, }; @@ -71,7 +71,9 @@ mod tests { gr_w.iter_mut() .take(BYTES_PER_GRANT) .enumerate() - .for_each(|(i, by)| *by = T::try_from(i).ok().expect("can construct from usize")); + .for_each(|(i, by)| { + *by = T::try_from(i).ok().expect("can construct from usize") + }); gr_w.commit(BYTES_PER_GRANT); (Self::Idle, Self::Idle) } @@ -79,7 +81,9 @@ mod tests { gr_r.iter() .take(BYTES_PER_GRANT) .enumerate() - .for_each(|(i, by)| assert_eq!(*by, T::try_from(i).ok().expect("can construct from usize"))); + .for_each(|(i, by)| { + assert_eq!(*by, T::try_from(i).ok().expect("can construct from usize")) + }); gr_r.release(BYTES_PER_GRANT); (Self::Idle, Self::Idle) } @@ -101,7 +105,10 @@ mod tests { generic_hello::(&BB); } - fn generic_hello(bb: &'static BBBuffer) where T: Sized + TryFrom + Debug + PartialEq { + fn generic_hello(bb: &'static BBBuffer) + where + T: Sized + TryFrom + Debug + PartialEq, + { let (prod, cons) = bb.try_split().unwrap(); // create the channels diff --git a/bbqtest/src/single_thread.rs b/bbqtest/src/single_thread.rs index bcab0cb..ab0b000 100644 --- a/bbqtest/src/single_thread.rs +++ b/bbqtest/src/single_thread.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod tests { - use std::fmt::Debug; use core::convert::TryFrom; + use std::fmt::Debug; use bbqueue::{consts::*, BBBuffer}; @@ -45,7 +45,7 @@ mod tests { enum PodEnum { Empty, Tuple((u64, i64, usize)), - Array([i16; 16]) + Array([i16; 16]), } impl From for PodEnum { @@ -76,22 +76,27 @@ mod tests { let mut vec = Vec::with_capacity(v as usize); vec.iter_mut().for_each(|e| *e = v); - let maybe_boxed = Some(Box::new(RefStruct{ vec: vec.clone(), maybe_boxed: None })); - RefStruct { - vec, - maybe_boxed - } + let maybe_boxed = Some(Box::new(RefStruct { + vec: vec.clone(), + maybe_boxed: None, + })); + RefStruct { vec, maybe_boxed } } } - fn generic_sanity_check() where T: Sized + TryFrom + Debug + PartialEq + Clone { + fn generic_sanity_check() + where + T: Sized + TryFrom + Debug + PartialEq + Clone, + { let bb: BBBuffer = BBBuffer::new(); let (mut prod, mut cons) = bb.try_split().unwrap(); const ITERS: usize = 100000; for i in 0..ITERS { - let j = T::try_from((i & 255) as u8).ok().expect("can construct type from u8"); + let j = T::try_from((i & 255) as u8) + .ok() + .expect("can construct type from u8"); #[cfg(feature = "extra-verbose")] println!("==========================="); diff --git a/core/src/bbbuffer.rs b/core/src/bbbuffer.rs index 893456c..547b5cd 100644 --- a/core/src/bbbuffer.rs +++ b/core/src/bbbuffer.rs @@ -32,7 +32,7 @@ unsafe impl Sync for ConstBBBuffer {} impl<'a, T, N> BBBuffer where - T: Sized, + T: Sized, N: ArrayLength, { /// Attempt to split the `BBBuffer` into `Consumer` and `Producer` halves to gain access to the @@ -339,7 +339,12 @@ where pd: PhantomData<&'a ()>, } -unsafe impl<'a, T, N> Send for Producer<'a, T, N> where T: Sized, N: ArrayLength {} +unsafe impl<'a, T, N> Send for Producer<'a, T, N> +where + T: Sized, + N: ArrayLength, +{ +} impl<'a, T, N> Producer<'a, T, N> where @@ -543,14 +548,19 @@ where /// `Consumer` is the primary interface for reading data from a `BBBuffer`. pub struct Consumer<'a, T, N> where - T: Sized, + T: Sized, N: ArrayLength, { bbq: NonNull>, pd: PhantomData<&'a ()>, } -unsafe impl<'a, T, N> Send for Consumer<'a, T, N> where T: Sized, N: ArrayLength {} +unsafe impl<'a, T, N> Send for Consumer<'a, T, N> +where + T: Sized, + N: ArrayLength, +{ +} impl<'a, T, N> Consumer<'a, T, N> where @@ -713,7 +723,12 @@ where bbq: NonNull>, } -unsafe impl<'a, T, N> Send for GrantW<'a, T, N> where T: Sized, N: ArrayLength {} +unsafe impl<'a, T, N> Send for GrantW<'a, T, N> +where + T: Sized, + N: ArrayLength, +{ +} /// A structure representing a contiguous region of memory that /// may be read from, and potentially "released" (or cleared) @@ -726,14 +741,19 @@ unsafe impl<'a, T, N> Send for GrantW<'a, T, N> where T: Sized, N: ArrayLength where - T: Sized, + T: Sized, N: ArrayLength, { pub(crate) buf: &'a [T], bbq: NonNull>, } -unsafe impl<'a, T, N> Send for GrantR<'a, T, N> where T: Sized, N: ArrayLength {} +unsafe impl<'a, T, N> Send for GrantR<'a, T, N> +where + T: Sized, + N: ArrayLength, +{ +} impl<'a, T, N> GrantW<'a, T, N> where From 8067533291f8fa608ad19de22423396efc1b83e7 Mon Sep 17 00:00:00 2001 From: ZK Date: Mon, 8 Jun 2020 00:20:08 +0100 Subject: [PATCH 4/4] Added type alias for BBBuffer, updated docs --- bbqtest/src/benches.rs | 6 +- bbqtest/src/lib.rs | 22 ++-- bbqtest/src/multi_thread.rs | 8 +- bbqtest/src/ring_around_the_senders.rs | 6 +- bbqtest/src/single_thread.rs | 4 +- core/src/bbbuffer.rs | 133 +++++++++++++------------ core/src/framed.rs | 2 +- core/src/lib.rs | 8 +- 8 files changed, 97 insertions(+), 92 deletions(-) diff --git a/bbqtest/src/benches.rs b/bbqtest/src/benches.rs index 123cd0a..c6b51e6 100644 --- a/bbqtest/src/benches.rs +++ b/bbqtest/src/benches.rs @@ -1,4 +1,4 @@ -use bbqueue::{consts::*, BBBuffer}; +use bbqueue::{consts::*, GenericBBBuffer}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use std::cmp::min; @@ -17,7 +17,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { c.bench_function("bbq 2048/4096", |bench| bench.iter(|| chunky(&data, 2048))); - let buffy: BBBuffer = BBBuffer::new(); + let buffy: GenericBBBuffer = GenericBBBuffer::new(); let (mut prod, mut cons) = buffy.try_split().unwrap(); c.bench_function("bbq 8192/65536", |bench| { @@ -196,7 +196,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { use crossbeam_utils::thread; fn chunky(data: &[u8], chunksz: usize) { - let buffy: BBBuffer = BBBuffer::new(); + let buffy: GenericBBBuffer = GenericBBBuffer::new(); let (mut prod, mut cons) = buffy.try_split().unwrap(); thread::scope(|sc| { diff --git a/bbqtest/src/lib.rs b/bbqtest/src/lib.rs index 8f4c6fc..103e92b 100644 --- a/bbqtest/src/lib.rs +++ b/bbqtest/src/lib.rs @@ -7,11 +7,11 @@ mod single_thread; #[cfg(test)] mod tests { - use bbqueue::{consts::*, BBBuffer, ConstBBBuffer, Error as BBQError}; + use bbqueue::{consts::*, BBBuffer, ConstBBBuffer, Error as BBQError, GenericBBBuffer}; #[test] fn deref_deref_mut() { - let bb: BBBuffer = BBBuffer::new(); + let bb: BBBuffer = BBBuffer::new(); let (mut prod, mut cons) = bb.try_split().unwrap(); let mut wgr = prod.grant_exact(1).unwrap(); @@ -34,8 +34,8 @@ mod tests { #[test] fn static_allocator() { // Check we can make multiple static items... - static BBQ1: BBBuffer = BBBuffer(ConstBBBuffer::new()); - static BBQ2: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BBQ1: BBBuffer = GenericBBBuffer(ConstBBBuffer::new()); + static BBQ2: BBBuffer = GenericBBBuffer(ConstBBBuffer::new()); let (mut prod1, mut cons1) = BBQ1.try_split().unwrap(); let (mut _prod2, mut cons2) = BBQ2.try_split().unwrap(); @@ -55,8 +55,8 @@ mod tests { #[test] fn release() { // Check we can make multiple static items... - static BBQ1: BBBuffer = BBBuffer(ConstBBBuffer::new()); - static BBQ2: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BBQ1: GenericBBBuffer = GenericBBBuffer(ConstBBBuffer::new()); + static BBQ2: GenericBBBuffer = GenericBBBuffer(ConstBBBuffer::new()); let (prod1, cons1) = BBQ1.try_split().unwrap(); let (prod2, cons2) = BBQ2.try_split().unwrap(); @@ -93,7 +93,7 @@ mod tests { #[test] fn direct_usage_sanity() { // Initialize - let bb: BBBuffer = BBBuffer::new(); + let bb: BBBuffer = GenericBBBuffer::new(); let (mut prod, mut cons) = bb.try_split().unwrap(); assert_eq!(cons.read(), Err(BBQError::InsufficientSize)); @@ -178,7 +178,7 @@ mod tests { #[test] fn zero_sized_grant() { - let bb: BBBuffer = BBBuffer::new(); + let bb: GenericBBBuffer = GenericBBBuffer::new(); let (mut prod, mut _cons) = bb.try_split().unwrap(); let size = 1000; @@ -191,7 +191,7 @@ mod tests { #[test] fn frame_sanity() { - let bb: BBBuffer = BBBuffer::new(); + let bb: GenericBBBuffer = GenericBBBuffer::new(); let (mut prod, mut cons) = bb.try_split_framed().unwrap(); // One frame in, one frame out @@ -238,7 +238,7 @@ mod tests { #[test] fn frame_wrap() { - let bb: BBBuffer = BBBuffer::new(); + let bb: GenericBBBuffer = GenericBBBuffer::new(); let (mut prod, mut cons) = bb.try_split_framed().unwrap(); // 10 + 1 used @@ -304,7 +304,7 @@ mod tests { #[test] fn frame_big_little() { - let bb: BBBuffer = BBBuffer::new(); + let bb: GenericBBBuffer = GenericBBBuffer::new(); let (mut prod, mut cons) = bb.try_split_framed().unwrap(); // Create a frame that should take 3 bytes for the header diff --git a/bbqtest/src/multi_thread.rs b/bbqtest/src/multi_thread.rs index d420fc7..3b964b4 100644 --- a/bbqtest/src/multi_thread.rs +++ b/bbqtest/src/multi_thread.rs @@ -1,7 +1,7 @@ #[cfg_attr(not(feature = "verbose"), allow(unused_variables))] #[cfg(test)] mod tests { - use bbqueue::{consts::*, BBBuffer, ConstBBBuffer, Error}; + use bbqueue::{consts::*, ConstBBBuffer, Error, GenericBBBuffer}; use rand::prelude::*; use std::thread::spawn; use std::time::{Duration, Instant}; @@ -52,7 +52,7 @@ mod tests { #[cfg(feature = "verbose")] println!("RTX: Running test..."); - static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BB: GenericBBBuffer = GenericBBBuffer(ConstBBBuffer::new()); let (mut tx, mut rx) = BB.try_split().unwrap(); let mut last_tx = Instant::now(); @@ -144,7 +144,7 @@ mod tests { #[test] fn sanity_check() { - static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BB: GenericBBBuffer = GenericBBBuffer(ConstBBBuffer::new()); let (mut tx, mut rx) = BB.try_split().unwrap(); let mut last_tx = Instant::now(); @@ -238,7 +238,7 @@ mod tests { #[test] fn sanity_check_grant_max() { - static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BB: GenericBBBuffer = GenericBBBuffer(ConstBBBuffer::new()); let (mut tx, mut rx) = BB.try_split().unwrap(); #[cfg(feature = "verbose")] diff --git a/bbqtest/src/ring_around_the_senders.rs b/bbqtest/src/ring_around_the_senders.rs index f4d7be3..b025893 100644 --- a/bbqtest/src/ring_around_the_senders.rs +++ b/bbqtest/src/ring_around_the_senders.rs @@ -5,7 +5,7 @@ mod tests { use core::fmt::Debug; use bbqueue::{ - consts::*, ArrayLength, BBBuffer, ConstBBBuffer, Consumer, GrantR, GrantW, Producer, + consts::*, ArrayLength, ConstBBBuffer, Consumer, GenericBBBuffer, GrantR, GrantW, Producer, }; enum Potato<'a, T, N> @@ -95,7 +95,7 @@ mod tests { // Data type type DataTy = u8; - static BB: BBBuffer = BBBuffer(ConstBBBuffer::new()); + static BB: GenericBBBuffer = GenericBBBuffer(ConstBBBuffer::new()); use std::sync::mpsc::{channel, Receiver, Sender}; use std::thread::spawn; @@ -105,7 +105,7 @@ mod tests { generic_hello::(&BB); } - fn generic_hello(bb: &'static BBBuffer) + fn generic_hello(bb: &'static GenericBBBuffer) where T: Sized + TryFrom + Debug + PartialEq, { diff --git a/bbqtest/src/single_thread.rs b/bbqtest/src/single_thread.rs index ab0b000..7b16497 100644 --- a/bbqtest/src/single_thread.rs +++ b/bbqtest/src/single_thread.rs @@ -3,7 +3,7 @@ mod tests { use core::convert::TryFrom; use std::fmt::Debug; - use bbqueue::{consts::*, BBBuffer}; + use bbqueue::{consts::*, GenericBBBuffer}; #[test] fn sanity_check_u8() { @@ -88,7 +88,7 @@ mod tests { where T: Sized + TryFrom + Debug + PartialEq + Clone, { - let bb: BBBuffer = BBBuffer::new(); + let bb: GenericBBBuffer = GenericBBBuffer::new(); let (mut prod, mut cons) = bb.try_split().unwrap(); const ITERS: usize = 100000; diff --git a/core/src/bbbuffer.rs b/core/src/bbbuffer.rs index 547b5cd..eb92ac7 100644 --- a/core/src/bbbuffer.rs +++ b/core/src/bbbuffer.rs @@ -23,19 +23,24 @@ use generic_array::{ArrayLength, GenericArray}; /// A backing structure for a BBQueue. Can be used to create either /// a BBQueue or a split Producer/Consumer pair #[derive(Debug)] -pub struct BBBuffer>( +pub struct GenericBBBuffer>( // Underlying data storage #[doc(hidden)] pub ConstBBBuffer>, ); +/// An alias of `GenericBBBuffer` parametrized with `u8` for operations on byte-based buffers, +/// including `try_split_framed` method, `FrameProducer` and `FrameConsumer`. +/// Added for compatibility with code depending on `BBBuffer` type name +pub type BBBuffer = GenericBBBuffer; + unsafe impl Sync for ConstBBBuffer {} -impl<'a, T, N> BBBuffer +impl<'a, T, N> GenericBBBuffer where T: Sized, N: ArrayLength, { - /// Attempt to split the `BBBuffer` into `Consumer` and `Producer` halves to gain access to the + /// Attempt to split the `GenericBBBuffer` into `Consumer` and `Producer` halves to gain access to the /// buffer. If buffer has already been split, an error will be returned. /// /// NOTE: When splitting, the underlying buffer will be explicitly initialized @@ -50,10 +55,10 @@ where /// ```rust /// # // bbqueue test shim! /// # fn bbqtest() { - /// use bbqueue::{BBBuffer, consts::*}; + /// use bbqueue::{GenericBBBuffer, consts::*}; /// /// // Create and split a new buffer - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: GenericBBBuffer = GenericBBBuffer::new(); /// let (prod, cons) = buffer.try_split().unwrap(); /// /// // Not possible to split twice @@ -99,16 +104,16 @@ where /// This re-initializes the buffer so it may be split in a different mode at a later /// time. There must be no read or write grants active, or an error will be returned. /// - /// The `Producer` and `Consumer` must be from THIS `BBBuffer`, or an error will + /// The `Producer` and `Consumer` must be from THIS `GenericBBBuffer`, or an error will /// be returned. /// /// ```rust /// # // bbqueue test shim! /// # fn bbqtest() { - /// use bbqueue::{BBBuffer, consts::*}; + /// use bbqueue::{GenericBBBuffer, consts::*}; /// /// // Create and split a new buffer - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: GenericBBBuffer = GenericBBBuffer::new(); /// let (prod, cons) = buffer.try_split().unwrap(); /// /// // Not possible to split twice @@ -170,11 +175,11 @@ where } } -impl<'a, N> BBBuffer +impl<'a, N> GenericBBBuffer where N: ArrayLength, { - /// Attempt to split the `BBBuffer` into `FrameConsumer` and `FrameProducer` halves + /// Attempt to split the `GenericBBBuffer` into `FrameConsumer` and `FrameProducer` halves /// to gain access to the buffer. If buffer has already been split, an error /// will be returned. /// @@ -196,7 +201,7 @@ where /// This re-initializes the buffer so it may be split in a different mode at a later /// time. There must be no read or write grants active, or an error will be returned. /// - /// The `FrameProducer` and `FrameConsumer` must be from THIS `BBBuffer`, or an error + /// The `FrameProducer` and `FrameConsumer` must be from THIS `GenericBBBuffer`, or an error /// will be returned. pub fn try_release_framed( &'a self, @@ -211,9 +216,9 @@ where } } -/// `const-fn` version BBBuffer +/// `const-fn` version GenericBBBuffer /// -/// NOTE: This is only necessary to use when creating a `BBBuffer` at static +/// NOTE: This is only necessary to use when creating a `GenericBBBuffer` at static /// scope, and is generally never used directly. This process is necessary to /// work around current limitations in `const fn`, and will be replaced in /// the future. @@ -235,7 +240,7 @@ pub struct ConstBBBuffer { /// when exiting the inverted condition last: AtomicUsize, - /// Used by the Writer to remember what bytes are currently + /// Used by the Writer to remember what elements are currently /// allowed to be written to, but are not yet ready to be /// read from reserve: AtomicUsize, @@ -251,17 +256,17 @@ pub struct ConstBBBuffer { } impl ConstBBBuffer { - /// Create a new constant inner portion of a `BBBuffer`. + /// Create a new constant inner portion of a `GenericBBBuffer`. /// - /// NOTE: This is only necessary to use when creating a `BBBuffer` at static + /// NOTE: This is only necessary to use when creating a `GenericBBBuffer` at static /// scope, and is generally never used directly. This process is necessary to /// work around current limitations in `const fn`, and will be replaced in /// the future. /// /// ```rust,no_run - /// use bbqueue::{BBBuffer, ConstBBBuffer, consts::*}; + /// use bbqueue::{GenericBBBuffer, ConstBBBuffer, consts::*}; /// - /// static BUF: BBBuffer = BBBuffer( ConstBBBuffer::new() ); + /// static BUF: GenericBBBuffer = GenericBBBuffer( ConstBBBuffer::new() ); /// /// fn main() { /// let (prod, cons) = BUF.try_split().unwrap(); @@ -285,9 +290,9 @@ impl ConstBBBuffer { /// and can cause the .data section to be much larger than necessary. By /// forcing the `last` pointer to be zero initially, we place the structure /// in an "inverted" condition, which will be resolved on the first commited - /// bytes that are written to the structure. + /// elements (i.e. bytes) that are written to the structure. /// - /// When read == last == write, no bytes will be allowed to be read (good), but + /// When read == last == write, no elements will be allowed to be read (good), but /// write grants can be given out (also good). last: AtomicUsize::new(0), @@ -306,7 +311,7 @@ impl ConstBBBuffer { } } -/// `Producer` is the primary interface for pushing data into a `BBBuffer`. +/// `Producer` is the primary interface for pushing data into a `GenericBBBuffer`. /// There are various methods for obtaining a grant to write to the buffer, with /// different potential tradeoffs. As all grants are required to be a contiguous /// range of data, different strategies are sometimes useful when making the decision @@ -318,15 +323,15 @@ impl ConstBBBuffer { /// * User will receive a grant `sz == N` (or receive an error) /// * This may cause a wraparound if a grant of size N is not available /// at the end of the ring. -/// * If this grant caused a wraparound, the bytes that were "skipped" at the +/// * If this grant caused a wraparound, the elements that were "skipped" at the /// end of the ring will not be available until the reader reaches them, /// regardless of whether the grant commited any data or not. -/// * Maximum possible waste due to skipping: `N - 1` bytes +/// * Maximum possible waste due to skipping: `N - 1` elements /// * `grant_max_remaining(N)` /// * User will receive a grant `0 < sz <= N` (or receive an error) /// * This will only cause a wrap to the beginning of the ring if exactly -/// zero bytes are available at the end of the ring. -/// * Maximum possible waste due to skipping: 0 bytes +/// zero element slots are available at the end of the ring. +/// * Maximum possible waste due to skipping: 0 elements /// /// See [this github issue](/~https://github.com/jamesmunns/bbqueue/issues/38) for a /// discussion of grant methods that could be added in the future. @@ -335,7 +340,7 @@ where T: Sized, N: ArrayLength, { - bbq: NonNull>, + bbq: NonNull>, pd: PhantomData<&'a ()>, } @@ -352,7 +357,7 @@ where N: ArrayLength, { /// Request a writable, contiguous section of memory of exactly - /// `sz` bytes. If the buffer size requested is not available, + /// `sz` element slots. If the buffer size requested is not available, /// an error will be returned. /// /// This method may cause the buffer to wrap around early if the @@ -362,18 +367,18 @@ where /// ```rust /// # // bbqueue test shim! /// # fn bbqtest() { - /// use bbqueue::{BBBuffer, consts::*}; + /// use bbqueue::{GenericBBBuffer, consts::*}; /// /// // Create and split a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: GenericBBBuffer = GenericBBBuffer::new(); /// let (mut prod, cons) = buffer.try_split().unwrap(); /// - /// // Successfully obtain and commit a grant of four bytes + /// // Successfully obtain and commit a grant of four elements /// let mut grant = prod.grant_exact(4).unwrap(); /// assert_eq!(grant.buf().len(), 4); /// grant.commit(4); /// - /// // Try to obtain a grant of three bytes + /// // Try to obtain a grant of three elements /// assert!(prod.grant_exact(3).is_err()); /// # // bbqueue test shim! /// # } @@ -443,7 +448,7 @@ where } /// Request a writable, contiguous section of memory of up to - /// `sz` bytes. If a buffer of size `sz` is not available without + /// `sz` elements. If a buffer of size `sz` is not available without /// wrapping, but some space (0 < available < sz) is available without /// wrapping, then a grant will be given for the remaining size at the /// end of the buffer. If no space is available for writing, an error @@ -452,23 +457,23 @@ where /// ``` /// # // bbqueue test shim! /// # fn bbqtest() { - /// use bbqueue::{BBBuffer, consts::*}; + /// use bbqueue::{GenericBBBuffer, consts::*}; /// /// // Create and split a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: GenericBBBuffer = GenericBBBuffer::new(); /// let (mut prod, mut cons) = buffer.try_split().unwrap(); /// - /// // Successfully obtain and commit a grant of four bytes + /// // Successfully obtain and commit a grant of four elements /// let mut grant = prod.grant_max_remaining(4).unwrap(); /// assert_eq!(grant.buf().len(), 4); /// grant.commit(4); /// - /// // Release the four initial commited bytes + /// // Release the four initial commited elements /// let mut grant = cons.read().unwrap(); /// assert_eq!(grant.buf().len(), 4); /// grant.release(4); /// - /// // Try to obtain a grant of three bytes, get two bytes + /// // Try to obtain a grant of three elements, get two elements /// let mut grant = prod.grant_max_remaining(3).unwrap(); /// assert_eq!(grant.buf().len(), 2); /// grant.commit(2); @@ -545,13 +550,13 @@ where } } -/// `Consumer` is the primary interface for reading data from a `BBBuffer`. +/// `Consumer` is the primary interface for reading data from a `GenericBBBuffer`. pub struct Consumer<'a, T, N> where T: Sized, N: ArrayLength, { - bbq: NonNull>, + bbq: NonNull>, pd: PhantomData<&'a ()>, } @@ -567,21 +572,21 @@ where T: Sized, N: ArrayLength, { - /// Obtains a contiguous slice of committed bytes. This slice may not - /// contain ALL available bytes, if the writer has wrapped around. The - /// remaining bytes will be available after all readable bytes are + /// Obtains a contiguous slice of committed elements. This slice may not + /// contain ALL available elements, if the writer has wrapped around. The + /// remaining elements will be available after all readable elements are /// released /// /// ```rust /// # // bbqueue test shim! /// # fn bbqtest() { - /// use bbqueue::{BBBuffer, consts::*}; + /// use bbqueue::{GenericBBBuffer, consts::*}; /// /// // Create and split a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: GenericBBBuffer = GenericBBBuffer::new(); /// let (mut prod, mut cons) = buffer.try_split().unwrap(); /// - /// // Successfully obtain and commit a grant of four bytes + /// // Successfully obtain and commit a grant of four elements /// let mut grant = prod.grant_max_remaining(4).unwrap(); /// assert_eq!(grant.buf().len(), 4); /// grant.commit(4); @@ -647,22 +652,22 @@ where } } -impl BBBuffer +impl GenericBBBuffer where T: Sized, N: ArrayLength, { /// Returns the size of the backing storage. /// - /// This is the maximum number of bytes that can be stored in this queue. + /// This is the maximum number of elements that can be stored in this queue. /// /// ```rust /// # // bbqueue test shim! /// # fn bbqtest() { - /// use bbqueue::{BBBuffer, consts::*}; + /// use bbqueue::{GenericBBBuffer, consts::*}; /// /// // Create a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: GenericBBBuffer = GenericBBBuffer::new(); /// assert_eq!(buffer.capacity(), 6); /// # // bbqueue test shim! /// # } @@ -677,7 +682,7 @@ where } } -impl BBBuffer +impl GenericBBBuffer where T: Sized, N: ArrayLength, @@ -689,10 +694,10 @@ where /// ```rust /// # // bbqueue test shim! /// # fn bbqtest() { - /// use bbqueue::{BBBuffer, consts::*}; + /// use bbqueue::{GenericBBBuffer, consts::*}; /// /// // Create a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: GenericBBBuffer = GenericBBBuffer::new(); /// # // bbqueue test shim! /// # } /// # @@ -710,7 +715,7 @@ where /// may be written to, and potentially "committed" to the queue. /// /// NOTE: If the grant is dropped without explicitly commiting -/// the contents, then no bytes will be comitted for writing. +/// the contents, then no elements will be comitted for writing. /// If the `thumbv6` feature is selected, dropping the grant /// without committing it takes a short critical section, #[derive(Debug, PartialEq)] @@ -720,7 +725,7 @@ where N: ArrayLength, { pub(crate) buf: &'a mut [T], - bbq: NonNull>, + bbq: NonNull>, } unsafe impl<'a, T, N> Send for GrantW<'a, T, N> @@ -735,7 +740,7 @@ where /// from the queue /// /// NOTE: If the grant is dropped without explicitly releasing -/// the contents, then no bytes will be released as read. +/// the contents, then no elements will be released as read. /// If the `thumbv6` feature is selected, dropping the grant /// without releasing it takes a short critical section, #[derive(Debug, PartialEq)] @@ -745,7 +750,7 @@ where N: ArrayLength, { pub(crate) buf: &'a [T], - bbq: NonNull>, + bbq: NonNull>, } unsafe impl<'a, T, N> Send for GrantR<'a, T, N> @@ -779,13 +784,13 @@ where /// ```rust /// # // bbqueue test shim! /// # fn bbqtest() { - /// use bbqueue::{BBBuffer, consts::*}; + /// use bbqueue::{GenericBBBuffer, consts::*}; /// /// // Create and split a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: GenericBBBuffer = GenericBBBuffer::new(); /// let (mut prod, mut cons) = buffer.try_split().unwrap(); /// - /// // Successfully obtain and commit a grant of four bytes + /// // Successfully obtain and commit a grant of four elements /// let mut grant = prod.grant_max_remaining(4).unwrap(); /// grant.buf().copy_from_slice(&[1, 2, 3, 4]); /// grant.commit(4); @@ -835,7 +840,7 @@ where let new_write = inner.reserve.load(Acquire); if (new_write < write) && (write != max) { - // We have already wrapped, but we are skipping some bytes at the end of the ring. + // We have already wrapped, but we are skipping some elements at the end of the ring. // Mark `last` where the write pointer used to be to hold the line here inner.last.store(write, Release); } else if new_write > last { @@ -868,7 +873,7 @@ where T: Sized, N: ArrayLength, { - /// Release a sequence of bytes from the buffer, allowing the space + /// Release a sequence of elements from the buffer, allowing the space /// to be used by later writes. This consumes the grant. /// /// If `used` is larger than the given grant, the full grant will @@ -894,13 +899,13 @@ where /// ``` /// # // bbqueue test shim! /// # fn bbqtest() { - /// use bbqueue::{BBBuffer, consts::*}; + /// use bbqueue::{GenericBBBuffer, consts::*}; /// /// // Create and split a new buffer of 6 elements - /// let buffer: BBBuffer = BBBuffer::new(); + /// let buffer: GenericBBBuffer = GenericBBBuffer::new(); /// let (mut prod, mut cons) = buffer.try_split().unwrap(); /// - /// // Successfully obtain and commit a grant of four bytes + /// // Successfully obtain and commit a grant of four elements /// let mut grant = prod.grant_max_remaining(4).unwrap(); /// grant.buf().copy_from_slice(&[1, 2, 3, 4]); /// grant.commit(4); diff --git a/core/src/framed.rs b/core/src/framed.rs index 5804d93..e2db4eb 100644 --- a/core/src/framed.rs +++ b/core/src/framed.rs @@ -13,7 +13,7 @@ //! # fn bbqtest() { //! use bbqueue::{BBBuffer, consts::*}; //! -//! let bb: BBBuffer = BBBuffer::new(); +//! let bb: BBBuffer = BBBuffer::new(); //! let (mut prod, mut cons) = bb.try_split_framed().unwrap(); //! //! // One frame in, one frame out diff --git a/core/src/lib.rs b/core/src/lib.rs index b109c0d..16e0f3d 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -26,7 +26,7 @@ //! # use bbqueue::cm_mutex::{BBBuffer, consts::*}; //! # //! // Create a buffer with six elements -//! let bb: BBBuffer = BBBuffer::new(); +//! let bb: BBBuffer = BBBuffer::new(); //! let (mut prod, mut cons) = bb.try_split().unwrap(); //! //! // Request space for one byte @@ -53,12 +53,12 @@ //! //! ```rust, no_run //! # #[cfg(feature = "atomic")] -//! # use bbqueue::atomic::{BBBuffer, ConstBBBuffer, consts::*}; +//! # use bbqueue::atomic::{BBBuffer, GenericBBBuffer, ConstBBBuffer, consts::*}; //! # #[cfg(not(feature = "atomic"))] -//! # use bbqueue::cm_mutex::{BBBuffer, ConstBBBuffer, consts::*}; +//! # use bbqueue::cm_mutex::{BBBuffer, GenericBBBuffer, ConstBBBuffer, consts::*}; //! # //! // Create a buffer with six elements -//! static BB: BBBuffer = BBBuffer( ConstBBBuffer::new() ); +//! static BB: BBBuffer = GenericBBBuffer( ConstBBBuffer::new() ); //! //! fn main() { //! // Split the bbqueue into producer and consumer halves.