| 1 | use crate::utils::ring_buffer_ranges; |
| 2 | #[cfg (feature = "alloc" )] |
| 3 | use alloc::vec::Vec; |
| 4 | use core::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit, num::NonZeroUsize, slice}; |
| 5 | |
| 6 | /// Abstract container for the ring buffer. |
| 7 | /// |
| 8 | /// Container items must be stored as a contiguous array. |
| 9 | /// |
| 10 | /// # Safety |
| 11 | /// |
| 12 | /// *[`Self::len`]/[`Self::is_empty`] must always return the same value.* |
| 13 | /// |
| 14 | /// *Container must not cause data race on concurrent [`Self::as_mut_slice`]/[`Self::as_mut_ptr`] calls.* |
| 15 | pub unsafe trait Container<T> { |
| 16 | /// Internal representation of the container. |
| 17 | /// |
| 18 | /// *Must not be aliased with its content.* |
| 19 | type Internal; |
| 20 | |
| 21 | /// Transform container to internal representation. |
| 22 | fn into_internal(self) -> Self::Internal; |
| 23 | /// Restore container from internal representation. |
| 24 | /// |
| 25 | /// # Safety |
| 26 | /// |
| 27 | /// `this` must be valid. |
| 28 | unsafe fn from_internal(this: Self::Internal) -> Self; |
| 29 | |
| 30 | /// Return pointer to the beginning of the container items. |
| 31 | fn as_mut_ptr(this: &Self::Internal) -> *mut MaybeUninit<T>; |
| 32 | /// Length of the container. |
| 33 | fn len(this: &Self::Internal) -> usize; |
| 34 | } |
| 35 | |
| 36 | unsafe impl<'a, T> Container<T> for &'a mut [MaybeUninit<T>] { |
| 37 | type Internal = (*mut MaybeUninit<T>, usize); |
| 38 | |
| 39 | fn into_internal(self) -> Self::Internal { |
| 40 | (self.as_mut_ptr(), self.len()) |
| 41 | } |
| 42 | unsafe fn from_internal(this: Self::Internal) -> Self { |
| 43 | slice::from_raw_parts_mut(data:this.0, len:this.1) |
| 44 | } |
| 45 | |
| 46 | #[inline ] |
| 47 | fn as_mut_ptr(this: &Self::Internal) -> *mut MaybeUninit<T> { |
| 48 | this.0 |
| 49 | } |
| 50 | #[inline ] |
| 51 | fn len(this: &Self::Internal) -> usize { |
| 52 | this.1 |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | unsafe impl<T, const N: usize> Container<T> for [MaybeUninit<T>; N] { |
| 57 | type Internal = UnsafeCell<[MaybeUninit<T>; N]>; |
| 58 | |
| 59 | fn into_internal(self) -> Self::Internal { |
| 60 | UnsafeCell::new(self) |
| 61 | } |
| 62 | unsafe fn from_internal(this: Self::Internal) -> Self { |
| 63 | this.into_inner() |
| 64 | } |
| 65 | |
| 66 | #[inline ] |
| 67 | fn as_mut_ptr(this: &Self::Internal) -> *mut MaybeUninit<T> { |
| 68 | this.get() as *mut _ |
| 69 | } |
| 70 | #[inline ] |
| 71 | fn len(_: &Self::Internal) -> usize { |
| 72 | N |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | #[cfg (feature = "alloc" )] |
| 77 | unsafe impl<T> Container<T> for Vec<MaybeUninit<T>> { |
| 78 | type Internal = Self; |
| 79 | |
| 80 | fn into_internal(self) -> Self::Internal { |
| 81 | self |
| 82 | } |
| 83 | unsafe fn from_internal(this: Self::Internal) -> Self { |
| 84 | this |
| 85 | } |
| 86 | |
| 87 | #[inline ] |
| 88 | fn as_mut_ptr(this: &Self::Internal) -> *mut MaybeUninit<T> { |
| 89 | this.as_ptr() as *mut _ |
| 90 | } |
| 91 | #[inline ] |
| 92 | fn len(this: &Self::Internal) -> usize { |
| 93 | this.len() |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | /// Wrapper for container that provides multiple write access to it. |
| 98 | pub(crate) struct SharedStorage<T, C: Container<T>> { |
| 99 | container: C::Internal, |
| 100 | _p: PhantomData<T>, |
| 101 | } |
| 102 | |
| 103 | unsafe impl<T, C: Container<T>> Sync for SharedStorage<T, C> where T: Send {} |
| 104 | |
| 105 | impl<T, C: Container<T>> SharedStorage<T, C> { |
| 106 | /// Create new storage. |
| 107 | /// |
| 108 | /// *Panics if container is empty.* |
| 109 | pub fn new(container: C) -> Self { |
| 110 | let internal = container.into_internal(); |
| 111 | assert!(C::len(&internal) > 0); |
| 112 | Self { |
| 113 | container: internal, |
| 114 | _p: PhantomData, |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | /// Get the length of the container. |
| 119 | #[inline ] |
| 120 | pub fn len(&self) -> NonZeroUsize { |
| 121 | unsafe { NonZeroUsize::new_unchecked(C::len(&self.container)) } |
| 122 | } |
| 123 | |
| 124 | /// Returns a pair of slices between `head` and `tail` positions in the storage. |
| 125 | /// |
| 126 | /// For more information see [`ring_buffer_ranges`]. |
| 127 | /// |
| 128 | /// # Safety |
| 129 | /// |
| 130 | /// There only single reference to any item allowed to exist at the time. |
| 131 | pub unsafe fn as_mut_slices( |
| 132 | &self, |
| 133 | head: usize, |
| 134 | tail: usize, |
| 135 | ) -> (&mut [MaybeUninit<T>], &mut [MaybeUninit<T>]) { |
| 136 | let ranges = ring_buffer_ranges(self.len(), head, tail); |
| 137 | let ptr = C::as_mut_ptr(&self.container); |
| 138 | ( |
| 139 | slice::from_raw_parts_mut(ptr.add(ranges.0.start), ranges.0.len()), |
| 140 | slice::from_raw_parts_mut(ptr.add(ranges.1.start), ranges.1.len()), |
| 141 | ) |
| 142 | } |
| 143 | |
| 144 | /// Returns underlying container. |
| 145 | pub fn into_inner(self) -> C { |
| 146 | unsafe { C::from_internal(self.container) } |
| 147 | } |
| 148 | } |
| 149 | |