diff options
author | David Tolnay <dtolnay@gmail.com> | 2020-12-28 17:09:48 -0800 |
---|---|---|
committer | David Tolnay <dtolnay@gmail.com> | 2020-12-28 17:41:20 -0800 |
commit | 215e77fbec91468f294ea372f7c5524ed890de65 (patch) | |
tree | 73fdfa32580be49721a028616cb6961ec90b09f2 /src | |
parent | cd1430c5ef65932a24c7fd2fd478db16a8cb19e1 (diff) | |
download | cxx-215e77fbec91468f294ea372f7c5524ed890de65.tar.gz |
Add Rust std::weak_ptr binding
Diffstat (limited to 'src')
-rw-r--r-- | src/cxx.cc | 15 | ||||
-rw-r--r-- | src/lib.rs | 4 | ||||
-rw-r--r-- | src/weak_ptr.rs | 130 |
3 files changed, 148 insertions, 1 deletions
@@ -508,6 +508,21 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *), void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \ const std::shared_ptr<CXX_TYPE> *self) noexcept { \ self->~shared_ptr(); \ + } \ + static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \ + static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), ""); \ + void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null( \ + std::weak_ptr<CXX_TYPE> *ptr) noexcept { \ + new (ptr) std::weak_ptr<CXX_TYPE>(); \ + } \ + void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone( \ + const std::weak_ptr<CXX_TYPE> &self, \ + std::weak_ptr<CXX_TYPE> *ptr) noexcept { \ + new (ptr) std::weak_ptr<CXX_TYPE>(self); \ + } \ + void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop( \ + const std::weak_ptr<CXX_TYPE> *self) noexcept { \ + self->~weak_ptr(); \ } // Usize and isize are the same type as one of the below. @@ -360,7 +360,6 @@ //! <tr><td>Option<T></td><td><sup><i>tbd</i></sup></td></tr> //! <tr><td><sup><i>tbd</i></sup></td><td>std::map<K, V></td></tr> //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map<K, V></td></tr> -//! <tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr<T></td></tr> //! </table> #![no_std] @@ -411,6 +410,7 @@ mod unique_ptr; mod unwind; #[path = "cxx_vector.rs"] pub mod vector; +mod weak_ptr; pub use crate::exception::Exception; pub use crate::extern_type::{kind, ExternType}; @@ -419,6 +419,7 @@ pub use crate::string::CxxString; pub use crate::unique_ptr::UniquePtr; #[doc(inline)] pub use crate::vector::CxxVector; +pub use crate::weak_ptr::WeakPtr; pub use cxxbridge_macro::bridge; /// For use in impls of the `ExternType` trait. See [`ExternType`]. @@ -457,6 +458,7 @@ pub mod private { pub use crate::unique_ptr::UniquePtrTarget; pub use crate::unwind::catch_unwind; pub use crate::vector::VectorElement; + pub use crate::weak_ptr::WeakPtrTarget; } mod actually_private { diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs new file mode 100644 index 00000000..d73ee8fe --- /dev/null +++ b/src/weak_ptr.rs @@ -0,0 +1,130 @@ +use crate::string::CxxString; +use core::ffi::c_void; +use core::fmt::Display; +use core::marker::PhantomData; +use core::mem::MaybeUninit; + +/// Binding to C++ `std::weak_ptr<T>`. +#[repr(C)] +pub struct WeakPtr<T> +where + T: WeakPtrTarget, +{ + repr: [*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() + } + } +} + +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) } + } +} + +// Methods are private; not intended to be implemented outside of cxxbridge +// codebase. +pub unsafe trait WeakPtrTarget { + #[doc(hidden)] + const __NAME: &'static dyn Display; + #[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 __drop(this: *mut c_void); +} + +macro_rules! impl_weak_ptr_target { + ($segment:expr, $name:expr, $ty:ty) => { + unsafe impl WeakPtrTarget for $ty { + const __NAME: &'static dyn Display = &$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); + } + } + __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); + } + } + __clone(this, new); + } + 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); + } + } + __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); |