1use crate::utils::ring_buffer_ranges;
2#[cfg(feature = "alloc")]
3use alloc::vec::Vec;
4use 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.*
15pub 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
36unsafe 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
56unsafe 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")]
77unsafe 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.
98pub(crate) struct SharedStorage<T, C: Container<T>> {
99 container: C::Internal,
100 _p: PhantomData<T>,
101}
102
103unsafe impl<T, C: Container<T>> Sync for SharedStorage<T, C> where T: Send {}
104
105impl<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