Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce SharedBuf trait for Bytes VTable #596

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
518 changes: 95 additions & 423 deletions src/bytes.rs

Large diffs are not rendered by default.

81 changes: 47 additions & 34 deletions src/bytes_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ use alloc::{
};

use crate::buf::{IntoIter, UninitSlice};
use crate::bytes::Vtable;
#[allow(unused)]
use crate::loom::sync::atomic::AtomicMut;
use crate::loom::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
use crate::shared_buf::{BufferParts, SharedBuf};
use crate::{Buf, BufMut, Bytes};

/// A unique reference to a contiguous slice of memory.
Expand Down Expand Up @@ -253,9 +253,9 @@ impl BytesMut {

let ptr = self.ptr.as_ptr();
let len = self.len;
let data = AtomicPtr::new(self.data.cast());
let shared = self.data;
mem::forget(self);
unsafe { Bytes::with_vtable(ptr, len, data, &SHARED_VTABLE) }
Bytes::from_shared_buf(SharedImpl { shared, ptr, len })
}
}

Expand Down Expand Up @@ -1703,46 +1703,59 @@ unsafe fn rebuild_vec(ptr: *mut u8, mut len: usize, mut cap: usize, off: usize)

// ===== impl SharedVtable =====

static SHARED_VTABLE: Vtable = Vtable {
clone: shared_v_clone,
to_vec: shared_v_to_vec,
drop: shared_v_drop,
};
struct SharedImpl {
shared: *mut Shared,
ptr: *const u8,
len: usize,
}

unsafe fn shared_v_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
let shared = data.load(Ordering::Relaxed) as *mut Shared;
increment_shared(shared);
unsafe impl SharedBuf for SharedImpl {
fn into_parts(this: Self) -> (AtomicPtr<()>, *const u8, usize) {
(AtomicPtr::new(this.shared.cast()), this.ptr, this.len)
}

let data = AtomicPtr::new(shared as *mut ());
Bytes::with_vtable(ptr, len, data, &SHARED_VTABLE)
}
unsafe fn from_parts(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Self {
SharedImpl {
shared: (data.with_mut(|p| *p)).cast(),
ptr,
len,
}
}

unsafe fn clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> BufferParts {
let shared = data.load(Ordering::Relaxed) as *mut Shared;
increment_shared(shared);

unsafe fn shared_v_to_vec(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec<u8> {
let shared: *mut Shared = data.load(Ordering::Relaxed).cast();
(AtomicPtr::new(shared.cast()), ptr, len)
}

if (*shared).is_unique() {
let shared = &mut *shared;
unsafe fn into_vec(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) -> Vec<u8> {
let shared: *mut Shared = (data.with_mut(|p| *p)).cast();

// Drop shared
let mut vec = mem::replace(&mut shared.vec, Vec::new());
release_shared(shared);
if (*shared).is_unique() {
let shared = &mut *shared;

// Copy back buffer
ptr::copy(ptr, vec.as_mut_ptr(), len);
vec.set_len(len);
// Drop shared
let mut vec = mem::replace(&mut shared.vec, Vec::new());
release_shared(shared);

vec
} else {
let v = slice::from_raw_parts(ptr, len).to_vec();
release_shared(shared);
v
// Copy back buffer
ptr::copy(ptr, vec.as_mut_ptr(), len);
vec.set_len(len);

vec
} else {
let v = slice::from_raw_parts(ptr, len).to_vec();
release_shared(shared);
v
}
}
}

unsafe fn shared_v_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) {
data.with_mut(|shared| {
release_shared(*shared as *mut Shared);
});
unsafe fn drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) {
data.with_mut(|shared| {
release_shared(*shared as *mut Shared);
});
}
}

// compile-fails
Expand Down
3 changes: 3 additions & 0 deletions src/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod promotable;
pub mod shared;
pub mod static_buf;
Loading