//! Direct implementation. //! //! All changes are synchronized with the ring buffer immediately. #[allow(deprecated)] use super::frozen::Frozen; use super::{caching::Caching, traits::Wrap}; use crate::{ rb::RbRef, traits::{ Observer, RingBuffer, consumer::{Consumer, impl_consumer_traits}, producer::{Producer, impl_producer_traits}, }, }; use core::{ mem::{ManuallyDrop, MaybeUninit}, num::NonZeroUsize, ptr, }; /// Direct wrapper of a ring buffer. pub struct Direct { rb: R, } /// Observer of a ring buffer. pub type Obs = Direct; /// Producer of a ring buffer. pub type Prod = Direct; /// Consumer of a ring buffer. pub type Cons = Direct; impl Clone for Obs { fn clone(&self) -> Self { Self { rb: self.rb.clone() } } } impl Direct { /// Create a new ring buffer direct wrapper. /// /// Panics if wrapper with matching rights already exists. pub fn new(rb: R) -> Self { if P { assert!(!unsafe { rb.rb().hold_write(true) }); } if C { assert!(!unsafe { rb.rb().hold_read(true) }); } Self { rb } } /// Get ring buffer observer. pub fn observe(&self) -> Obs { Obs { rb: self.rb.clone() } } /// Convert to the deprecated compatibility wrapper. Changes remain immediately visible. #[deprecated(note = "use the endpoint directly; freezing no longer delays publication")] #[allow(deprecated)] pub fn freeze(self) -> Frozen { Frozen::from_caching(Caching::from_direct(self)) } /// # Safety /// /// Must not be used after this call. unsafe fn close(&mut self) { if P { unsafe { self.rb().hold_write(false) }; } if C { unsafe { self.rb().hold_read(false) }; } } } impl Wrap for Direct { type RbRef = R; fn rb_ref(&self) -> &R { &self.rb } fn into_rb_ref(mut self) -> R { unsafe { self.close(); let this = ManuallyDrop::new(self); ptr::read(&this.rb) } } } impl AsRef for Direct { fn as_ref(&self) -> &Self { self } } impl AsMut for Direct { fn as_mut(&mut self) -> &mut Self { self } } impl Observer for Direct { type Item = ::Item; #[inline] fn capacity(&self) -> NonZeroUsize { self.rb().capacity() } #[inline] fn read_index(&self) -> usize { self.rb().read_index() } #[inline] fn write_index(&self) -> usize { self.rb().write_index() } #[inline] unsafe fn unsafe_slices(&self, start: usize, end: usize) -> (&[MaybeUninit], &[MaybeUninit]) { unsafe { self.rb().unsafe_slices(start, end) } } #[inline] unsafe fn unsafe_slices_mut(&self, start: usize, end: usize) -> (&mut [MaybeUninit], &mut [MaybeUninit]) { unsafe { self.rb().unsafe_slices_mut(start, end) } } #[inline] fn read_is_held(&self) -> bool { self.rb().read_is_held() } #[inline] fn write_is_held(&self) -> bool { self.rb().write_is_held() } } impl Producer for Prod { #[inline] unsafe fn set_write_index(&self, value: usize) { unsafe { self.rb().set_write_index(value) } } } impl Consumer for Cons { #[inline] unsafe fn set_read_index(&self, value: usize) { unsafe { self.rb().set_read_index(value) } } } impl Drop for Direct { fn drop(&mut self) { unsafe { self.close() }; } } impl_producer_traits!(Prod); impl_consumer_traits!(Cons);