mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-26 00:00:20 +02:00
Move drop_fn of from_owner into vtable (#801)
This commit is contained in:
+34
-47
@@ -267,10 +267,7 @@ impl Bytes {
|
|||||||
// and: https://github.com/tokio-rs/bytes/pull/742/#discussion_r1813316032
|
// and: https://github.com/tokio-rs/bytes/pull/742/#discussion_r1813316032
|
||||||
|
|
||||||
let owned = Box::into_raw(Box::new(Owned {
|
let owned = Box::into_raw(Box::new(Owned {
|
||||||
lifetime: OwnedLifetime {
|
ref_cnt: AtomicUsize::new(1),
|
||||||
ref_cnt: AtomicUsize::new(1),
|
|
||||||
drop: owned_box_and_drop::<T>,
|
|
||||||
},
|
|
||||||
owner,
|
owner,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -278,7 +275,7 @@ impl Bytes {
|
|||||||
ptr: NonNull::dangling().as_ptr(),
|
ptr: NonNull::dangling().as_ptr(),
|
||||||
len: 0,
|
len: 0,
|
||||||
data: AtomicPtr::new(owned.cast()),
|
data: AtomicPtr::new(owned.cast()),
|
||||||
vtable: &OWNED_VTABLE,
|
vtable: &Owned::<T>::VTABLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
let buf = unsafe { &*owned }.owner.as_ref();
|
let buf = unsafe { &*owned }.owner.as_ref();
|
||||||
@@ -1107,85 +1104,75 @@ unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
|
|||||||
|
|
||||||
// ===== impl OwnedVtable =====
|
// ===== impl OwnedVtable =====
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
struct OwnedLifetime {
|
|
||||||
ref_cnt: AtomicUsize,
|
|
||||||
drop: unsafe fn(*mut ()),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct Owned<T> {
|
struct Owned<T> {
|
||||||
lifetime: OwnedLifetime,
|
ref_cnt: AtomicUsize,
|
||||||
owner: T,
|
owner: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn owned_box_and_drop<T>(ptr: *mut ()) {
|
impl<T> Owned<T> {
|
||||||
let b: Box<Owned<T>> = Box::from_raw(ptr as _);
|
const VTABLE: Vtable = Vtable {
|
||||||
drop(b);
|
clone: owned_clone::<T>,
|
||||||
|
into_vec: owned_to_vec::<T>,
|
||||||
|
into_mut: owned_to_mut::<T>,
|
||||||
|
is_unique: owned_is_unique,
|
||||||
|
drop: owned_drop::<T>,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn owned_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
|
unsafe fn owned_clone<T>(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
|
||||||
let owned = data.load(Ordering::Relaxed);
|
let owned = data.load(Ordering::Relaxed);
|
||||||
let ref_cnt = &(*owned.cast::<OwnedLifetime>()).ref_cnt;
|
let old_cnt = (*owned.cast::<AtomicUsize>()).fetch_add(1, Ordering::Relaxed);
|
||||||
let old_cnt = ref_cnt.fetch_add(1, Ordering::Relaxed);
|
|
||||||
if old_cnt > usize::MAX >> 1 {
|
if old_cnt > usize::MAX >> 1 {
|
||||||
crate::abort()
|
crate::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
Bytes {
|
Bytes {
|
||||||
ptr,
|
ptr,
|
||||||
len,
|
len,
|
||||||
data: AtomicPtr::new(owned as _),
|
data: AtomicPtr::new(owned as _),
|
||||||
vtable: &OWNED_VTABLE,
|
vtable: &Owned::<T>::VTABLE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn owned_to_vec(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec<u8> {
|
unsafe fn owned_to_vec<T>(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec<u8> {
|
||||||
let slice = slice::from_raw_parts(ptr, len);
|
let slice = slice::from_raw_parts(ptr, len);
|
||||||
let vec = slice.to_vec();
|
let vec = slice.to_vec();
|
||||||
owned_drop_impl(data.load(Ordering::Relaxed));
|
owned_drop_impl::<T>(data.load(Ordering::Relaxed));
|
||||||
vec
|
vec
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn owned_to_mut(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> BytesMut {
|
unsafe fn owned_to_mut<T>(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> BytesMut {
|
||||||
BytesMut::from_vec(owned_to_vec(data, ptr, len))
|
BytesMut::from_vec(owned_to_vec::<T>(data, ptr, len))
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn owned_is_unique(_data: &AtomicPtr<()>) -> bool {
|
unsafe fn owned_is_unique(_data: &AtomicPtr<()>) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn owned_drop_impl(owned: *mut ()) {
|
unsafe fn owned_drop_impl<T>(owned: *mut ()) {
|
||||||
let lifetime = owned.cast::<OwnedLifetime>();
|
{
|
||||||
let ref_cnt = &(*lifetime).ref_cnt;
|
let ref_cnt = &*owned.cast::<AtomicUsize>();
|
||||||
|
|
||||||
let old_cnt = ref_cnt.fetch_sub(1, Ordering::Release);
|
let old_cnt = ref_cnt.fetch_sub(1, Ordering::Release);
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
old_cnt > 0 && old_cnt <= usize::MAX >> 1,
|
old_cnt > 0 && old_cnt <= usize::MAX >> 1,
|
||||||
"expected non-zero refcount and no underflow"
|
"expected non-zero refcount and no underflow"
|
||||||
);
|
);
|
||||||
if old_cnt != 1 {
|
if old_cnt != 1 {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
ref_cnt.load(Ordering::Acquire);
|
||||||
}
|
}
|
||||||
ref_cnt.load(Ordering::Acquire);
|
|
||||||
|
|
||||||
let drop_fn = &(*lifetime).drop;
|
drop(Box::<Owned<T>>::from_raw(owned.cast()));
|
||||||
drop_fn(owned)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn owned_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) {
|
unsafe fn owned_drop<T>(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) {
|
||||||
let owned = data.load(Ordering::Relaxed);
|
let owned = data.load(Ordering::Relaxed);
|
||||||
owned_drop_impl(owned);
|
owned_drop_impl::<T>(owned);
|
||||||
}
|
}
|
||||||
|
|
||||||
static OWNED_VTABLE: Vtable = Vtable {
|
|
||||||
clone: owned_clone,
|
|
||||||
into_vec: owned_to_vec,
|
|
||||||
into_mut: owned_to_mut,
|
|
||||||
is_unique: owned_is_unique,
|
|
||||||
drop: owned_drop,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ===== impl PromotableVtable =====
|
// ===== impl PromotableVtable =====
|
||||||
|
|
||||||
static PROMOTABLE_EVEN_VTABLE: Vtable = Vtable {
|
static PROMOTABLE_EVEN_VTABLE: Vtable = Vtable {
|
||||||
|
|||||||
Reference in New Issue
Block a user