extra_pointers 0.1.4

Box, Rc and Arc do not suffice? Take some extra

use std::marker::{ Send, Sync, Unsize };
use std::ops::CoerceUnsized;
use std::ptr::Shared;
use std::cell::Cell;
use std::ops::{Deref};
use std::sync::atomic::{AtomicUsize, Ordering};


use std::fmt;

/// Types capable of reference counting by itself
pub trait IntrusiveReferenceCounted {
	unsafe fn acquire_ref(&self) { self.multi_acquire_ref(1) }
	unsafe fn release_ref(&self) { self.multi_release_ref(1) }

	unsafe fn multi_acquire_ref(&self, refs: usize);
	unsafe fn multi_release_ref(&self, refs: usize);
}

pub struct Irc<T: ?Sized + IntrusiveReferenceCounted>(Shared<T>);

impl<T: ?Sized + IntrusiveReferenceCounted, U: ?Sized + IntrusiveReferenceCounted> CoerceUnsized<Irc<U>> for Irc<T> where T: Unsize<U> {}
	
impl<T: IntrusiveReferenceCounted> Irc<T> {
	pub unsafe fn from_pointer(ptr: Shared<T>) -> Self {
		debug_assert!(!ptr.is_null());
		Self::from_pointer_checked(ptr)
	}

	pub unsafe fn from_pointer_preacquired(ptr: Shared<T>) -> Self {
		debug_assert!(!ptr.is_null());
		Self::from_pointer_preacquired_checked(ptr)
	}
}

impl<T: IntrusiveReferenceCounted + ?Sized> Irc<T> {
	pub unsafe fn from_pointer_checked(ptr: Shared<T>) -> Self {
		(**ptr).acquire_ref();
		Irc(ptr)
	}

	pub unsafe fn from_pointer_preacquired_checked(ptr: Shared<T>) -> Self {
		Irc(ptr)
	}
	pub unsafe fn inner(&self) -> Shared<T> { self.0 }
}

impl<T: IntrusiveReferenceCounted + ?Sized> Clone for Irc<T> {
	fn clone(&self) -> Self { unsafe { Irc::from_pointer_checked(self.0) } }
}
impl<T: IntrusiveReferenceCounted + ?Sized> Drop for Irc<T> {
	fn drop(&mut self) {
		unsafe { (**self.0).release_ref(); }
	}
}
impl<T: IntrusiveReferenceCounted + ?Sized> Deref for Irc<T> {
	type Target = T;
	fn deref(&self) -> &T {		
		unsafe { &**self.0 }
	}
}

unsafe impl<T: IntrusiveReferenceCounted + ?Sized> Send for Irc<T> where T: Send {}
unsafe impl<T: IntrusiveReferenceCounted + ?Sized> Sync for Irc<T> where T: Sync + Send {}



impl<T: fmt::Debug + IntrusiveReferenceCounted + ?Sized> fmt::Debug for Irc<T> {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		self.deref().fmt(f)
	}
}

impl<T: fmt::Display + IntrusiveReferenceCounted + ?Sized> fmt::Display for Irc<T> {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		self.deref().fmt(f)	
	}
}


// --------
// Wrappers

pub struct IrcWrapped<T: ?Sized>(Cell<usize>, T);

impl<T: ?Sized, U> CoerceUnsized<IrcWrapped<U>> for IrcWrapped<T> where T: CoerceUnsized<U> {}

impl<T> IrcWrapped<T> {
	fn new_box(value: T) -> *mut Self { Box::into_raw(Box::new(IrcWrapped(Cell::new(1), value))) }
	pub fn new_irc(value: T) -> Irc<Self> { unsafe { Irc::from_pointer_preacquired(Shared::new(Self::new_box(value))) } }
}
impl<T: ?Sized> IrcWrapped<T> {	
	unsafe fn final_release(&self) { Self::del_box(self as *const Self as *mut Self) }
	unsafe fn del_box(ptr: *mut Self) { Box::from_raw(ptr); }
}

impl<T: ?Sized> IntrusiveReferenceCounted for IrcWrapped<T> {
	unsafe fn multi_acquire_ref(&self, refs: usize) {
		self.0.set(self.0.get() + refs);
	}
	unsafe fn multi_release_ref(&self, refs: usize) {
		if self.0.get() != refs {
			self.0.set(self.0.get() - refs)
		} else {
			self.final_release();
		}
	}
}

impl<T: fmt::Debug + ?Sized> fmt::Debug for IrcWrapped<T> {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		write!(f, "[{:?}, {:?}]", &self.1, self.0.get())
	}
}

impl<T: fmt::Display + ?Sized> fmt::Display for IrcWrapped<T> {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		self.1.fmt(f)
	}
}


pub struct AircWrapped<T: ?Sized>(AtomicUsize, T);

impl<T: ?Sized, U> CoerceUnsized<AircWrapped<U>> for AircWrapped<T> where T: CoerceUnsized<U> {}

impl<T> AircWrapped<T> {
	fn new_box(value: T) -> *mut Self { Box::into_raw(Box::new(AircWrapped(AtomicUsize::new(1), value))) }
	pub fn new_irc(value: T) -> Irc<Self> { unsafe { Irc::from_pointer_preacquired(Shared::new(Self::new_box(value))) } }
}
impl<T: ?Sized> AircWrapped<T> {	
	unsafe fn final_release(&self) { Self::del_box(self as *const Self as *mut Self) }
	unsafe fn del_box(ptr: *mut Self) { Box::from_raw(ptr); }
}

impl<T: ?Sized> IntrusiveReferenceCounted for AircWrapped<T> {
	unsafe fn multi_acquire_ref(&self, refs: usize) {
		self.0.fetch_add(refs, Ordering::Relaxed);
	}
	unsafe fn multi_release_ref(&self, refs: usize) {
		if refs == self.0.fetch_sub(refs, Ordering::AcqRel) {
			self.final_release();
		}
	}
}

impl<T: fmt::Debug + ?Sized> fmt::Debug for AircWrapped<T> {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		write!(f, "[{:?}, {:?}]", &self.1, self.0.load(Ordering::Relaxed))
	}
}

impl<T: fmt::Display + ?Sized> fmt::Display for AircWrapped<T> {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		self.1.fmt(f)
	}
}