1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use core::fmt;
use core::ops::Deref;
use core::borrow::Borrow;
use core::ptr::{self, NonNull, Pointee};
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use std::rc::Rc;
use crate::runtime::gc::{GcBox, GcBoxHeader, GC_STATE, deref_safe, GcTrace};
pub struct Gc<T> where T: GcTrace + ?Sized + 'static {
ptr: NonNull<GcBox<T>>,
_marker: PhantomData<Rc<GcBox<T>>>,
}
impl<T: GcTrace> Gc<T> {
pub fn new(data: T) -> Self {
GC_STATE.with(|gc| {
let mut gc = gc.borrow_mut();
let gcbox = GcBox::new(data);
let header = GcBoxHeader::from_alloc(gcbox);
gc.insert(header);
Self::from_raw(gcbox)
})
}
}
impl<T> Gc<T> where
T: GcTrace + ?Sized + Pointee,
GcBox<T>: Pointee<Metadata = T::Metadata>
{
pub fn from_box(data: Box<T>) -> Self {
GC_STATE.with(|gc| {
let mut gc = gc.borrow_mut();
let gcbox = GcBox::from_box(data);
let header = GcBoxHeader::from_alloc(gcbox);
gc.insert(header);
Self::from_raw(gcbox)
})
}
}
impl<T> Gc<T> where T: GcTrace + ?Sized {
pub(super) fn from_raw(ptr: NonNull<GcBox<T>>) -> Self {
Self { ptr, _marker: PhantomData }
}
#[inline]
pub(super) fn inner(&self) -> &GcBox<T> {
debug_assert!(deref_safe());
unsafe { &*self.ptr.as_ptr() }
}
#[inline]
fn inner_mut(&self) -> &mut GcBox<T> {
debug_assert!(deref_safe());
unsafe { &mut *self.ptr.as_ptr() }
}
pub fn mark_trace(&self) {
self.inner_mut().mark_trace()
}
pub fn ptr_eq<U>(self_gc: &Gc<T>, other_gc: &Gc<U>) -> bool where U: GcTrace + ?Sized {
ptr::eq(self_gc.inner().header(), other_gc.inner().header())
}
pub fn as_id(self_gc: &Gc<T>) -> usize {
self_gc.ptr.as_ptr() as *const () as usize
}
}
impl<T> From<Gc<T>> for Gc<dyn GcTrace> where T: GcTrace {
fn from(handle: Gc<T>) -> Self {
Self {
ptr: handle.ptr,
_marker: PhantomData,
}
}
}
impl<T> AsRef<T> for Gc<T> where T: GcTrace + ?Sized {
fn as_ref(&self) -> &T {
self.deref()
}
}
impl<T> Borrow<T> for Gc<T> where T: GcTrace + ?Sized {
fn borrow(&self) -> &T {
self.deref()
}
}
impl<T> Deref for Gc<T> where T: GcTrace + ?Sized {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
self.inner().value()
}
}
impl<T> Clone for Gc<T> where T: GcTrace + ?Sized {
fn clone(&self) -> Self {
Self {
ptr: self.ptr,
_marker: PhantomData,
}
}
}
impl<T> Copy for Gc<T> where T: GcTrace + ?Sized { }
impl<T> Hash for Gc<T> where T: GcTrace {
fn hash<H>(self: &Self, state: &mut H) where H: Hasher {
<NonNull<GcBox<T>> as Hash>::hash(&self.ptr, state)
}
}
impl<T> fmt::Debug for Gc<T> where T: GcTrace + ?Sized {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
if fmt.alternate() {
write!(fmt, "Gc({:#?})", self.ptr)
} else {
write!(fmt, "Gc({:?})", self.ptr)
}
}
}