1mod collection;
15
16use collection::{dec_rc, inc_rc};
17pub use collection::{init_gc, process_mutation_buffer};
18use futures::future::Shared;
19pub use scheme_rs_macros::Trace;
20
21use std::{
22 cell::UnsafeCell,
23 collections::{BTreeMap, BTreeSet, HashMap, HashSet},
24 future::Future,
25 marker::PhantomData,
26 ops::{Deref, DerefMut},
27 ptr::{drop_in_place, NonNull},
28 sync::Arc,
29};
30use tokio::sync::{RwLock, Semaphore, SemaphorePermit};
31
32pub struct Gc<T: Trace> {
34 ptr: NonNull<GcInner<T>>,
35 marker: PhantomData<Arc<RwLock<T>>>,
36}
37
38impl<T: Trace> Gc<T> {
39 pub fn new(data: T) -> Gc<T> {
40 Self {
41 ptr: NonNull::from(Box::leak(Box::new(GcInner {
42 header: UnsafeCell::new(GcHeader::default()),
43 data: UnsafeCell::new(data),
44 }))),
45 marker: PhantomData,
46 }
47 }
48}
49
50impl<T: Trace> Gc<T> {
51 pub unsafe fn as_opaque(&self) -> OpaqueGcPtr {
56 self.ptr as OpaqueGcPtr
57 }
58
59 pub async fn read(&self) -> GcReadGuard<'_, T> {
61 unsafe {
62 let _permit = (*self.ptr.as_ref().header.get())
63 .semaphore
64 .acquire()
65 .await
66 .unwrap();
67 let data = &*self.ptr.as_ref().data.get() as *const T;
68 GcReadGuard {
69 _permit,
70 data,
71 marker: PhantomData,
72 }
73 }
74 }
75
76 pub fn try_read(&self) -> Option<GcReadGuard<'_, T>> {
78 unsafe {
79 let _permit = (*self.ptr.as_ref().header.get())
80 .semaphore
81 .try_acquire()
82 .ok()?;
83 let data = &*self.ptr.as_ref().data.get() as *const T;
84 Some(GcReadGuard {
85 _permit,
86 data,
87 marker: PhantomData,
88 })
89 }
90 }
91
92 pub async fn write(&self) -> GcWriteGuard<'_, T> {
94 unsafe {
95 let _permit = (*self.ptr.as_ref().header.get())
96 .semaphore
97 .acquire_many(MAX_READS)
98 .await
99 .unwrap();
100 let data = &mut *self.ptr.as_ref().data.get() as *mut T;
101 GcWriteGuard {
102 _permit,
103 data,
104 marker: PhantomData,
105 }
106 }
107 }
108}
109
110impl<T: Trace> std::fmt::Debug for Gc<T>
111where
112 T: std::fmt::Debug,
113{
114 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 loop {
116 if let Some(x) = self.try_read() {
117 return x.fmt(fmt);
118 }
119 }
120 }
121}
122
123impl<T: Trace> Clone for Gc<T> {
124 fn clone(&self) -> Gc<T> {
125 inc_rc(self.ptr);
126 Self {
127 ptr: self.ptr,
128 marker: PhantomData,
129 }
130 }
131}
132
133impl<T: Trace> Drop for Gc<T> {
134 fn drop(&mut self) {
135 dec_rc(self.ptr);
136 }
137}
138
139unsafe impl<T: Trace + Send + Sync> Send for Gc<T> {}
140unsafe impl<T: Trace + Send + Sync> Sync for Gc<T> {}
141
142#[derive(Copy, Clone, Debug, PartialEq, Eq)]
143enum Color {
144 Black,
146 Gray,
148 White,
150 Purple,
152 Red,
154 Orange,
156}
157
158const MAX_READS: u32 = u32::MAX >> 3;
159
160#[derive(derive_more::Debug)]
161pub struct GcHeader {
162 rc: usize,
163 crc: isize,
164 color: Color,
165 buffered: bool,
166 #[debug(skip)]
167 semaphore: Semaphore,
168}
169
170impl Default for GcHeader {
171 fn default() -> Self {
172 Self {
173 rc: 1,
174 crc: 1,
175 color: Color::Black,
176 buffered: false,
177 semaphore: Semaphore::new(MAX_READS as usize),
178 }
179 }
180}
181
182unsafe impl Send for GcHeader {}
183unsafe impl Sync for GcHeader {}
184
185pub struct GcInner<T: ?Sized> {
186 header: UnsafeCell<GcHeader>,
187 data: UnsafeCell<T>,
188}
189
190unsafe impl<T: ?Sized + Send + Sync> Send for GcInner<T> {}
191unsafe impl<T: ?Sized + Send + Sync> Sync for GcInner<T> {}
192
193type OpaqueGc = GcInner<dyn Trace>;
194pub type OpaqueGcPtr = NonNull<OpaqueGc>;
195
196pub struct GcReadGuard<'a, T: ?Sized> {
197 _permit: SemaphorePermit<'a>,
198 data: *const T,
199 marker: PhantomData<&'a T>,
200}
201
202impl<T: ?Sized> Deref for GcReadGuard<'_, T> {
203 type Target = T;
204
205 fn deref(&self) -> &T {
206 unsafe { &*self.data }
207 }
208}
209
210impl<T: ?Sized> AsRef<T> for GcReadGuard<'_, T> {
211 fn as_ref(&self) -> &T {
212 self
213 }
214}
215
216unsafe impl<T: ?Sized + Send + Sync> Send for GcReadGuard<'_, T> {}
217unsafe impl<T: ?Sized + Send + Sync> Sync for GcReadGuard<'_, T> {}
218
219pub struct GcWriteGuard<'a, T: ?Sized> {
220 _permit: SemaphorePermit<'a>,
221 data: *mut T,
222 marker: PhantomData<&'a mut T>,
223}
224
225impl<T: ?Sized> Deref for GcWriteGuard<'_, T> {
226 type Target = T;
227
228 fn deref(&self) -> &T {
229 unsafe { &*self.data }
230 }
231}
232
233impl<T: ?Sized> DerefMut for GcWriteGuard<'_, T> {
234 fn deref_mut(&mut self) -> &mut T {
235 unsafe { &mut *self.data }
236 }
237}
238
239pub unsafe trait Trace: 'static {
243 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr));
251
252 unsafe fn finalize(&mut self) {
259 drop_in_place(self as *mut Self);
260 }
261}
262
263macro_rules! impl_empty_trace {
264 ( $( $x:ty ),* ) => {
265 $(
266 unsafe impl Trace for $x {
267 unsafe fn visit_children(&self, _visitor: fn(OpaqueGcPtr)) {}
268 }
269 )*
270 }
271}
272
273impl_empty_trace! {
274 (),
275 bool,
276 char,
277 f32,
278 f64,
279 i8,
281 i16,
282 i32,
283 i64,
284 i128,
285 isize,
286 u8,
291 u16,
292 u32,
293 u64,
294 u128,
295 usize,
296 &'static str,
297 String
298}
299
300unsafe trait GcOrTrace: 'static {
304 unsafe fn visit_or_recurse(&self, visitor: fn(OpaqueGcPtr));
305
306 unsafe fn finalize_or_skip(&mut self);
307}
308
309unsafe impl<T: Trace> GcOrTrace for Gc<T> {
310 unsafe fn visit_or_recurse(&self, visitor: fn(OpaqueGcPtr)) {
311 visitor(self.as_opaque())
312 }
313
314 unsafe fn finalize_or_skip(&mut self) {}
315}
316
317unsafe impl<T: Trace + ?Sized> GcOrTrace for T {
318 unsafe fn visit_or_recurse(&self, visitor: fn(OpaqueGcPtr)) {
319 self.visit_children(visitor);
320 }
321
322 unsafe fn finalize_or_skip(&mut self) {
323 self.finalize();
324 }
325}
326
327unsafe impl<A, B> Trace for (A, B)
328where
329 A: GcOrTrace,
330 B: GcOrTrace,
331{
332 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
333 self.0.visit_or_recurse(visitor);
334 self.1.visit_or_recurse(visitor);
335 }
336
337 unsafe fn finalize(&mut self) {
338 self.0.finalize_or_skip();
339 self.1.finalize_or_skip();
340 }
341}
342
343unsafe impl<T> Trace for Vec<T>
344where
345 T: GcOrTrace,
346{
347 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
348 for child in self {
349 child.visit_or_recurse(visitor);
350 }
351 }
352
353 unsafe fn finalize(&mut self) {
354 for mut child in std::mem::take(self).into_iter() {
355 child.finalize_or_skip();
356 std::mem::forget(child);
357 }
358 }
359}
360
361unsafe impl<K> Trace for HashSet<K>
362where
363 K: GcOrTrace,
364{
365 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
366 for k in self {
367 k.visit_or_recurse(visitor);
368 }
369 }
370
371 unsafe fn finalize(&mut self) {
372 for mut k in std::mem::take(self).into_iter() {
373 k.finalize_or_skip();
374 std::mem::forget(k);
375 }
376 }
377}
378
379unsafe impl<K, V> Trace for HashMap<K, V>
380where
381 K: GcOrTrace,
382 V: GcOrTrace,
383{
384 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
385 for (k, v) in self {
386 k.visit_or_recurse(visitor);
387 v.visit_or_recurse(visitor);
388 }
389 }
390
391 unsafe fn finalize(&mut self) {
392 for (mut k, mut v) in std::mem::take(self) {
393 k.finalize_or_skip();
394 v.finalize_or_skip();
395 std::mem::forget((k, v));
396 }
397 }
398}
399
400unsafe impl<K> Trace for BTreeSet<K>
401where
402 K: GcOrTrace,
403{
404 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
405 for k in self {
406 k.visit_or_recurse(visitor);
407 }
408 }
409
410 unsafe fn finalize(&mut self) {
411 for mut k in std::mem::take(self) {
412 k.finalize_or_skip();
413 std::mem::forget(k);
414 }
415 }
416}
417
418unsafe impl<K, V> Trace for BTreeMap<K, V>
419where
420 K: GcOrTrace,
421 V: GcOrTrace,
422{
423 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
424 for (k, v) in self {
425 k.visit_or_recurse(visitor);
426 v.visit_or_recurse(visitor);
427 }
428 }
429
430 unsafe fn finalize(&mut self) {
431 for (mut k, mut v) in std::mem::take(self).into_iter() {
432 k.finalize_or_skip();
433 v.finalize_or_skip();
434 std::mem::forget((k, v));
435 }
436 }
437}
438
439unsafe impl<T> Trace for Option<T>
440where
441 T: GcOrTrace,
442{
443 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
444 if let Some(inner) = self {
445 inner.visit_or_recurse(visitor);
446 }
447 }
448
449 unsafe fn finalize(&mut self) {
450 if let Some(inner) = self {
451 inner.finalize_or_skip();
452 }
453 }
454}
455
456unsafe impl<T> Trace for Box<T>
457where
458 T: GcOrTrace,
459{
460 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
461 self.as_ref().visit_or_recurse(visitor);
462 }
463
464 unsafe fn finalize(&mut self) {
465 self.as_mut().finalize_or_skip();
466 todo!("need to dealloc data without dropping box");
467 }
468}
469
470unsafe impl<T> Trace for [T]
471where
472 T: GcOrTrace,
473{
474 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
475 for item in self {
476 item.visit_or_recurse(visitor);
477 }
478 }
479
480 unsafe fn finalize(&mut self) {
481 for item in self {
482 item.finalize_or_skip();
483 }
484 }
485}
486
487unsafe impl<T> Trace for std::sync::Arc<T>
488where
489 T: ?Sized + 'static,
490{
491 unsafe fn visit_children(&self, _visitor: fn(OpaqueGcPtr)) {
492 }
497}
498
499unsafe impl<T> Trace for std::sync::Weak<T>
500where
501 T: ?Sized + 'static,
502{
503 unsafe fn visit_children(&self, _visitor: fn(OpaqueGcPtr)) {
504 }
507}
508
509unsafe impl<T> Trace for Shared<T>
510where
511 T: Future + 'static,
512{
513 unsafe fn visit_children(&self, _visitor: fn(OpaqueGcPtr)) {}
514}
515
516unsafe impl<A: 'static, O: 'static> Trace for fn(A) -> O {
517 unsafe fn visit_children(&self, _visitor: fn(OpaqueGcPtr)) {}
518}
519
520unsafe impl<A: 'static, B: 'static, O: 'static> Trace for fn(A, B) -> O {
521 unsafe fn visit_children(&self, _visitor: fn(OpaqueGcPtr)) {}
522}
523
524unsafe impl<T> Trace for tokio::sync::Mutex<T>
525where
526 T: GcOrTrace,
527{
528 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
529 let lock = self.blocking_lock();
532 lock.visit_or_recurse(visitor);
533 }
534}
535
536unsafe impl<T> Trace for tokio::sync::RwLock<T>
537where
538 T: GcOrTrace,
539{
540 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
541 loop {
543 if let Ok(read_lock) = self.try_read() {
544 read_lock.visit_or_recurse(visitor);
545 return;
546 }
547 }
548 }
549}
550
551unsafe impl<T> Trace for std::sync::Mutex<T>
552where
553 T: GcOrTrace,
554{
555 unsafe fn visit_children(&self, visitor: fn(OpaqueGcPtr)) {
556 let lock = self.lock().unwrap();
558 lock.visit_or_recurse(visitor);
559 }
560}