diff options
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! { |