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 {
use std::{
any::Any,
borrow::{Borrow, BorrowMut},
cell::UnsafeCell,
fmt::Debug,
fmt::{Debug, Display},
hint::cold_path,
marker::PhantomPinned,
mem::{self, ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut},
pin::Pin,
ptr::{self, NonNull},
sync::atomic::Ordering,
@ -185,23 +187,114 @@ mod job {
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
/// drop()
unsafe fn get_unchecked(&self, inline: bool) -> T {
if inline {
unsafe { mem::transmute_copy::<MaybeUninit<Box<MaybeUninit<T>>>, T>(&self.0) }
unsafe { mem::transmute_copy::<MaybeUninit<Box<T>>, T>(&self.0) }
} else {
unsafe {
let inner = *self.0.assume_init_read();
inner.assume_init()
unsafe { *self.0.assume_init_read() }
}
}
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 inline = Self::is_inline();
@ -228,12 +321,12 @@ mod job {
this.assume_init()
}
} 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) {
// drop contained value.
drop(unsafe { self.get_unchecked(Self::is_inline()) });
@ -374,7 +467,7 @@ mod job {
union ValueOrThis<T> {
uninit: (),
value: ManuallyDrop<Value<T>>,
value: ManuallyDrop<SmallBox<T>>,
this: NonNull<()>,
}
@ -568,7 +661,7 @@ mod job {
ManuallyDrop::take(&mut (&mut *self.val_or_this.get()).value)
};
Ok(val.get())
Ok(val.into_inner())
};
return result;
@ -647,7 +740,7 @@ mod job {
match result {
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);
},
Err(err) => unsafe {

View file

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