diff options
author | David Tolnay <dtolnay@gmail.com> | 2020-12-28 17:47:51 -0800 |
---|---|---|
committer | David Tolnay <dtolnay@gmail.com> | 2020-12-28 18:06:17 -0800 |
commit | 85b6bc4a39a68c5b064807e89f1933d898e0f5b6 (patch) | |
tree | e7a87a31e86e05c0841aec38e08c6abdc350f383 /src | |
parent | 215e77fbec91468f294ea372f7c5524ed890de65 (diff) | |
download | cxx-85b6bc4a39a68c5b064807e89f1933d898e0f5b6.tar.gz |
Add downgrade conversion from SharedPtr to WeakPtr
Diffstat (limited to 'src')
-rw-r--r-- | src/cxx.cc | 5 | ||||
-rw-r--r-- | src/shared_ptr.rs | 19 | ||||
-rw-r--r-- | src/weak_ptr.rs | 16 |
3 files changed, 40 insertions, 0 deletions
@@ -520,6 +520,11 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *), std::weak_ptr<CXX_TYPE> *ptr) noexcept { \ new (ptr) std::weak_ptr<CXX_TYPE>(self); \ } \ + void cxxbridge1$std$weak_ptr$##RUST_TYPE##$downgrade( \ + const std::shared_ptr<CXX_TYPE> &shared, \ + std::weak_ptr<CXX_TYPE> *weak) noexcept { \ + new (weak) std::weak_ptr<CXX_TYPE>(shared); \ + } \ void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop( \ const std::weak_ptr<CXX_TYPE> *self) noexcept { \ self->~weak_ptr(); \ diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs index 9269e5a2..18f600fb 100644 --- a/src/shared_ptr.rs +++ b/src/shared_ptr.rs @@ -1,5 +1,6 @@ use crate::kind::Trivial; use crate::string::CxxString; +use crate::weak_ptr::{WeakPtr, WeakPtrTarget}; use crate::ExternType; use core::ffi::c_void; use core::fmt::{self, Debug, Display}; @@ -61,6 +62,24 @@ where let this = self as *const Self as *const c_void; unsafe { T::__get(this).as_ref() } } + + /// Constructs new WeakPtr as a non-owning reference to the object managed + /// by `self`. If `self` manages no object, the WeakPtr manages no object + /// too. + /// + /// Matches the behavior of [std::weak_ptr\<T\>::weak_ptr(const std::shared_ptr\<T\> \&)](https://en.cppreference.com/w/cpp/memory/weak_ptr/weak_ptr). + pub fn downgrade(self: &SharedPtr<T>) -> WeakPtr<T> + where + T: WeakPtrTarget, + { + let this = self as *const Self as *const c_void; + let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit(); + let new = weak_ptr.as_mut_ptr().cast(); + unsafe { + T::__downgrade(this, new); + weak_ptr.assume_init() + } + } } unsafe impl<T> Send for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {} diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs index d73ee8fe..9038f4e0 100644 --- a/src/weak_ptr.rs +++ b/src/weak_ptr.rs @@ -5,6 +5,11 @@ use core::marker::PhantomData; use core::mem::MaybeUninit; /// Binding to C++ `std::weak_ptr<T>`. +/// +/// The typical way to construct a WeakPtr from Rust is by [downgrading] from a +/// SharedPtr. +/// +/// [downgrading]: crate::SharedPtr::downgrade #[repr(C)] pub struct WeakPtr<T> where @@ -69,6 +74,8 @@ pub unsafe trait WeakPtrTarget { #[doc(hidden)] unsafe fn __clone(this: *const c_void, new: *mut c_void); #[doc(hidden)] + unsafe fn __downgrade(shared: *const c_void, new: *mut c_void); + #[doc(hidden)] unsafe fn __drop(this: *mut c_void); } @@ -94,6 +101,15 @@ macro_rules! impl_weak_ptr_target { } __clone(this, new); } + unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$downgrade")] + fn __downgrade(shared: *const c_void, weak: *mut c_void); + } + } + __downgrade(shared, weak); + } unsafe fn __drop(this: *mut c_void) { extern "C" { attr! { |