use std::cell::Cell; use std::mem; use std::ops::{Deref, DerefMut}; use std::ptr::NonNull; use log::*; use crate::list::List; use crate::trace::Trace; extern "C" { pub type Data; type Vtable; } pub struct Allocation { header: Header, pub(crate) data: T, } struct Header { list: List>, vtable: *mut Vtable, marked: Cell, } impl Allocation { pub fn new(data: T) -> Ptr> { let vtable = extract_vtable(&data); let allocation = Box::new(Allocation { header: Header { list: List::default(), vtable, marked: Cell::new(false), }, data, }); unsafe { Ptr(NonNull::new_unchecked(Box::into_raw(allocation))) } } } impl Allocation { pub unsafe fn free(self: *mut Allocation) { (&mut *self).dyn_data_mut().finalize(); drop(Box::from_raw(self)) } } impl Allocation { pub unsafe fn mark(&self) { debug!( "MARKING object at: {:x}", self.erased() as *const _ as usize ); if !self.header.marked.replace(true) { self.dyn_data().mark() } } pub fn data(&self) -> &T { &self.data } pub fn marked(&self) -> bool { self.header.marked.replace(false) } pub fn is_unmanaged(&self) -> bool { self.header.list.is_head() } fn dyn_data(&self) -> &dyn Trace { unsafe { let object = Object { data: self.erased().data() as *const Data, vtable: self.header.vtable, }; mem::transmute::(object) } } fn dyn_data_mut(&mut self) -> &mut dyn Trace { unsafe { let object = Object { data: self.erased().data() as *const Data, vtable: self.header.vtable, }; mem::transmute::(object) } } fn erased(&self) -> &Allocation { unsafe { &*(self as *const Allocation as *const Allocation) } } } impl AsRef>> for Allocation { fn as_ref(&self) -> &List> { &self.header.list } } #[repr(C)] struct Object { data: *const Data, vtable: *mut Vtable, } fn extract_vtable(data: &T) -> *mut Vtable { unsafe { let obj = data as &dyn Trace; mem::transmute::<&dyn Trace, Object>(obj).vtable } } // TODO Remove unstable feature and make types that reflect its traits. unsafe impl Send for Header {} unsafe impl Sync for Header {} unsafe impl Send for Data {} unsafe impl Sync for Data {} pub struct Ptr(pub NonNull); unsafe impl Send for Ptr {} unsafe impl Sync for Ptr {} impl Copy for Ptr {} impl Clone for Ptr { fn clone(&self) -> Ptr { *self } } impl Deref for Ptr { type Target = NonNull; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for Ptr { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } }