diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/cxx/src/weak_ptr.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/cxx/src/weak_ptr.rs')
-rw-r--r-- | vendor/cxx/src/weak_ptr.rs | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/vendor/cxx/src/weak_ptr.rs b/vendor/cxx/src/weak_ptr.rs new file mode 100644 index 000000000..e9320f374 --- /dev/null +++ b/vendor/cxx/src/weak_ptr.rs @@ -0,0 +1,189 @@ +use crate::shared_ptr::{SharedPtr, SharedPtrTarget}; +use crate::string::CxxString; +use core::ffi::c_void; +use core::fmt::{self, Debug}; +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 + T: WeakPtrTarget, +{ + repr: [MaybeUninit<*mut c_void>; 2], + ty: PhantomData<T>, +} + +impl<T> WeakPtr<T> +where + T: WeakPtrTarget, +{ + /// Makes a new WeakPtr wrapping a null pointer. + /// + /// Matches the behavior of default-constructing a std::weak\_ptr. + pub fn null() -> Self { + let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit(); + let new = weak_ptr.as_mut_ptr().cast(); + unsafe { + T::__null(new); + weak_ptr.assume_init() + } + } + + /// Upgrades a non-owning reference into an owning reference if possible, + /// otherwise to a null reference. + /// + /// Matches the behavior of [std::weak_ptr\<T\>::lock](https://en.cppreference.com/w/cpp/memory/weak_ptr/lock). + pub fn upgrade(&self) -> SharedPtr<T> + where + T: SharedPtrTarget, + { + let this = self as *const Self as *const c_void; + let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit(); + let new = shared_ptr.as_mut_ptr().cast(); + unsafe { + T::__upgrade(this, new); + shared_ptr.assume_init() + } + } +} + +unsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {} +unsafe impl<T> Sync for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {} + +impl<T> Clone for WeakPtr<T> +where + T: WeakPtrTarget, +{ + fn clone(&self) -> Self { + let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit(); + let new = weak_ptr.as_mut_ptr().cast(); + let this = self as *const Self as *mut c_void; + unsafe { + T::__clone(this, new); + weak_ptr.assume_init() + } + } +} + +impl<T> Drop for WeakPtr<T> +where + T: WeakPtrTarget, +{ + fn drop(&mut self) { + let this = self as *mut Self as *mut c_void; + unsafe { T::__drop(this) } + } +} + +impl<T> Debug for WeakPtr<T> +where + T: Debug + WeakPtrTarget + SharedPtrTarget, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.upgrade(), formatter) + } +} + +/// Trait bound for types which may be used as the `T` inside of a `WeakPtr<T>` +/// in generic code. +/// +/// This trait has no publicly callable or implementable methods. Implementing +/// it outside of the CXX codebase is not supported. +pub unsafe trait WeakPtrTarget { + #[doc(hidden)] + fn __typename(f: &mut fmt::Formatter) -> fmt::Result; + #[doc(hidden)] + unsafe fn __null(new: *mut c_void); + #[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 __upgrade(weak: *const c_void, shared: *mut c_void); + #[doc(hidden)] + unsafe fn __drop(this: *mut c_void); +} + +macro_rules! impl_weak_ptr_target { + ($segment:expr, $name:expr, $ty:ty) => { + unsafe impl WeakPtrTarget for $ty { + fn __typename(f: &mut fmt::Formatter) -> fmt::Result { + f.write_str($name) + } + unsafe fn __null(new: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")] + fn __null(new: *mut c_void); + } + } + unsafe { __null(new) } + } + unsafe fn __clone(this: *const c_void, new: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")] + fn __clone(this: *const c_void, new: *mut c_void); + } + } + unsafe { __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); + } + } + unsafe { __downgrade(shared, weak) } + } + unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$upgrade")] + fn __upgrade(weak: *const c_void, shared: *mut c_void); + } + } + unsafe { __upgrade(weak, shared) } + } + unsafe fn __drop(this: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")] + fn __drop(this: *mut c_void); + } + } + unsafe { __drop(this) } + } + } + }; +} + +macro_rules! impl_weak_ptr_target_for_primitive { + ($ty:ident) => { + impl_weak_ptr_target!(stringify!($ty), stringify!($ty), $ty); + }; +} + +impl_weak_ptr_target_for_primitive!(bool); +impl_weak_ptr_target_for_primitive!(u8); +impl_weak_ptr_target_for_primitive!(u16); +impl_weak_ptr_target_for_primitive!(u32); +impl_weak_ptr_target_for_primitive!(u64); +impl_weak_ptr_target_for_primitive!(usize); +impl_weak_ptr_target_for_primitive!(i8); +impl_weak_ptr_target_for_primitive!(i16); +impl_weak_ptr_target_for_primitive!(i32); +impl_weak_ptr_target_for_primitive!(i64); +impl_weak_ptr_target_for_primitive!(isize); +impl_weak_ptr_target_for_primitive!(f32); +impl_weak_ptr_target_for_primitive!(f64); + +impl_weak_ptr_target!("string", "CxxString", CxxString); |