Move drop_fn of from_owner into vtable (#801)

This commit is contained in:
Alice Ryhl
2025-11-10 15:16:58 +01:00
committed by GitHub
parent 4b53a29eb2
commit 7ce330f519
+34 -47
View File
@@ -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 {