mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-28 16:21:04 -05:00
Fix minor SharedPtr/SharedRef issues, and add unit tests (#450)
* The `Default` trait did not actually get derived for `SharedPtr<T>`. This is solved by implementing `Default` manually. * Trait function `Shared::get()` used to return a mutable raw pointer (`*mut Self`), but it would be inconceivable to ever mutate the referenced value. It was changed to return a const pointer instead. * Added some basic unit tests for types `SharedPtr` and `SharedRef`.
This commit is contained in:
parent
b88f9f5bbc
commit
d91970dcf6
2 changed files with 85 additions and 4 deletions
|
@ -113,7 +113,7 @@ impl Shared for Allocator {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn get(ptr: &SharedPtrBase<Self>) -> *mut Self {
|
fn get(ptr: &SharedPtrBase<Self>) -> *const Self {
|
||||||
unsafe { std__shared_ptr__v8__ArrayBuffer__Allocator__get(ptr) }
|
unsafe { std__shared_ptr__v8__ArrayBuffer__Allocator__get(ptr) }
|
||||||
}
|
}
|
||||||
fn reset(ptr: &mut SharedPtrBase<Self>) {
|
fn reset(ptr: &mut SharedPtrBase<Self>) {
|
||||||
|
@ -219,7 +219,7 @@ impl Shared for BackingStore {
|
||||||
std__shared_ptr__v8__BackingStore__CONVERT__std__unique_ptr(unique_ptr)
|
std__shared_ptr__v8__BackingStore__CONVERT__std__unique_ptr(unique_ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn get(ptr: &SharedPtrBase<Self>) -> *mut Self {
|
fn get(ptr: &SharedPtrBase<Self>) -> *const Self {
|
||||||
unsafe { std__shared_ptr__v8__BackingStore__get(ptr) }
|
unsafe { std__shared_ptr__v8__BackingStore__get(ptr) }
|
||||||
}
|
}
|
||||||
fn reset(ptr: &mut SharedPtrBase<Self>) {
|
fn reset(ptr: &mut SharedPtrBase<Self>) {
|
||||||
|
|
|
@ -178,7 +178,7 @@ where
|
||||||
{
|
{
|
||||||
fn clone(shared_ptr: &SharedPtrBase<Self>) -> SharedPtrBase<Self>;
|
fn clone(shared_ptr: &SharedPtrBase<Self>) -> SharedPtrBase<Self>;
|
||||||
fn from_unique_ptr(unique_ptr: UniquePtr<Self>) -> SharedPtrBase<Self>;
|
fn from_unique_ptr(unique_ptr: UniquePtr<Self>) -> SharedPtrBase<Self>;
|
||||||
fn get(shared_ptr: &SharedPtrBase<Self>) -> *mut Self;
|
fn get(shared_ptr: &SharedPtrBase<Self>) -> *const Self;
|
||||||
fn reset(shared_ptr: &mut SharedPtrBase<Self>);
|
fn reset(shared_ptr: &mut SharedPtrBase<Self>);
|
||||||
fn use_count(shared_ptr: &SharedPtrBase<Self>) -> long;
|
fn use_count(shared_ptr: &SharedPtrBase<Self>) -> long;
|
||||||
}
|
}
|
||||||
|
@ -186,6 +186,7 @@ where
|
||||||
/// Private base type which is shared by the `SharedPtr` and `SharedRef`
|
/// Private base type which is shared by the `SharedPtr` and `SharedRef`
|
||||||
/// implementations.
|
/// implementations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
pub struct SharedPtrBase<T: Shared>([usize; 2], PhantomData<T>);
|
pub struct SharedPtrBase<T: Shared>([usize; 2], PhantomData<T>);
|
||||||
|
|
||||||
unsafe impl<T: Shared + Sync> Send for SharedPtrBase<T> {}
|
unsafe impl<T: Shared + Sync> Send for SharedPtrBase<T> {}
|
||||||
|
@ -205,7 +206,6 @@ impl<T: Shared> Drop for SharedPtrBase<T> {
|
||||||
|
|
||||||
/// Wrapper around a C++ shared_ptr. A shared_ptr may be be null.
|
/// Wrapper around a C++ shared_ptr. A shared_ptr may be be null.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Default)]
|
|
||||||
pub struct SharedPtr<T: Shared>(SharedPtrBase<T>);
|
pub struct SharedPtr<T: Shared>(SharedPtrBase<T>);
|
||||||
|
|
||||||
impl<T: Shared> SharedPtr<T> {
|
impl<T: Shared> SharedPtr<T> {
|
||||||
|
@ -238,6 +238,12 @@ impl<T: Shared> Clone for SharedPtr<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Shared> Default for SharedPtr<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(Default::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, U> From<U> for SharedPtr<T>
|
impl<T, U> From<U> for SharedPtr<T>
|
||||||
where
|
where
|
||||||
T: Shared,
|
T: Shared,
|
||||||
|
@ -625,13 +631,85 @@ where
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::ptr::null;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
struct MockSharedObj {
|
||||||
|
pub inner: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MockSharedObj {
|
||||||
|
const INSTANCE_A: Self = Self { inner: 11111 };
|
||||||
|
const INSTANCE_B: Self = Self { inner: 22222 };
|
||||||
|
|
||||||
|
const SHARED_PTR_BASE_A: SharedPtrBase<Self> =
|
||||||
|
SharedPtrBase([1, 1], PhantomData);
|
||||||
|
const SHARED_PTR_BASE_B: SharedPtrBase<Self> =
|
||||||
|
SharedPtrBase([2, 2], PhantomData);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shared for MockSharedObj {
|
||||||
|
fn clone(_: &SharedPtrBase<Self>) -> SharedPtrBase<Self> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_unique_ptr(_: UniquePtr<Self>) -> SharedPtrBase<Self> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(p: &SharedPtrBase<Self>) -> *const Self {
|
||||||
|
match p {
|
||||||
|
&Self::SHARED_PTR_BASE_A => &Self::INSTANCE_A,
|
||||||
|
&Self::SHARED_PTR_BASE_B => &Self::INSTANCE_B,
|
||||||
|
p if p == &Default::default() => null(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(p: &mut SharedPtrBase<Self>) {
|
||||||
|
forget(take(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_count(_: &SharedPtrBase<Self>) -> long {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shared_ptr_and_shared_ref() {
|
||||||
|
let mut shared_ptr_a1 = SharedPtr(MockSharedObj::SHARED_PTR_BASE_A);
|
||||||
|
assert!(!shared_ptr_a1.is_null());
|
||||||
|
|
||||||
|
let shared_ref_a: SharedRef<_> = shared_ptr_a1.take().unwrap();
|
||||||
|
assert_eq!(shared_ref_a.inner, 11111);
|
||||||
|
|
||||||
|
assert!(shared_ptr_a1.is_null());
|
||||||
|
|
||||||
|
let shared_ptr_a2: SharedPtr<_> = shared_ref_a.into();
|
||||||
|
assert!(!shared_ptr_a2.is_null());
|
||||||
|
assert_eq!(shared_ptr_a2.unwrap().inner, 11111);
|
||||||
|
|
||||||
|
let mut shared_ptr_b1 = SharedPtr(MockSharedObj::SHARED_PTR_BASE_B);
|
||||||
|
assert!(!shared_ptr_b1.is_null());
|
||||||
|
|
||||||
|
let shared_ref_b: SharedRef<_> = shared_ptr_b1.take().unwrap();
|
||||||
|
assert_eq!(shared_ref_b.inner, 22222);
|
||||||
|
|
||||||
|
assert!(shared_ptr_b1.is_null());
|
||||||
|
|
||||||
|
let shared_ptr_b2: SharedPtr<_> = shared_ref_b.into();
|
||||||
|
assert!(!shared_ptr_b2.is_null());
|
||||||
|
assert_eq!(shared_ptr_b2.unwrap().inner, 22222);
|
||||||
|
}
|
||||||
|
|
||||||
static TEST_OBJ_DROPPED: AtomicBool = AtomicBool::new(false);
|
static TEST_OBJ_DROPPED: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
struct TestObj {
|
struct TestObj {
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for TestObj {
|
impl Drop for TestObj {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
assert!(!TEST_OBJ_DROPPED.swap(true, Ordering::SeqCst));
|
assert!(!TEST_OBJ_DROPPED.swap(true, Ordering::SeqCst));
|
||||||
|
@ -639,12 +717,15 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestObjRef(TestObj);
|
struct TestObjRef(TestObj);
|
||||||
|
|
||||||
impl Deref for TestObjRef {
|
impl Deref for TestObjRef {
|
||||||
type Target = TestObj;
|
type Target = TestObj;
|
||||||
|
|
||||||
fn deref(&self) -> &TestObj {
|
fn deref(&self) -> &TestObj {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Borrow<TestObj> for TestObjRef {
|
impl Borrow<TestObj> for TestObjRef {
|
||||||
fn borrow(&self) -> &TestObj {
|
fn borrow(&self) -> &TestObj {
|
||||||
&**self
|
&**self
|
||||||
|
|
Loading…
Reference in a new issue