Clear all weakrefs but DON'T call callbacks. Instead, return them for later invocation. Used by GC to ensure ALL weakrefs are cleared BEFORE any callbacks are invoked. handle_weakrefs() clears all weakrefs first, then invokes callbacks.
(&self, obj: &PyObject)
| 706 | /// Used by GC to ensure ALL weakrefs are cleared BEFORE any callbacks are invoked. |
| 707 | /// handle_weakrefs() clears all weakrefs first, then invokes callbacks. |
| 708 | fn clear_for_gc_collect_callbacks(&self, obj: &PyObject) -> Vec<(PyRef<PyWeak>, PyObjectRef)> { |
| 709 | let obj_addr = obj as *const PyObject as usize; |
| 710 | let _lock = weakref_lock::lock(obj_addr); |
| 711 | |
| 712 | // Clear generic cache |
| 713 | self.generic.store(ptr::null_mut(), Ordering::Relaxed); |
| 714 | |
| 715 | let mut callbacks = Vec::new(); |
| 716 | let mut current = NonNull::new(self.head.load(Ordering::Relaxed)); |
| 717 | while let Some(node) = current { |
| 718 | let next = unsafe { WeakLink::pointers(node).as_ref().get_next() }; |
| 719 | |
| 720 | let wr = unsafe { node.as_ref() }; |
| 721 | |
| 722 | // Mark weakref as dead |
| 723 | wr.0.payload |
| 724 | .wr_object |
| 725 | .store(ptr::null_mut(), Ordering::Relaxed); |
| 726 | |
| 727 | // Unlink from list |
| 728 | unsafe { |
| 729 | let mut ptrs = WeakLink::pointers(node); |
| 730 | ptrs.as_mut().set_prev(None); |
| 731 | ptrs.as_mut().set_next(None); |
| 732 | } |
| 733 | |
| 734 | // Collect callback without invoking only if we can keep weakref alive. |
| 735 | if wr.0.ref_count.safe_inc() { |
| 736 | let wr_ref = unsafe { PyRef::from_raw(wr as *const Py<PyWeak>) }; |
| 737 | let cb = unsafe { wr.0.payload.callback.get().replace(None) }; |
| 738 | if let Some(cb) = cb { |
| 739 | callbacks.push((wr_ref, cb)); |
| 740 | } |
| 741 | } |
| 742 | |
| 743 | current = next; |
| 744 | } |
| 745 | self.head.store(ptr::null_mut(), Ordering::Relaxed); |
| 746 | |
| 747 | callbacks |
| 748 | } |
| 749 | |
| 750 | fn count(&self, obj: &PyObject) -> usize { |
| 751 | let _lock = weakref_lock::lock(obj as *const PyObject as usize); |
no test coverage detected