Skip to main content

aeon_tk/
shared.rs

1//! Helpers for working with slices of unsafe cells.
2
3use std::{cell::UnsafeCell, ops::Range, slice};
4
5/// Represents a reference to a slice which may be shared among threads. This uses `UnsafeCell` to
6/// Uphold rust's immutability gaurentees, but it is the responsibility of the user that the values
7/// at two different indices are not aliased improperly.
8#[repr(transparent)]
9#[derive(Clone, Copy)]
10pub struct SharedSlice<'a, T>(&'a [SyncUnsafeCell<T>]);
11
12impl<'a, T> SharedSlice<'a, T> {
13    pub fn new(data: &'a mut [T]) -> Self {
14        Self(unsafe {
15            slice::from_raw_parts(data.as_ptr() as *const SyncUnsafeCell<T>, data.len())
16        })
17    }
18
19    pub fn len(self) -> usize {
20        self.0.len()
21    }
22
23    pub fn is_empty(self) -> bool {
24        self.len() == 0
25    }
26
27    /// Retrieves a reference to the `index`th element of the slice.
28    ///
29    /// # Safety
30    /// No mutable references to this element may exist when this function is called.
31    pub unsafe fn get(self, index: usize) -> &'a T {
32        unsafe { &*self.0[index].get() }
33    }
34
35    /// Retrieves a mutable reference to the `index`th element of the slice.
36    ///
37    /// # Safety
38    /// No mutable or immutable references to this element may exist when this function is called.
39    pub unsafe fn get_mut(self, index: usize) -> &'a mut T {
40        unsafe { &mut *self.0[index].get() }
41    }
42
43    pub unsafe fn slice(self, range: Range<usize>) -> &'a [T] {
44        debug_assert!(range.start <= self.0.len());
45        debug_assert!(range.end <= self.0.len());
46
47        if range.start >= range.end {
48            return &[];
49        }
50
51        unsafe { core::slice::from_raw_parts(self.get(range.start), range.end - range.start) }
52    }
53
54    pub unsafe fn slice_mut(self, range: Range<usize>) -> &'a mut [T] {
55        debug_assert!(range.start <= self.0.len());
56        debug_assert!(range.end <= self.0.len());
57
58        if range.start >= range.end {
59            return &mut [];
60        }
61        unsafe {
62            core::slice::from_raw_parts_mut(self.get_mut(range.start), range.end - range.start)
63        }
64    }
65}
66
67/// Wrapper around `UnsafeCell` that also implements sync.
68#[repr(transparent)]
69struct SyncUnsafeCell<T: ?Sized> {
70    value: UnsafeCell<T>,
71}
72
73unsafe impl<T: ?Sized + Sync> Sync for SyncUnsafeCell<T> {}
74
75// Identical interface as UnsafeCell:
76impl<T: ?Sized> SyncUnsafeCell<T> {
77    pub const fn get(&self) -> *mut T {
78        self.value.get()
79    }
80}