Add downgrade conversion from SharedPtr to WeakPtr

This commit is contained in:
David Tolnay 2020-12-28 17:47:51 -08:00
parent 215e77fbec
commit 85b6bc4a39
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
5 changed files with 55 additions and 0 deletions

View File

@ -1797,6 +1797,13 @@ fn write_weak_ptr(out: &mut OutFile, ident: &RustName) {
);
writeln!(out, " ::new (ptr) ::std::weak_ptr<{}>(self);", inner);
writeln!(out, "}}");
writeln!(
out,
"void cxxbridge1$weak_ptr${}$downgrade(const ::std::shared_ptr<{}>& shared, ::std::weak_ptr<{}> *weak) noexcept {{",
instance, inner, inner,
);
writeln!(out, " ::new (weak) ::std::weak_ptr<{}>(shared);", inner);
writeln!(out, "}}");
writeln!(
out,
"void cxxbridge1$weak_ptr${}$drop(::std::weak_ptr<{}> *self) noexcept {{",

View File

@ -1242,6 +1242,7 @@ fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>
let prefix = format!("cxxbridge1$weak_ptr${}$", ident.to_symbol(types));
let link_null = format!("{}null", prefix);
let link_clone = format!("{}clone", prefix);
let link_downgrade = format!("{}downgrade", prefix);
let link_drop = format!("{}drop", prefix);
let begin_span =
@ -1266,6 +1267,13 @@ fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>
}
__clone(this, new);
}
unsafe fn __downgrade(shared: *const ::std::ffi::c_void, weak: *mut ::std::ffi::c_void) {
extern "C" {
#[link_name = #link_downgrade]
fn __downgrade(shared: *const ::std::ffi::c_void, weak: *mut ::std::ffi::c_void);
}
__downgrade(shared, weak);
}
unsafe fn __drop(this: *mut ::std::ffi::c_void) {
extern "C" {
#[link_name = #link_drop]

View File

@ -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(); \

View File

@ -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 {}

View File

@ -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! {