use core::ops::Deref;
use super::linked_list::LinkedList;
struct CountedReference<T> {
value: T,
count: u8,
weaks: LinkedList<*mut WeakReference<T>>,
}
pub struct SharedReference<T> {
value: *mut CountedReference<T>
}
pub struct WeakReference<T> {
is_valid: bool,
value: *mut CountedReference<T>,
}
impl<T> Deref for SharedReference<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
return &((*[Link]).value)
};
}
}
impl<T> Drop for SharedReference<T> {
fn drop(&mut self) {
let count: &mut u8;
unsafe {
count = &mut (*[Link]).count;
};
println!("Reducing the [Link]!");
*count -= 1;
if *count == 0 {
unsafe {
// Box destructor will properly clean up the Heap data
let _ = Box::from_raw([Link]);
println!("Deleting the SmartReference!");
// Invalidate any WeakReference pointing to 'self'
for weak in (*[Link]).[Link]() {
(*(*weak)).is_valid = false;
}
}
}
}
}
impl<T> SharedReference<T> {
pub fn new(value: T) -> SharedReference<T> {
let boxed: Box<CountedReference<T>> = Box::new(CountedReference {
value: value,
count: 1,
weaks: LinkedList::new(),
});
return SharedReference {
value: Box::into_raw(boxed),
};
}
pub fn copy(&self) -> SharedReference<T> {
let count: &mut u8;
unsafe {
count = &mut (*[Link]).count;
};
*count += 1;
return SharedReference {
value: [Link],
};
}
pub fn count(&self) -> u8 {
let count: &u8;
unsafe {
count = &(*[Link]).count;
};
return *count;
}
pub fn downgrade(&self) -> WeakReference<T> {
return WeakReference {
is_valid: true,
value: [Link],
};
}
}
impl<T> Drop for WeakReference<T> {
fn drop(&mut self) {
if self.is_valid {
let weaks: &mut LinkedList<*mut WeakReference<T>>;
unsafe {
weaks = &mut (*[Link]).weaks;
}
for (i, weak) in [Link]().enumerate() {
if std::ptr::eq(self, *weak) {
// Remove myself from the 'weaks' list
[Link](weak);
break;
}
}
}
}
}
impl<T> WeakReference<T> {
pub fn copy(&self) -> WeakReference<T> {
return WeakReference {
is_valid: self.is_valid,
value: [Link],
};
}
pub fn upgrade(&self) -> Option<SharedReference<T>> {
if !self.is_valid {
return None;
}
let count: &mut u8;
unsafe {
count = &mut (*[Link]).count;
};
*count += 1;
return Some(SharedReference {
value: [Link],
});
}
}