gc_lib 0.0.0

Rc<RefCell<T>> is just garbage collection
Documentation
use std::{cell::RefCell, fmt, rc::Rc};

pub struct GC<T>(pub Rc<RefCell<T>>);

impl<T> GC<T> {
    pub fn new(value: T) -> Self {
        GC(Rc::new(RefCell::new(value)))
    }

    pub fn borrow(&self) -> std::cell::Ref<T> {
        self.0.borrow()
    }

    pub fn borrow_mut(&self) -> std::cell::RefMut<T> {
        self.0.borrow_mut()
    }

    pub fn strong_count(&self) -> usize {
        Rc::strong_count(&self.0)
    }

    pub fn weak_count(&self) -> usize {
        Rc::weak_count(&self.0)
    }

    pub fn downgrade(&self) -> std::rc::Weak<RefCell<T>> {
        Rc::downgrade(&self.0)
    }

    pub fn upgrade(weak: &std::rc::Weak<RefCell<T>>) -> Option<Self> {
        weak.upgrade().map(GC)
    }
}

impl<T> fmt::Debug for GC<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.borrow().fmt(f)
    }
}

impl<T> Clone for GC<T> {
    fn clone(&self) -> Self {
        GC(self.0.clone())
    }
}


#[cfg(test)]
mod tests {
    use std::rc::Weak;

    use super::*;

    #[test]
    fn test_gc() {
        let _x = GC::new(5);
        let _y = GC::new("Hello, world!");
        let _z = GC::new(vec![1, 2, 3, 4, 5]);

        struct Tracked {
            id: u32,
        }
    
        impl Drop for Tracked {
            fn drop(&mut self) {
                println!("Tracked object {} is being dropped!", self.id);
            }
        }
    
        {
            let obj1 = GC::new(Tracked { id: 1 });
            
            {
                let obj2 = GC::new(Tracked { id: 2 });
                
                let _obj1_ref1 = obj1.clone();
                let _obj1_ref2 = obj1.clone();
                
                assert_eq!(obj1.strong_count(), 3);
                assert_eq!(obj2.strong_count(), 1);
                
            
            } // obj2 will be dropped here when we exit this scope
            assert_eq!(obj1.strong_count(), 1);
        } // Both obj1 and obj2 should be dropped by now
    
    

        struct TrackableResource {
            id: u32,
        }
    
        impl Drop for TrackableResource {
            fn drop(&mut self) {
                println!("Resource {} being dropped!", self.id);
            }
        }
    
        // Create a weak reference tracker
        let tracker: RefCell<Vec<Weak<RefCell<TrackableResource>>>> = RefCell::new(Vec::new());
    
        // Create some GC objects and track them weakly
        {
            let obj = GC::new(TrackableResource { id: 42 });
            
            // Store a weak reference to the internal Rc
            tracker.borrow_mut().push(Rc::downgrade(&obj.0));
            
            assert_eq!(obj.strong_count(), 1);
            assert_eq!(tracker.borrow()[0].upgrade().is_some(), true);
        }
    
        assert_eq!(tracker.borrow()[0].upgrade().is_some(), false);

        }
}