weakref_dealloc: remove from list if still linked.
(&self)
| 854 | |
| 855 | /// weakref_dealloc: remove from list if still linked. |
| 856 | fn drop_inner(&self) { |
| 857 | let obj_ptr = self.wr_object.load(Ordering::Acquire); |
| 858 | if obj_ptr.is_null() { |
| 859 | return; // Already cleared by WeakRefList::clear() |
| 860 | } |
| 861 | |
| 862 | let _lock = weakref_lock::lock(obj_ptr as usize); |
| 863 | |
| 864 | // Double-check under lock |
| 865 | let obj_ptr = self.wr_object.load(Ordering::Relaxed); |
| 866 | if obj_ptr.is_null() { |
| 867 | return; // Cleared between our check and lock acquisition |
| 868 | } |
| 869 | |
| 870 | let obj = unsafe { &*obj_ptr }; |
| 871 | // Safety: if a weakref exists pointing to this object, weakref prefix must be present |
| 872 | let wrl = obj.0.weakref_list_ref().unwrap(); |
| 873 | |
| 874 | // Compute our Py<PyWeak> node pointer from payload address |
| 875 | let offset = std::mem::offset_of!(PyInner<Self>, payload); |
| 876 | let py_inner = (self as *const Self) |
| 877 | .cast::<u8>() |
| 878 | .wrapping_sub(offset) |
| 879 | .cast::<PyInner<Self>>(); |
| 880 | let node_ptr = unsafe { NonNull::new_unchecked(py_inner as *mut Py<Self>) }; |
| 881 | |
| 882 | // Unlink from list |
| 883 | unsafe { unlink_weakref(wrl, node_ptr) }; |
| 884 | |
| 885 | // Update generic cache if this was it |
| 886 | if wrl.generic.load(Ordering::Relaxed) == node_ptr.as_ptr() { |
| 887 | wrl.generic.store(ptr::null_mut(), Ordering::Relaxed); |
| 888 | } |
| 889 | |
| 890 | // Mark as dead |
| 891 | self.wr_object.store(ptr::null_mut(), Ordering::Relaxed); |
| 892 | } |
| 893 | } |
| 894 | |
| 895 | impl Drop for PyWeak { |
no test coverage detected