renamed Value<T> to SmallBox<T>

This commit is contained in:
Janis 2025-02-21 12:18:59 +01:00
parent 2ef2744eca
commit 5881f8e26a
2 changed files with 120 additions and 27 deletions

View file

@ -170,11 +170,13 @@ mod util {
mod job { mod job {
use std::{ use std::{
any::Any, any::Any,
borrow::{Borrow, BorrowMut},
cell::UnsafeCell, cell::UnsafeCell,
fmt::Debug, fmt::{Debug, Display},
hint::cold_path, hint::cold_path,
marker::PhantomPinned, marker::PhantomPinned,
mem::{self, ManuallyDrop, MaybeUninit}, mem::{self, ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut},
pin::Pin, pin::Pin,
ptr::{self, NonNull}, ptr::{self, NonNull},
sync::atomic::Ordering, sync::atomic::Ordering,
@ -185,23 +187,114 @@ mod job {
use super::util::TaggedAtomicPtr; use super::util::TaggedAtomicPtr;
pub struct Value<T>(pub MaybeUninit<Box<MaybeUninit<T>>>); #[derive(Debug)]
pub struct SmallBox<T>(pub MaybeUninit<Box<T>>);
impl<T> Value<T> { impl<T: Display> Display for SmallBox<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(**self).fmt(f)
}
}
impl<T: Ord> Ord for SmallBox<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_ref().cmp(other.as_ref())
}
}
impl<T: PartialOrd> PartialOrd for SmallBox<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.as_ref().partial_cmp(other.as_ref())
}
}
impl<T: Eq> Eq for SmallBox<T> {}
impl<T: PartialEq> PartialEq for SmallBox<T> {
fn eq(&self, other: &Self) -> bool {
self.as_ref().eq(other.as_ref())
}
}
impl<T: Default> Default for SmallBox<T> {
fn default() -> Self {
Self::new(Default::default())
}
}
impl<T: Clone> Clone for SmallBox<T> {
fn clone(&self) -> Self {
Self::new(self.as_ref().clone())
}
}
impl<T> Deref for SmallBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T> DerefMut for SmallBox<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
}
impl<T> AsRef<T> for SmallBox<T> {
fn as_ref(&self) -> &T {
Self::as_ref(self)
}
}
impl<T> AsMut<T> for SmallBox<T> {
fn as_mut(&mut self) -> &mut T {
Self::as_mut(self)
}
}
impl<T> Borrow<T> for SmallBox<T> {
fn borrow(&self) -> &T {
&**self
}
}
impl<T> BorrowMut<T> for SmallBox<T> {
fn borrow_mut(&mut self) -> &mut T {
&mut **self
}
}
impl<T> SmallBox<T> {
/// must only be called once. takes a reference so this can be called in /// must only be called once. takes a reference so this can be called in
/// drop() /// drop()
unsafe fn get_unchecked(&self, inline: bool) -> T { unsafe fn get_unchecked(&self, inline: bool) -> T {
if inline { if inline {
unsafe { mem::transmute_copy::<MaybeUninit<Box<MaybeUninit<T>>>, T>(&self.0) } unsafe { mem::transmute_copy::<MaybeUninit<Box<T>>, T>(&self.0) }
} else { } else {
unsafe { unsafe { *self.0.assume_init_read() }
let inner = *self.0.assume_init_read(); }
inner.assume_init() }
pub fn as_ref(&self) -> &T {
unsafe {
if Self::is_inline() {
mem::transmute::<&MaybeUninit<Box<T>>, &T>(&self.0)
} else {
self.0.assume_init_ref()
}
}
}
pub fn as_mut(&mut self) -> &mut T {
unsafe {
if Self::is_inline() {
mem::transmute::<&mut MaybeUninit<Box<T>>, &mut T>(&mut self.0)
} else {
self.0.assume_init_mut()
} }
} }
} }
pub fn get(self) -> T { pub fn into_inner(self) -> T {
let this = ManuallyDrop::new(self); let this = ManuallyDrop::new(self);
let inline = Self::is_inline(); let inline = Self::is_inline();
@ -228,12 +321,12 @@ mod job {
this.assume_init() this.assume_init()
} }
} else { } else {
Self(MaybeUninit::new(Box::new(MaybeUninit::new(value)))) Self(MaybeUninit::new(Box::new(value)))
} }
} }
} }
impl<T> Drop for Value<T> { impl<T> Drop for SmallBox<T> {
fn drop(&mut self) { fn drop(&mut self) {
// drop contained value. // drop contained value.
drop(unsafe { self.get_unchecked(Self::is_inline()) }); drop(unsafe { self.get_unchecked(Self::is_inline()) });
@ -374,7 +467,7 @@ mod job {
union ValueOrThis<T> { union ValueOrThis<T> {
uninit: (), uninit: (),
value: ManuallyDrop<Value<T>>, value: ManuallyDrop<SmallBox<T>>,
this: NonNull<()>, this: NonNull<()>,
} }
@ -568,7 +661,7 @@ mod job {
ManuallyDrop::take(&mut (&mut *self.val_or_this.get()).value) ManuallyDrop::take(&mut (&mut *self.val_or_this.get()).value)
}; };
Ok(val.get()) Ok(val.into_inner())
}; };
return result; return result;
@ -647,7 +740,7 @@ mod job {
match result { match result {
Ok(val) => unsafe { Ok(val) => unsafe {
(&mut *self.val_or_this.get()).value = ManuallyDrop::new(Value::new(val)); (&mut *self.val_or_this.get()).value = ManuallyDrop::new(SmallBox::new(val));
(&mut *self.err_or_link.get()).error = ManuallyDrop::new(None); (&mut *self.err_or_link.get()).error = ManuallyDrop::new(None);
}, },
Err(err) => unsafe { Err(err) => unsafe {

View file

@ -201,9 +201,9 @@ fn tagged_ptr_exchange_failure() {
#[test] #[test]
fn value_inline() { fn value_inline() {
let val = Value::new(3usize); let val = SmallBox::new(3usize);
let inner = val.get(); let inner = val.into_inner();
assert_eq!(inner, 3usize); assert_eq!(inner, 3usize);
} }
@ -213,15 +213,15 @@ fn value_inline_struct() {
struct Small { struct Small {
c: f32, c: f32,
} }
let val = Value::new(Small { c: 3.2 }); let val = SmallBox::new(Small { c: 3.2 });
let inner = val.get(); let inner = val.into_inner();
assert_eq!(inner.c, 3.2); assert_eq!(inner.c, 3.2);
} }
#[test] #[test]
fn value_inline_ptr_sized() { fn value_inline_ptr_sized() {
assert!(Value::<usize>::is_inline()); assert!(SmallBox::<usize>::is_inline());
} }
#[test] #[test]
@ -232,13 +232,13 @@ fn value_boxed() {
b: f32, b: f32,
c: u32, c: u32,
} }
let val = Value::new(Big { let val = SmallBox::new(Big {
a: 42, a: 42,
b: 2.25, b: 2.25,
c: 7, c: 7,
}); });
let inner = val.get(); let inner = val.into_inner();
assert_eq!( assert_eq!(
inner, inner,
Big { Big {
@ -261,21 +261,21 @@ fn value_inline_drop() {
*self.inner += 1; *self.inner += 1;
} }
} }
assert!(Value::<Small<'_>>::is_inline()); assert!(SmallBox::<Small<'_>>::is_inline());
let mut dropped = 0; let mut dropped = 0;
{ {
let inner = { let inner = {
let val = Value::new(Small { let val = SmallBox::new(Small {
inner: &mut dropped, inner: &mut dropped,
}); });
val.get() val.into_inner()
}; };
assert_eq!(*inner.inner, 0); assert_eq!(*inner.inner, 0);
} }
assert_eq!(dropped, 1); assert_eq!(dropped, 1);
{ {
let _val = Value::new(Small { let _val = SmallBox::new(Small {
inner: &mut dropped, inner: &mut dropped,
}); });
} }
@ -297,18 +297,18 @@ fn value_boxed_drop() {
let mut dropped = 0; let mut dropped = 0;
{ {
let inner = { let inner = {
let val = Value::new(Big { let val = SmallBox::new(Big {
inner: &mut dropped, inner: &mut dropped,
pad: [0; 3], pad: [0; 3],
}); });
val.get() val.into_inner()
}; };
assert_eq!(*inner.inner, 0); assert_eq!(*inner.inner, 0);
} }
assert_eq!(dropped, 1); assert_eq!(dropped, 1);
{ {
let _val = Value::new(Big { let _val = SmallBox::new(Big {
inner: &mut dropped, inner: &mut dropped,
pad: [0; 3], pad: [0; 3],
}); });