blob: 9038f4e0eab2c52d199eee018de35cd54bee8000 [file] [log] [blame]
David Tolnay215e77f2020-12-28 17:09:48 -08001use crate::string::CxxString;
2use core::ffi::c_void;
3use core::fmt::Display;
4use core::marker::PhantomData;
5use core::mem::MaybeUninit;
6
7/// Binding to C++ `std::weak_ptr<T>`.
David Tolnay85b6bc42020-12-28 17:47:51 -08008///
9/// The typical way to construct a WeakPtr from Rust is by [downgrading] from a
10/// SharedPtr.
11///
12/// [downgrading]: crate::SharedPtr::downgrade
David Tolnay215e77f2020-12-28 17:09:48 -080013#[repr(C)]
14pub struct WeakPtr<T>
15where
16 T: WeakPtrTarget,
17{
18 repr: [*mut c_void; 2],
19 ty: PhantomData<T>,
20}
21
22impl<T> WeakPtr<T>
23where
24 T: WeakPtrTarget,
25{
26 /// Makes a new WeakPtr wrapping a null pointer.
27 ///
28 /// Matches the behavior of default-constructing a std::weak\_ptr.
29 pub fn null() -> Self {
30 let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
31 let new = weak_ptr.as_mut_ptr().cast();
32 unsafe {
33 T::__null(new);
34 weak_ptr.assume_init()
35 }
36 }
37}
38
39unsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
40unsafe impl<T> Sync for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
41
42impl<T> Clone for WeakPtr<T>
43where
44 T: WeakPtrTarget,
45{
46 fn clone(&self) -> Self {
47 let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
48 let new = weak_ptr.as_mut_ptr().cast();
49 let this = self as *const Self as *mut c_void;
50 unsafe {
51 T::__clone(this, new);
52 weak_ptr.assume_init()
53 }
54 }
55}
56
57impl<T> Drop for WeakPtr<T>
58where
59 T: WeakPtrTarget,
60{
61 fn drop(&mut self) {
62 let this = self as *mut Self as *mut c_void;
63 unsafe { T::__drop(this) }
64 }
65}
66
67// Methods are private; not intended to be implemented outside of cxxbridge
68// codebase.
69pub unsafe trait WeakPtrTarget {
70 #[doc(hidden)]
71 const __NAME: &'static dyn Display;
72 #[doc(hidden)]
73 unsafe fn __null(new: *mut c_void);
74 #[doc(hidden)]
75 unsafe fn __clone(this: *const c_void, new: *mut c_void);
76 #[doc(hidden)]
David Tolnay85b6bc42020-12-28 17:47:51 -080077 unsafe fn __downgrade(shared: *const c_void, new: *mut c_void);
78 #[doc(hidden)]
David Tolnay215e77f2020-12-28 17:09:48 -080079 unsafe fn __drop(this: *mut c_void);
80}
81
82macro_rules! impl_weak_ptr_target {
83 ($segment:expr, $name:expr, $ty:ty) => {
84 unsafe impl WeakPtrTarget for $ty {
85 const __NAME: &'static dyn Display = &$name;
86 unsafe fn __null(new: *mut c_void) {
87 extern "C" {
88 attr! {
89 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")]
90 fn __null(new: *mut c_void);
91 }
92 }
93 __null(new);
94 }
95 unsafe fn __clone(this: *const c_void, new: *mut c_void) {
96 extern "C" {
97 attr! {
98 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")]
99 fn __clone(this: *const c_void, new: *mut c_void);
100 }
101 }
102 __clone(this, new);
103 }
David Tolnay85b6bc42020-12-28 17:47:51 -0800104 unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) {
105 extern "C" {
106 attr! {
107 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$downgrade")]
108 fn __downgrade(shared: *const c_void, weak: *mut c_void);
109 }
110 }
111 __downgrade(shared, weak);
112 }
David Tolnay215e77f2020-12-28 17:09:48 -0800113 unsafe fn __drop(this: *mut c_void) {
114 extern "C" {
115 attr! {
116 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")]
117 fn __drop(this: *mut c_void);
118 }
119 }
120 __drop(this);
121 }
122 }
123 };
124}
125
126macro_rules! impl_weak_ptr_target_for_primitive {
127 ($ty:ident) => {
128 impl_weak_ptr_target!(stringify!($ty), stringify!($ty), $ty);
129 };
130}
131
132impl_weak_ptr_target_for_primitive!(bool);
133impl_weak_ptr_target_for_primitive!(u8);
134impl_weak_ptr_target_for_primitive!(u16);
135impl_weak_ptr_target_for_primitive!(u32);
136impl_weak_ptr_target_for_primitive!(u64);
137impl_weak_ptr_target_for_primitive!(usize);
138impl_weak_ptr_target_for_primitive!(i8);
139impl_weak_ptr_target_for_primitive!(i16);
140impl_weak_ptr_target_for_primitive!(i32);
141impl_weak_ptr_target_for_primitive!(i64);
142impl_weak_ptr_target_for_primitive!(isize);
143impl_weak_ptr_target_for_primitive!(f32);
144impl_weak_ptr_target_for_primitive!(f64);
145
146impl_weak_ptr_target!("string", "CxxString", CxxString);