1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
use alloc::boxed::Box;
use alloc::sync::Arc;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ops::{Deref, Not};
use crate::node::{TryClone, XNode};
/// A trait for the types users wish to store in an `XArray`.
///
/// Items stored in an `XArray` must be representable by a `*const ()` aligned to 4. We prefer
/// `*const ()` than `usize` to make the implementation conform to [Strict Provenance][1].
///
/// [1]: https://doc.rust-lang.org/std/ptr/index.html#strict-provenance
///
/// # Safety
///
/// Users must ensure that [`ItemEntry::into_raw`] always produce `*const ()`s that meet the above
/// alignment requirements.
///
/// Users must also ensure that as long as the value does not get dropped (e.g., by dropping the
/// value obtaining from [`ItemEntry::from_raw`]), it is safe to invoke [`ItemEntry::raw_as_ref`]
/// multiple times to obtain values of [`ItemEntry::Ref`] that behave just like shared references
/// to the underleying data.
pub unsafe trait ItemEntry {
/// A type that behaves just like a shared references to the underleying data.
type Ref<'a>: Deref<Target = Self>
where
Self: 'a;
/// Converts the original value into a `*const ()`, consuming the ownership of the original
/// value.
fn into_raw(self) -> *const ();
/// Recovers the original value from a `*const ()`, reclaiming the ownership of the original
/// value.
///
/// # Safety
///
/// The original value must have not been dropped, and all references obtained from
/// [`ItemEntry::raw_as_ref`] must be dead.
unsafe fn from_raw(raw: *const ()) -> Self;
/// Obtains a shared reference to the original value.
///
/// # Safety
///
/// The original value must outlive the lifetime parameter `'a`, and during `'a` no mutable
/// references to the value will exist.
unsafe fn raw_as_ref<'a>(raw: *const ()) -> Self::Ref<'a>;
}
/// A type that represents `&'a Arc<T>`.
#[derive(PartialEq, Debug)]
pub struct ArcRef<'a, T> {
inner: ManuallyDrop<Arc<T>>,
_marker: PhantomData<&'a Arc<T>>,
}
impl<'a, T> Deref for ArcRef<'a, T> {
type Target = Arc<T>;
fn deref(&self) -> &Self::Target {
&*self.inner
}
}
// SAFETY: `Arc<T>` meets the safety requirements of `ItemEntry`.
unsafe impl<T> ItemEntry for Arc<T> {
type Ref<'a> = ArcRef<'a, T> where Self: 'a;
fn into_raw(self) -> *const () {
// A contant expression, so compilers should be smart enough to optimize it away.
assert!((core::mem::align_of::<T>() & XEntry::<Self>::TYPE_MASK) == 0);
Arc::into_raw(self).cast()
}
unsafe fn from_raw(raw: *const ()) -> Self {
// SAFETY: By the safety requirements of `ItemEntry::from_raw`, the original value has not
// been dropped and there are no outstanding references to it. Thus, the ownership of the
// original value can be taken.
unsafe { Arc::from_raw(raw.cast()) }
}
unsafe fn raw_as_ref<'a>(raw: *const ()) -> Self::Ref<'a> {
// SAFETY: By the safety requirements of `ItemEntry::raw_as_ref`, the original value
// outlives the lifetime parameter `'a` and during `'a` no mutable references to it can
// exist. Thus, a shared reference to the original value can be created.
unsafe {
ArcRef {
inner: ManuallyDrop::new(Arc::from_raw(raw.cast())),
_marker: PhantomData,
}
}
}
}
/// A type that represents `&'a Box<T>`.
#[derive(PartialEq, Debug)]
pub struct BoxRef<'a, T> {
inner: *mut T,
_marker: PhantomData<&'a Box<T>>,
}
impl<'a, T> Deref for BoxRef<'a, T> {
type Target = Box<T>;
fn deref(&self) -> &Self::Target {
// SAFETY: A `Box<T>` is guaranteed to be represented by a single pointer [1] and a shared
// reference to the `Box<T>` during the lifetime `'a` can be created according to the
// safety requirements of `ItemEntry::raw_as_ref`.
//
// [1]: https://doc.rust-lang.org/std/boxed/#memory-layout
unsafe { core::mem::transmute(&self.inner) }
}
}
// SAFETY: `Box<T>` meets the safety requirements of `ItemEntry`.
unsafe impl<T> ItemEntry for Box<T> {
type Ref<'a> = BoxRef<'a, T> where Self: 'a;
fn into_raw(self) -> *const () {
// A contant expression, so compilers should be smart enough to optimize it away.
assert!((core::mem::align_of::<T>() & XEntry::<Self>::TYPE_MASK) == 0);
Box::into_raw(self).cast_const().cast()
}
unsafe fn from_raw(raw: *const ()) -> Self {
// SAFETY: By the safety requirements of `ItemEntry::from_raw`, the original value has not
// been dropped and there are no outstanding references to it. Thus, the ownership of the
// original value can be taken.
unsafe { Box::from_raw(raw.cast_mut().cast()) }
}
unsafe fn raw_as_ref<'a>(raw: *const ()) -> Self::Ref<'a> {
BoxRef {
inner: raw.cast_mut().cast(),
_marker: PhantomData,
}
}
}
/// A type serving as the basic unit of storage for `XArray`s, used in the head of the `XArray` and
/// the slots of `XNode`s.
///
/// There are the following types of `XEntry`:
/// - Internal entries: These are invisible to users and have the last two bits set to 10.
/// - Item entries: These represent user-given items and have the last two bits set to 00.
///
/// An `XEntry` owns the item or node that it represents. Once an `XEntry` generated from an item
/// or an `XNode`, the ownership of the item or the `XNode` will be transferred to the `XEntry`.
///
/// An `XEntry` behaves just like the item or node it represents. Therefore, if the item type `I`
/// implements the [`Clone`] trait, the `XEntry` will also also implement the [`Clone`] trait.
#[derive(PartialEq, Eq, Debug)]
#[repr(transparent)]
pub(super) struct XEntry<I>
where
I: ItemEntry,
{
raw: *const (),
_marker: core::marker::PhantomData<(Arc<XNode<I>>, I)>,
}
// SAFETY: `XEntry<I>` represents a value of either `Arc<XNode<I>>` or `I`.
unsafe impl<I: ItemEntry> Send for XEntry<I> where (Arc<XNode<I>>, I): Send {}
unsafe impl<I: ItemEntry> Sync for XEntry<I> where (Arc<XNode<I>>, I): Sync {}
#[derive(PartialEq, Eq, Debug)]
#[repr(usize)]
enum EntryType {
Node = 0,
Item = 2,
}
impl TryFrom<usize> for EntryType {
type Error = ();
fn try_from(val: usize) -> Result<Self, Self::Error> {
match val {
x if x == EntryType::Node as usize => Ok(EntryType::Node),
x if x == EntryType::Item as usize => Ok(EntryType::Item),
_ => Err(()),
}
}
}
impl<I: ItemEntry> XEntry<I> {
const TYPE_MASK: usize = 3;
pub const EMPTY: Self = Self {
raw: core::ptr::null(),
_marker: PhantomData,
};
// SAFETY: `ptr` must be returned from `Arc::<XNode<I>>::into_raw` or `I::into_raw` and be
// consistent with `ty`. In addition, the ownership of the value of `Arc<XNode<I>>` or `I` must
// be transferred to the constructed instance of `XEntry`.
unsafe fn new(ptr: *const (), ty: EntryType) -> Self {
let raw = ptr.map_addr(|addr| {
debug_assert!(addr & Self::TYPE_MASK == 0);
addr | (ty as usize)
});
Self {
raw,
_marker: PhantomData,
}
}
fn ptr(&self) -> *const () {
self.raw.map_addr(|addr| addr & !Self::TYPE_MASK)
}
fn ty(&self) -> Option<EntryType> {
self.is_null()
.not()
.then(|| (self.raw.addr() & Self::TYPE_MASK).try_into().unwrap())
}
pub fn is_null(&self) -> bool {
self.raw.is_null()
}
}
pub(super) enum NodeMaybeMut<'a, I>
where
I: ItemEntry,
{
Shared(&'a XNode<I>),
Exclusive(&'a mut XNode<I>),
}
impl<'a, I: ItemEntry> Deref for NodeMaybeMut<'a, I> {
type Target = XNode<I>;
fn deref(&self) -> &XNode<I> {
match &self {
Self::Shared(ref node) => node,
Self::Exclusive(ref node) => node,
}
}
}
impl<I: ItemEntry> XEntry<I> {
pub fn from_node(node: XNode<I>) -> Self {
let node_ptr = {
let arc_node = Arc::new(node);
Arc::into_raw(arc_node).cast()
};
// SAFETY: `node_ptr` is returned from `Arc::<Node<I>>::into_raw` and the ownership of the
// value of `Arc<XNode<I>>` is transferred.
unsafe { Self::new(node_ptr, EntryType::Node) }
}
pub fn is_node(&self) -> bool {
self.ty() == Some(EntryType::Node)
}
pub fn as_node_ref(&self) -> Option<&XNode<I>> {
if !self.is_node() {
return None;
}
// SAFETY: `self` owns the value of `Arc<XNode<I>>`.
Some(unsafe { &*self.ptr().cast() })
}
pub fn as_node_maybe_mut(&mut self) -> Option<NodeMaybeMut<'_, I>> {
match self.node_strong_count() {
0 => None,
// SAFETY: `&mut self` ensures the exclusive access to the value of `Arc<XNode<I>>`,
// and `node_strong_count() == 1` ensures the exclusive access to the value of
// `XNode<I>`.
1 => Some(NodeMaybeMut::Exclusive(unsafe {
&mut *self.ptr().cast_mut().cast()
})),
// SAFETY: `self` owns the value of `Arc<XNode<I>>`.
_ => Some(NodeMaybeMut::Shared(unsafe { &*self.ptr().cast() })),
}
}
pub fn as_node_mut_or_cow(&mut self) -> Option<&mut XNode<I>> {
match self.node_strong_count() {
0 => return None,
// SAFETY: `&mut self` ensures the exclusive access to the value of `Arc<XNode<I>>`,
// and `node_strong_count() == 1` ensures the exclusive access to the value of
// `XNode<I>`.
1 => return Some(unsafe { &mut *self.ptr().cast_mut().cast() }),
_ => (),
}
// SAFETY: `self` owns the value of `Arc<XNode<I>>`.
let node: &XNode<I> = unsafe { &*self.ptr().cast() };
let new_node = node.try_clone().unwrap();
*self = Self::from_node(new_node);
// SAFETY: `node_strong_count() == 1` now holds.
Some(unsafe { &mut *self.ptr().cast_mut().cast() })
}
fn node_strong_count(&self) -> usize {
if !self.is_node() {
return 0;
}
// SAFETY: `self` owns the value of `Arc<XNode<I>>` and the constructed instance of
// `Arc<XNode<I>>` will not be dropped.
let node = unsafe { ManuallyDrop::new(Arc::<XNode<I>>::from_raw(self.ptr().cast())) };
Arc::strong_count(&*node)
}
}
impl<I: ItemEntry> XEntry<I> {
pub fn from_item(item: I) -> Self {
let item_ptr = I::into_raw(item);
// SAFETY: `item_ptr` is returned from `I::from_raw` and the ownership of the value of `I`
// is transferred.
unsafe { Self::new(item_ptr, EntryType::Item) }
}
pub fn is_item(&self) -> bool {
self.ty() == Some(EntryType::Item)
}
pub fn into_item(self) -> Option<I> {
if !self.is_item() {
return None;
}
let ptr = self.ptr();
core::mem::forget(self);
// SAFETY: `self` owns the value of `I`.
Some(unsafe { I::from_raw(ptr) })
}
pub fn as_item_ref(&self) -> Option<I::Ref<'_>> {
if !self.is_item() {
return None;
}
let ptr = self.ptr();
// SAFETY: `self` owns the value of `I` and does not create any mutable references to the
// value. Thus, the value of `I` outlives the lifetime of `&self`.
Some(unsafe { I::raw_as_ref(ptr) })
}
}
impl<I: ItemEntry> Drop for XEntry<I> {
fn drop(&mut self) {
match self.ty() {
None => (),
// SAFETY: `self` owns the value of `I`.
Some(EntryType::Item) => unsafe {
I::from_raw(self.ptr());
},
// SAFETY: `self` owns the value of `Arc<XNode<I>>`.
Some(EntryType::Node) => unsafe {
Arc::<XNode<I>>::from_raw(self.ptr().cast());
},
}
}
}
impl<I: ItemEntry + Clone> Clone for XEntry<I> {
fn clone(&self) -> Self {
match self.ty() {
None => Self::EMPTY,
Some(EntryType::Item) => {
// SAFETY: `self` owns the value of `I` and does not create any mutable references to the
// value. Thus, the value of `I` outlives the lifetime of `&self`.
let item_entry = unsafe { I::raw_as_ref(self.ptr()) };
Self::from_item((*item_entry).clone())
}
// SAFETY: `self` owns the value of `Arc<XNode<T>>`, and `Arc` can be cloned by
// increasing its strong count.
Some(EntryType::Node) => unsafe {
Arc::<XNode<I>>::increment_strong_count(self.ptr().cast());
Self {
raw: self.raw,
_marker: PhantomData,
}
},
}
}
}