renamed Value<T> to SmallBox<T>
This commit is contained in:
parent
2ef2744eca
commit
5881f8e26a
|
@ -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 {
|
||||||
|
|
|
@ -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],
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue