MCPcopy Index your code
hub / github.com/RustPython/RustPython / add

Method add

crates/vm/src/object/core.rs:555–651  ·  view source on GitHub ↗

get_or_create_weakref

(
        &self,
        obj: &PyObject,
        cls: PyTypeRef,
        cls_is_weakref: bool,
        callback: Option<PyObjectRef>,
        dict: Option<PyDictRef>,
    )

Source from the content-addressed store, hash-verified

553
554 /// get_or_create_weakref
555 fn add(
556 &self,
557 obj: &PyObject,
558 cls: PyTypeRef,
559 cls_is_weakref: bool,
560 callback: Option<PyObjectRef>,
561 dict: Option<PyDictRef>,
562 ) -> PyRef<PyWeak> {
563 let is_generic = cls_is_weakref && callback.is_none();
564
565 // Try reuse under lock first (fast path, no allocation)
566 {
567 let _lock = weakref_lock::lock(obj as *const PyObject as usize);
568 if is_generic {
569 let generic_ptr = self.generic.load(Ordering::Relaxed);
570 if !generic_ptr.is_null() {
571 let generic = unsafe { &*generic_ptr };
572 if generic.0.ref_count.safe_inc() {
573 return unsafe { PyRef::from_raw(generic_ptr) };
574 }
575 }
576 }
577 }
578
579 // Allocate OUTSIDE the stripe lock. PyRef::new_ref may trigger
580 // maybe_collect → GC → WeakRefList::clear on another object that
581 // hashes to the same stripe, which would deadlock on the spinlock.
582 let weak_payload = PyWeak {
583 pointers: Pointers::new(),
584 wr_object: Radium::new(obj as *const PyObject as *mut PyObject),
585 callback: UnsafeCell::new(callback),
586 hash: Radium::new(crate::common::hash::SENTINEL),
587 };
588 let weak = PyRef::new_ref(weak_payload, cls, dict);
589
590 // Re-acquire lock for linked list insertion
591 let _lock = weakref_lock::lock(obj as *const PyObject as usize);
592
593 // Re-check: another thread may have inserted a generic ref while we
594 // were allocating outside the lock. If so, reuse it and drop ours.
595 if is_generic {
596 let generic_ptr = self.generic.load(Ordering::Relaxed);
597 if !generic_ptr.is_null() {
598 let generic = unsafe { &*generic_ptr };
599 if generic.0.ref_count.safe_inc() {
600 // Nullify wr_object so drop_inner won't unlink an
601 // un-inserted node (which would corrupt the list head).
602 weak.wr_object.store(ptr::null_mut(), Ordering::Relaxed);
603 return unsafe { PyRef::from_raw(generic_ptr) };
604 }
605 }
606 }
607
608 // Insert into linked list under stripe lock
609 let node_ptr = NonNull::from(&*weak);
610 unsafe {
611 let mut ptrs = WeakLink::pointers(node_ptr);
612 if is_generic {

Callers 4

newMethod · 0.45
downgrade_with_typMethod · 0.45
init_type_hierarchyFunction · 0.45

Calls 13

lockFunction · 0.85
newFunction · 0.85
safe_incMethod · 0.80
set_prevMethod · 0.80
get_nextMethod · 0.80
SomeClass · 0.50
is_noneMethod · 0.45
loadMethod · 0.45
storeMethod · 0.45
set_nextMethod · 0.45
as_mutMethod · 0.45
as_ptrMethod · 0.45

Tested by

no test coverage detected