aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2020-12-28 17:47:51 -0800
committerDavid Tolnay <dtolnay@gmail.com>2020-12-28 18:06:17 -0800
commit85b6bc4a39a68c5b064807e89f1933d898e0f5b6 (patch)
treee7a87a31e86e05c0841aec38e08c6abdc350f383 /src
parent215e77fbec91468f294ea372f7c5524ed890de65 (diff)
downloadcxx-85b6bc4a39a68c5b064807e89f1933d898e0f5b6.tar.gz
Add downgrade conversion from SharedPtr to WeakPtr
Diffstat (limited to 'src')
-rw-r--r--src/cxx.cc5
-rw-r--r--src/shared_ptr.rs19
-rw-r--r--src/weak_ptr.rs16
3 files changed, 40 insertions, 0 deletions
diff --git a/src/cxx.cc b/src/cxx.cc
index e573b446..2e1cc15b 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -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! {