use std::cell::RefCell;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ptr;
use std::hash::Hash;
use std::hash::Hasher;
use std::borrow::Borrow;
use std::borrow::BorrowMut;
pub struct Grc<T> where T: 'static {
cell: *mut GrcCell<T>
}
impl<T> Grc<T> {
pub fn new(item: T) -> Self {
let cell = Box::new(GrcCell {
header: GrcHeader::new(),
strong_count: 1,
weak_count: 0,
item: Some(item)
});
let cell = Box::into_raw(cell);
unsafe {
GrcStorage::add(cell);
}
Self {
cell: cell
}
}
#[inline]
pub fn downgrade(r: &Grc<T>) -> Weak<T> {
unsafe {
(*r.cell).weak_count += 1;
}
Weak {
cell: r.cell
}
}
#[inline]
pub fn ptr_eq(r1: &Grc<T>, r2: &Grc<T>) -> bool {
ptr::eq(r1.cell, r2.cell)
}
}
impl<T> Drop for Grc<T> {
fn drop(&mut self) {
unsafe {
(*self.cell).strong_count -= 1;
if (*self.cell).strong_count == 0 {
if (*self.cell).weak_count == 0 {
GrcStorage::remove(self.cell);
} else {
if (*self.cell).item.is_some() {
(*self.cell).strong_count +=1;
let _ = (*self.cell).item.take();
(*self.cell).strong_count -=1;
if (*self.cell).weak_count == 0 {
GrcStorage::remove(self.cell);
}
}
}
}
}
}
}
impl<T> Clone for Grc<T> {
#[inline]
fn clone(&self) -> Self {
unsafe {
(*self.cell).strong_count += 1;
}
Self {
cell: self.cell
}
}
}
impl<T> Deref for Grc<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe {
match &((*self.cell).item) {
Some(ref item) => item,
None => panic!("Grc reference cannot be empty")
}
}
}
}
impl<T> DerefMut for Grc<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe {
match &mut ((*self.cell).item) {
Some(ref mut item) => item,
None => panic!("Grc reference cannot be empty")
}
}
}
}
impl<T> PartialEq for Grc<T> where T: PartialEq {
#[inline]
fn eq(&self, other: &Self) -> bool {
(self.deref()).eq(other.deref())
}
}
impl<T> Eq for Grc<T> where T: Eq {}
impl<T> Hash for Grc<T> where T: Hash {
#[inline]
fn hash<H>(&self, state: &mut H)
where H: Hasher
{
(self.deref()).hash(state)
}
}
impl<T> Borrow<T> for Grc<T> {
#[inline]
fn borrow(&self) -> &T {
self.deref()
}
}
impl<T> BorrowMut<T> for Grc<T> {
#[inline]
fn borrow_mut(&mut self) -> &mut T {
self.deref_mut()
}
}
pub struct Weak<T> where T: 'static {
cell: *mut GrcCell<T>
}
impl<T> Weak<T> {
pub fn upgrade(&self) -> Option<Grc<T>> {
unsafe {
match &((*self.cell).item) {
None => None,
Some(_) => {
(*self.cell).strong_count += 1;
Some(Grc {
cell: self.cell
})
}
}
}
}
}
impl<T> Drop for Weak<T> {
fn drop(&mut self) {
unsafe {
(*self.cell).weak_count -= 1;
if (*self.cell).weak_count == 0 {
if (*self.cell).strong_count == 0 {
GrcStorage::remove(self.cell);
}
}
}
}
}
impl<T> Clone for Weak<T> {
#[inline]
fn clone(&self) -> Self {
unsafe {
(*self.cell).weak_count += 1;
}
Self {
cell: self.cell
}
}
}
struct GrcHeader {
state: GrcState,
prev: Option<*mut dyn GrcObject>,
next: Option<*mut dyn GrcObject>
}
impl GrcHeader {
#[inline]
fn new() -> Self {
Self {
state: GrcState::Active,
prev: None,
next: None
}
}
}
trait GrcObject {
fn header_mut(&mut self) -> &mut GrcHeader;
unsafe fn free(&mut self);
unsafe fn destroy(&mut self);
}
struct GrcCell<T> {
header: GrcHeader,
strong_count: usize,
weak_count: usize,
item: Option<T>
}
impl<T> GrcObject for GrcCell<T> {
fn header_mut(&mut self) -> &mut GrcHeader {
&mut self.header
}
unsafe fn free(&mut self) {
let _ = self.item.take();
}
unsafe fn destroy(&mut self) {
let _ = Box::from_raw(self);
}
}
#[derive(PartialEq, Eq)]
enum GrcState {
Active,
FreeObjects
}
pub struct GrcStorage {
state: GrcState,
head_active: Option<*mut dyn GrcObject>,
tail_active: Option<*mut dyn GrcObject>
}
thread_local! {
static STORAGE: RefCell<GrcStorage> = RefCell::new(GrcStorage::new());
}
impl GrcStorage {
fn new() -> Self {
Self {
state: GrcState::Active,
head_active: None,
tail_active: None
}
}
unsafe fn add(p: *mut dyn GrcObject) {
STORAGE.with(|cell| {
let mut storage = cell.borrow_mut();
storage.add_to_active(p)
})
}
unsafe fn remove(p: *mut dyn GrcObject) {
STORAGE.with(|cell| {
{
let h = (*p).header_mut();
match h.state {
GrcState::Active => {
},
GrcState::FreeObjects => {
let mut storage = cell.borrow_mut();
storage.remove_from_active(p);
}
}
}
(*p).destroy();
})
}
unsafe fn add_to_active(&mut self, p: *mut dyn GrcObject) {
let h = (*p).header_mut();
debug_assert!(h.state == GrcState::Active);
debug_assert!(h.prev.is_none());
debug_assert!(h.next.is_none());
h.state = GrcState::FreeObjects;
h.prev = self.tail_active;
h.next = None;
if let Some(x) = self.tail_active {
let tail_h = (*x).header_mut();
tail_h.next = Some(p);
} else if self.head_active.is_none() {
self.head_active = Some(p);
} else {
panic!("Inconsistent state");
}
self.tail_active = Some(p);
}
unsafe fn remove_from_active(&mut self, p: *mut dyn GrcObject) {
let h = (*p).header_mut();
debug_assert!(h.state == GrcState::FreeObjects);
if let Some(x) = h.prev {
let prev_h = (*x).header_mut();
prev_h.next = h.next;
} else if let Some(x) = self.head_active {
if ptr::eq(x as *const u8, p as *const u8) {
self.head_active = h.next;
} else {
panic!("Inconsistent state");
}
} else {
panic!("Inconsistent state");
}
if let Some(x) = h.next {
let next_h = (*x).header_mut();
next_h.prev = h.prev;
} else if let Some(x) = self.tail_active {
if ptr::eq(x as *const u8, p as *const u8) {
self.tail_active = h.prev;
} else {
panic!("Inconsistent state");
}
} else {
panic!("Inconsistent state");
}
h.state = GrcState::Active;
h.prev = None;
h.next = None;
}
pub fn free_thread_local() {
loop {
let mut idle = true;
let mut x_to_free: Option<*mut dyn GrcObject> = None;
STORAGE.with(|cell| {
let mut storage = cell.borrow_mut();
match storage.state {
GrcState::Active => {
storage.state = GrcState::FreeObjects;
idle = false;
},
GrcState::FreeObjects => {
if let Some(x) = storage.head_active {
unsafe {
storage.remove_from_active(x);
x_to_free = Some(x);
idle = false;
}
} else {
storage.state = GrcState::Active;
idle = true;
}
}
}
});
if idle {
break;
}
if let Some(x) = x_to_free {
unsafe {
(*x).free();
}
}
}
}
}
pub fn with_grc_storage<F, R>(f: F) -> R
where F: FnOnce() -> R
{
let result = f();
GrcStorage::free_thread_local();
result
}