rust-arc-gc 0.1.1

A simple GCArc implementation for Rust
Documentation
use std::{any::TypeId, sync::atomic::{AtomicBool, AtomicUsize}};

use crate::traceable::GCTraceable;


pub struct GCHeapedObject {
    pub value: *mut dyn GCTraceable,
    pub type_id: TypeId,
    pub strong_rc: AtomicUsize,
    pub weak_rc: AtomicUsize,
    pub marked: AtomicBool,
    pub dropped: AtomicBool,
}

#[allow(dead_code)]
impl GCHeapedObject {
    pub fn new<T: GCTraceable + 'static>(value: T) -> Self {
        Self {
            value: Box::into_raw(Box::new(value)),
            type_id: TypeId::of::<T>(),
            strong_rc: AtomicUsize::new(1),
            weak_rc: AtomicUsize::new(0),
            marked: AtomicBool::new(false),
            dropped: AtomicBool::new(false),
        }
    }

    pub fn strong_ref(&self) -> usize {
        self.strong_rc.load(std::sync::atomic::Ordering::SeqCst)
    }

    pub fn weak_ref(&self) -> usize {
        self.weak_rc.load(std::sync::atomic::Ordering::SeqCst)
    }

    pub fn mark(&self) {
        self.marked.store(true, std::sync::atomic::Ordering::SeqCst);
    }

    pub fn unmark(&self) {
        self.marked
            .store(false, std::sync::atomic::Ordering::SeqCst);
    }

    pub fn is_marked(&self) -> bool {
        self.marked.load(std::sync::atomic::Ordering::SeqCst)
    }

    pub fn downcast_mut<T: GCTraceable + 'static>(self: &mut Self) -> &mut T {
        if self.dropped.load(std::sync::atomic::Ordering::SeqCst) {
            panic!("Attempted to access a dropped object");
        }
        if self.type_id != TypeId::of::<T>() {
            panic!("Type mismatch: expected {:?}, found {:?}", TypeId::of::<T>(), self.type_id);
        }
        unsafe { &mut *(self.value as *mut dyn GCTraceable as *mut T) }
    }
    pub fn downcast<T: GCTraceable + 'static>(self: &Self) -> &T {
        if self.dropped.load(std::sync::atomic::Ordering::SeqCst) {
            panic!("Attempted to access a dropped object");
        }
        if self.type_id != TypeId::of::<T>() {
            panic!("Type mismatch: expected {:?}, found {:?}", TypeId::of::<T>(), self.type_id);
        }
        unsafe { &*(self.value as *const dyn GCTraceable as *const T) }
    }

    pub(crate) fn drop_value(self: &mut Self) {
        if self.dropped.load(std::sync::atomic::Ordering::SeqCst) {
            return;
        }
        unsafe {
            drop(Box::from_raw(self.value));
            self.dropped.store(true, std::sync::atomic::Ordering::SeqCst);
        }
    }

    pub fn isinstance<T: GCTraceable + 'static>(&self) -> bool {
        self.type_id == TypeId::of::<T>()
    }

    pub fn as_ref(&self) -> &dyn GCTraceable {
        if self.dropped.load(std::sync::atomic::Ordering::SeqCst) {
            panic!("Attempted to access a dropped object");
        }
        unsafe { &*(self.value as *const dyn GCTraceable) }
    }

    pub fn as_mut(&mut self) -> &mut dyn GCTraceable {
        if self.dropped.load(std::sync::atomic::Ordering::SeqCst) {
            panic!("Attempted to access a dropped object");
        }
        unsafe { &mut *(self.value as *mut dyn GCTraceable) }
    }
}

impl Drop for GCHeapedObject {
    fn drop(&mut self) {
        self.drop_value();        
    }
}