1use crate::{
2 Finalize,
3 lifetime::{Lifetime, LifetimeLazy, ValueReadAccess, ValueWriteAccess},
4 managed::{
5 DynamicManagedLazy, DynamicManagedRef, DynamicManagedRefMut, ManagedLazy, ManagedRef,
6 ManagedRefMut,
7 },
8 non_zero_alloc, non_zero_dealloc,
9 type_hash::TypeHash,
10};
11use std::{
12 alloc::{Layout, handle_alloc_error},
13 marker::PhantomData,
14 mem::MaybeUninit,
15};
16
17enum Kind {
18 Owned {
19 lifetime: Lifetime,
20 data: *mut u8,
21 },
22 Referenced {
23 lifetime: LifetimeLazy,
24 data: *mut u8,
25 },
26}
27
28pub enum ManagedGcLifetime<'a> {
29 Owned(&'a Lifetime),
30 Referenced(&'a LifetimeLazy),
31}
32
33pub struct ManagedGc<T> {
34 dynamic: DynamicManagedGc,
35 _phantom: PhantomData<fn() -> T>,
36}
37
38unsafe impl<T> Send for ManagedGc<T> {}
39unsafe impl<T> Sync for ManagedGc<T> {}
40
41impl<T: Default> Default for ManagedGc<T> {
42 fn default() -> Self {
43 Self::new(T::default())
44 }
45}
46
47impl<T> ManagedGc<T> {
48 pub fn new(data: T) -> Self {
49 Self {
50 dynamic: DynamicManagedGc::new(data),
51 _phantom: PhantomData,
52 }
53 }
54
55 pub fn consume(self) -> Result<T, Self> {
56 self.dynamic.consume().map_err(|value| Self {
57 dynamic: value,
58 _phantom: PhantomData,
59 })
60 }
61
62 pub fn into_dynamic(self) -> DynamicManagedGc {
63 self.dynamic
64 }
65
66 pub fn renew(&mut self) {
67 self.dynamic.renew();
68 }
69
70 pub fn type_hash(&self) -> TypeHash {
71 self.dynamic.type_hash()
72 }
73
74 pub fn lifetime(&self) -> ManagedGcLifetime<'_> {
75 self.dynamic.lifetime()
76 }
77
78 pub fn exists(&self) -> bool {
79 self.dynamic.exists()
80 }
81
82 pub fn is_owning(&self) -> bool {
83 self.dynamic.is_owning()
84 }
85
86 pub fn is_referencing(&self) -> bool {
87 self.dynamic.is_referencing()
88 }
89
90 pub fn is_owned_by(&self, other: &Self) -> bool {
91 self.dynamic.is_owned_by(&other.dynamic)
92 }
93
94 pub fn try_read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
95 self.dynamic.try_read::<T>()
96 }
97
98 pub fn try_write(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
99 self.dynamic.try_write::<T>()
100 }
101
102 pub fn read<const LOCKING: bool>(&'_ self) -> ValueReadAccess<'_, T> {
103 self.dynamic.read::<LOCKING, T>()
104 }
105
106 pub fn write<const LOCKING: bool>(&'_ mut self) -> ValueWriteAccess<'_, T> {
107 self.dynamic.write::<LOCKING, T>()
108 }
109
110 pub fn borrow<const LOCKING: bool>(&self) -> ManagedRef<T> {
111 self.dynamic
112 .borrow::<LOCKING>()
113 .into_typed()
114 .ok()
115 .expect("ManagedGc cannot be immutably borrowed")
116 }
117
118 pub fn borrow_mut<const LOCKING: bool>(&mut self) -> ManagedRefMut<T> {
119 self.dynamic
120 .borrow_mut::<LOCKING>()
121 .into_typed()
122 .ok()
123 .expect("ManagedGc cannot be mutably borrowed")
124 }
125
126 pub fn lazy(&self) -> ManagedLazy<T> {
127 self.dynamic
128 .lazy()
129 .into_typed()
130 .ok()
131 .expect("ManagedGc cannot be lazily borrowed")
132 }
133
134 pub unsafe fn as_ptr(&self) -> *const T {
136 unsafe { self.dynamic.as_ptr_raw().cast::<T>() }
137 }
138
139 pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
141 unsafe { self.dynamic.as_mut_ptr_raw().cast::<T>() }
142 }
143}
144
145impl<T> Clone for ManagedGc<T> {
146 fn clone(&self) -> Self {
147 Self {
148 dynamic: self.dynamic.clone(),
149 _phantom: PhantomData,
150 }
151 }
152}
153
154pub struct DynamicManagedGc {
155 type_hash: TypeHash,
156 kind: Kind,
157 layout: Layout,
158 finalizer: unsafe fn(*mut ()),
159 drop: bool,
160}
161
162unsafe impl Send for DynamicManagedGc {}
163unsafe impl Sync for DynamicManagedGc {}
164
165impl Drop for DynamicManagedGc {
166 fn drop(&mut self) {
167 if let Kind::Owned { lifetime, data } = &mut self.kind
168 && self.drop
169 {
170 while lifetime.state().is_in_use() {
171 std::hint::spin_loop();
172 }
173 lifetime.invalidate();
174 unsafe {
175 if data.is_null() {
176 return;
177 }
178 (self.finalizer)(data.cast::<()>());
179 non_zero_dealloc(*data, self.layout);
180 }
181 }
182 }
183}
184
185impl DynamicManagedGc {
186 pub fn new<T: Finalize>(data: T) -> Self {
187 let layout = Layout::new::<T>().pad_to_align();
188 unsafe {
189 let memory = non_zero_alloc(layout) as *mut T;
190 if memory.is_null() {
191 handle_alloc_error(layout);
192 }
193 memory.cast::<T>().write(data);
194 Self {
195 type_hash: TypeHash::of::<T>(),
196 kind: Kind::Owned {
197 lifetime: Default::default(),
198 data: memory.cast::<u8>(),
199 },
200 layout,
201 finalizer: T::finalize_raw,
202 drop: true,
203 }
204 }
205 }
206
207 pub fn new_raw(
208 type_hash: TypeHash,
209 lifetime: Lifetime,
210 memory: *mut u8,
211 layout: Layout,
212 finalizer: unsafe fn(*mut ()),
213 ) -> Self {
214 if memory.is_null() {
215 handle_alloc_error(layout);
216 }
217 Self {
218 type_hash,
219 kind: Kind::Owned {
220 lifetime,
221 data: memory,
222 },
223 layout,
224 finalizer,
225 drop: true,
226 }
227 }
228
229 pub fn new_uninitialized(
230 type_hash: TypeHash,
231 layout: Layout,
232 finalizer: unsafe fn(*mut ()),
233 ) -> Self {
234 let memory = unsafe { non_zero_alloc(layout) };
235 if memory.is_null() {
236 handle_alloc_error(layout);
237 }
238 Self {
239 type_hash,
240 kind: Kind::Owned {
241 lifetime: Default::default(),
242 data: memory,
243 },
244 layout,
245 finalizer,
246 drop: true,
247 }
248 }
249
250 pub fn consume<T>(mut self) -> Result<T, Self> {
251 if let Kind::Owned { lifetime, data } = &mut self.kind {
252 if self.type_hash == TypeHash::of::<T>() && !lifetime.state().is_in_use() {
253 if data.is_null() {
254 return Err(self);
255 }
256 self.drop = false;
257 let mut result = MaybeUninit::<T>::uninit();
258 unsafe {
259 result.as_mut_ptr().copy_from(data.cast::<T>(), 1);
260 non_zero_dealloc(*data, self.layout);
261 Ok(result.assume_init())
262 }
263 } else {
264 Err(self)
265 }
266 } else {
267 Err(self)
268 }
269 }
270
271 pub fn into_typed<T>(self) -> ManagedGc<T> {
272 ManagedGc {
273 dynamic: self,
274 _phantom: PhantomData,
275 }
276 }
277
278 pub fn renew(&mut self) {
279 if let Kind::Owned { lifetime, .. } = &mut self.kind {
280 *lifetime = Default::default();
281 }
282 }
283
284 pub fn type_hash(&self) -> TypeHash {
285 self.type_hash
286 }
287
288 pub fn lifetime(&self) -> ManagedGcLifetime<'_> {
289 match &self.kind {
290 Kind::Owned { lifetime, .. } => ManagedGcLifetime::Owned(lifetime),
291 Kind::Referenced { lifetime, .. } => ManagedGcLifetime::Referenced(lifetime),
292 }
293 }
294
295 pub fn exists(&self) -> bool {
296 match &self.kind {
297 Kind::Owned { .. } => true,
298 Kind::Referenced { lifetime, .. } => lifetime.exists(),
299 }
300 }
301
302 pub fn is_owning(&self) -> bool {
303 matches!(self.kind, Kind::Owned { .. })
304 }
305
306 pub fn is_referencing(&self) -> bool {
307 matches!(self.kind, Kind::Referenced { .. })
308 }
309
310 pub fn is_owned_by(&self, other: &Self) -> bool {
311 if let (Kind::Referenced { lifetime: l1, .. }, Kind::Owned { lifetime: l2, .. }) =
312 (&self.kind, &other.kind)
313 {
314 l1.state().is_owned_by(l2.state())
315 } else {
316 false
317 }
318 }
319
320 pub fn is<T>(&self) -> bool {
321 self.type_hash == TypeHash::of::<T>()
322 }
323
324 pub fn try_read<T>(&'_ self) -> Option<ValueReadAccess<'_, T>> {
325 if !self.is::<T>() {
326 panic!(
327 "DynamicManagedGc is not of the requested type: {}",
328 std::any::type_name::<T>()
329 );
330 }
331 unsafe {
332 match &self.kind {
333 Kind::Owned { lifetime, data } => {
334 let data = data.cast::<T>().as_ref()?;
335 lifetime.read(data)
336 }
337 Kind::Referenced { lifetime, data } => {
338 if lifetime.exists() {
339 let data = data.cast::<T>().as_ref()?;
340 lifetime.read(data)
341 } else {
342 None
343 }
344 }
345 }
346 }
347 }
348
349 pub fn try_write<T>(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
350 if !self.is::<T>() {
351 panic!(
352 "DynamicManagedGc is not of the requested type: {}",
353 std::any::type_name::<T>()
354 );
355 }
356 unsafe {
357 match &self.kind {
358 Kind::Owned { lifetime, data } => {
359 let data = data.cast::<T>().as_mut()?;
360 lifetime.write(data)
361 }
362 Kind::Referenced { lifetime, data } => {
363 if lifetime.exists() {
364 let data = data.cast::<T>().as_mut()?;
365 lifetime.write(data)
366 } else {
367 None
368 }
369 }
370 }
371 }
372 }
373
374 pub fn read<const LOCKING: bool, T>(&'_ self) -> ValueReadAccess<'_, T> {
375 if !self.is::<T>() {
376 panic!(
377 "DynamicManagedGc is not of the requested type: {}",
378 std::any::type_name::<T>()
379 );
380 }
381 unsafe {
382 if LOCKING {
383 match &self.kind {
384 Kind::Owned { lifetime, data } => loop {
385 let data = data
386 .cast::<T>()
387 .as_ref()
388 .expect("DynamicManagedGc data pointer is null");
389 if let Some(access) = lifetime.read(data) {
390 return access;
391 }
392 std::hint::spin_loop();
393 },
394 Kind::Referenced { lifetime, data } => loop {
395 if !lifetime.exists() {
396 panic!("DynamicManagedGc owner is dead");
397 }
398 let data = data
399 .cast::<T>()
400 .as_ref()
401 .expect("DynamicManagedGc data pointer is null");
402 if let Some(access) = lifetime.read(data) {
403 return access;
404 }
405 std::hint::spin_loop();
406 },
407 }
408 } else {
409 match &self.kind {
410 Kind::Owned { lifetime, data } => {
411 let data = data
412 .cast::<T>()
413 .as_ref()
414 .expect("DynamicManagedGc data pointer is null");
415 lifetime
416 .read(data)
417 .expect("DynamicManagedGc is inaccessible for reading")
418 }
419 Kind::Referenced { lifetime, data } => {
420 let data = data
421 .cast::<T>()
422 .as_ref()
423 .expect("DynamicManagedGc data pointer is null");
424 lifetime
425 .read(data)
426 .expect("DynamicManagedGc is inaccessible for reading")
427 }
428 }
429 }
430 }
431 }
432
433 pub fn write<const LOCKING: bool, T>(&'_ mut self) -> ValueWriteAccess<'_, T> {
434 if !self.is::<T>() {
435 panic!(
436 "DynamicManagedGc is not of the requested type: {}",
437 std::any::type_name::<T>()
438 );
439 }
440 unsafe {
441 if LOCKING {
442 match &self.kind {
443 Kind::Owned { lifetime, data } => loop {
444 let data = data
445 .cast::<T>()
446 .as_mut()
447 .expect("DynamicManagedGc data pointer is null");
448 if let Some(access) = lifetime.write(data) {
449 return access;
450 }
451 std::hint::spin_loop();
452 },
453 Kind::Referenced { lifetime, data } => loop {
454 if !lifetime.exists() {
455 panic!("DynamicManagedGc owner is dead");
456 }
457 let data = data
458 .cast::<T>()
459 .as_mut()
460 .expect("DynamicManagedGc data pointer is null");
461 if let Some(access) = lifetime.write(data) {
462 return access;
463 }
464 std::hint::spin_loop();
465 },
466 }
467 } else {
468 match &self.kind {
469 Kind::Owned { lifetime, data } => {
470 let data = data
471 .cast::<T>()
472 .as_mut()
473 .expect("DynamicManagedGc data pointer is null");
474 lifetime
475 .write(data)
476 .expect("DynamicManagedGc is inaccessible for writing")
477 }
478 Kind::Referenced { lifetime, data } => {
479 let data = data
480 .cast::<T>()
481 .as_mut()
482 .expect("DynamicManagedGc data pointer is null");
483 lifetime
484 .write(data)
485 .expect("DynamicManagedGc is inaccessible for writing")
486 }
487 }
488 }
489 }
490 }
491
492 pub fn borrow<const LOCKING: bool>(&self) -> DynamicManagedRef {
493 unsafe {
494 if LOCKING {
495 match &self.kind {
496 Kind::Owned { lifetime, data } => loop {
497 if let Some(lifetime) = lifetime.borrow() {
498 return DynamicManagedRef::new_raw(self.type_hash, lifetime, *data)
499 .expect("DynamicManagedGc cannot be immutably borrowed");
500 }
501 std::hint::spin_loop();
502 },
503 Kind::Referenced { lifetime, data } => loop {
504 if !lifetime.exists() {
505 panic!("DynamicManagedGc owner is dead");
506 }
507 if let Some(lifetime) = lifetime.borrow() {
508 return DynamicManagedRef::new_raw(self.type_hash, lifetime, *data)
509 .expect("DynamicManagedGc cannot be immutably borrowed");
510 }
511 std::hint::spin_loop();
512 },
513 }
514 } else {
515 match &self.kind {
516 Kind::Owned { lifetime, data } => DynamicManagedRef::new_raw(
517 self.type_hash,
518 lifetime
519 .borrow()
520 .expect("DynamicManagedGc is inaccessible for immutable borrowing"),
521 *data,
522 )
523 .expect("DynamicManagedGc cannot be immutably borrowed"),
524 Kind::Referenced { lifetime, data } => DynamicManagedRef::new_raw(
525 self.type_hash,
526 lifetime
527 .borrow()
528 .expect("DynamicManagedGc is inaccessible for immutable borrowing"),
529 *data,
530 )
531 .expect("DynamicManagedGc cannot be immutably borrowed"),
532 }
533 }
534 }
535 }
536
537 pub fn borrow_mut<const LOCKING: bool>(&mut self) -> DynamicManagedRefMut {
538 unsafe {
539 if LOCKING {
540 match &self.kind {
541 Kind::Owned { lifetime, data } => loop {
542 if let Some(lifetime) = lifetime.borrow_mut() {
543 return DynamicManagedRefMut::new_raw(self.type_hash, lifetime, *data)
544 .expect("DynamicManagedGc cannot be mutably borrowed");
545 }
546 std::hint::spin_loop();
547 },
548 Kind::Referenced { lifetime, data } => loop {
549 if !lifetime.exists() {
550 panic!("DynamicManagedGc owner is dead");
551 }
552 if let Some(lifetime) = lifetime.borrow_mut() {
553 return DynamicManagedRefMut::new_raw(self.type_hash, lifetime, *data)
554 .expect("DynamicManagedGc cannot be mutably borrowed");
555 }
556 std::hint::spin_loop();
557 },
558 }
559 } else {
560 match &self.kind {
561 Kind::Owned { lifetime, data } => DynamicManagedRefMut::new_raw(
562 self.type_hash,
563 lifetime
564 .borrow_mut()
565 .expect("DynamicManagedGc is inaccessible for mutable borrowing"),
566 *data,
567 )
568 .expect("DynamicManagedGc cannot be mutably borrowed"),
569 Kind::Referenced { lifetime, data } => DynamicManagedRefMut::new_raw(
570 self.type_hash,
571 lifetime
572 .borrow_mut()
573 .expect("DynamicManagedGc is inaccessible for mutable borrowing"),
574 *data,
575 )
576 .expect("DynamicManagedGc cannot be mutably borrowed"),
577 }
578 }
579 }
580 }
581
582 pub fn lazy(&self) -> DynamicManagedLazy {
583 unsafe {
584 match &self.kind {
585 Kind::Owned { lifetime, data } => {
586 DynamicManagedLazy::new_raw(self.type_hash, lifetime.lazy(), *data)
587 .expect("DynamicManagedGc cannot be lazily borrowed")
588 }
589 Kind::Referenced { lifetime, data } => {
590 DynamicManagedLazy::new_raw(self.type_hash, lifetime.clone(), *data)
591 .expect("DynamicManagedGc cannot be lazily borrowed")
592 }
593 }
594 }
595 }
596
597 pub unsafe fn as_ptr_raw(&self) -> *const u8 {
599 match &self.kind {
600 Kind::Owned { data, .. } => *data as *const u8,
601 Kind::Referenced { data, .. } => *data as *const u8,
602 }
603 }
604
605 pub unsafe fn as_mut_ptr_raw(&mut self) -> *mut u8 {
607 match &self.kind {
608 Kind::Owned { data, .. } => *data,
609 Kind::Referenced { data, .. } => *data,
610 }
611 }
612}
613
614impl Clone for DynamicManagedGc {
615 fn clone(&self) -> Self {
616 match &self.kind {
617 Kind::Owned { lifetime, data } => Self {
618 type_hash: self.type_hash,
619 kind: Kind::Referenced {
620 lifetime: lifetime.lazy(),
621 data: *data,
622 },
623 layout: self.layout,
624 finalizer: self.finalizer,
625 drop: true,
626 },
627 Kind::Referenced { lifetime, data } => Self {
628 type_hash: self.type_hash,
629 kind: Kind::Referenced {
630 lifetime: lifetime.clone(),
631 data: *data,
632 },
633 layout: self.layout,
634 finalizer: self.finalizer,
635 drop: true,
636 },
637 }
638 }
639}
640
641#[cfg(test)]
642mod tests {
643 use super::*;
644
645 #[test]
646 fn test_is_async() {
647 fn is_async<T: Send + Sync>() {}
648
649 is_async::<ManagedGc<()>>();
650 is_async::<DynamicManagedGc>();
651 }
652
653 #[test]
654 fn test_managed_gc() {
655 let mut managed = ManagedGc::new(42);
656 {
657 let read_access = managed.read::<true>();
658 assert_eq!(*read_access, 42);
659 }
660 {
661 let mut write_access = managed.write::<true>();
662 *write_access = 100;
663 }
664 {
665 let read_access = managed.read::<true>();
666 assert_eq!(*read_access, 100);
667 }
668 }
669
670 #[test]
671 fn test_managed_gc_cycles() {
672 #[derive(Default)]
673 struct Foo {
674 other: Option<ManagedGc<Self>>,
675 }
676
677 {
678 let mut a = ManagedGc::<Foo>::default();
679 let mut b = ManagedGc::<Foo>::default();
680 a.write::<true>().other = Some(b.clone());
681 b.write::<true>().other = Some(a.clone());
682
683 assert!(a.exists());
684 assert!(a.is_owning());
685 assert!(a.read::<true>().other.as_ref().unwrap().is_referencing());
686 assert!(a.read::<true>().other.as_ref().unwrap().is_owned_by(&b));
687
688 assert!(b.exists());
689 assert!(b.is_owning());
690 assert!(b.read::<true>().other.as_ref().unwrap().is_referencing());
691 assert!(b.read::<true>().other.as_ref().unwrap().is_owned_by(&a));
692
693 drop(b);
694 assert!(!a.read::<true>().other.as_ref().unwrap().exists());
695 }
696
697 {
698 let mut a = ManagedGc::<Foo>::default();
699 a.write::<true>().other = Some(a.clone());
700
701 assert!(a.exists());
702 assert!(a.is_owning());
703 assert!(a.read::<true>().other.as_ref().unwrap().is_referencing());
704 assert!(a.read::<true>().other.as_ref().unwrap().is_owned_by(&a));
705 }
706 }
707
708 #[test]
709 fn test_dynamic_managed_gc() {
710 let mut managed = DynamicManagedGc::new(42);
711 {
712 let read_access = managed.read::<true, i32>();
713 assert_eq!(*read_access, 42);
714 }
715 {
716 let mut write_access = managed.write::<true, i32>();
717 *write_access = 100;
718 }
719 {
720 let read_access = managed.read::<true, i32>();
721 assert_eq!(*read_access, 100);
722 }
723 }
724
725 #[test]
726 fn test_dynamic_managed_gc_cycles() {
727 #[derive(Default)]
728 struct Foo {
729 other: Option<DynamicManagedGc>,
730 }
731
732 {
733 let mut a = DynamicManagedGc::new(Foo::default());
734 let mut b = DynamicManagedGc::new(Foo::default());
735 a.write::<true, Foo>().other = Some(b.clone());
736 b.write::<true, Foo>().other = Some(a.clone());
737
738 assert!(a.exists());
739 assert!(a.is_owning());
740 assert!(
741 a.read::<true, Foo>()
742 .other
743 .as_ref()
744 .unwrap()
745 .is_referencing()
746 );
747 assert!(
748 a.read::<true, Foo>()
749 .other
750 .as_ref()
751 .unwrap()
752 .is_owned_by(&b)
753 );
754
755 assert!(b.exists());
756 assert!(b.is_owning());
757 assert!(
758 b.read::<true, Foo>()
759 .other
760 .as_ref()
761 .unwrap()
762 .is_referencing()
763 );
764 assert!(
765 b.read::<true, Foo>()
766 .other
767 .as_ref()
768 .unwrap()
769 .is_owned_by(&a)
770 );
771
772 drop(b);
773 assert!(!a.read::<true, Foo>().other.as_ref().unwrap().exists());
774 }
775
776 {
777 let mut a = DynamicManagedGc::new(Foo::default());
778 a.write::<true, Foo>().other = Some(a.clone());
779
780 assert!(a.exists());
781 assert!(a.is_owning());
782 assert!(
783 a.read::<true, Foo>()
784 .other
785 .as_ref()
786 .unwrap()
787 .is_referencing()
788 );
789 assert!(
790 a.read::<true, Foo>()
791 .other
792 .as_ref()
793 .unwrap()
794 .is_owned_by(&a)
795 );
796 }
797 }
798
799 #[test]
800 fn test_gc_conversions() {
801 let managed = ManagedGc::new(42);
802 assert_eq!(*managed.read::<true>(), 42);
803
804 let mut dynamic = managed.into_dynamic();
805 *dynamic.write::<true, i32>() = 100;
806
807 let managed = dynamic.into_typed::<i32>();
808 assert_eq!(*managed.read::<true>(), 100);
809 }
810
811 #[test]
812 fn test_gc_dead_owner() {
813 let a = ManagedGc::new(42);
814 let mut b = a.clone();
815
816 assert!(a.exists());
817 assert!(b.exists());
818 assert_eq!(*b.read::<true>(), 42);
819
820 drop(a);
821 assert!(!b.exists());
822 assert!(b.try_write().is_none());
823 }
824
825 #[test]
826 #[should_panic]
827 fn test_gc_dead_owner_panic() {
828 let a = ManagedGc::new(42);
829 let mut b = a.clone();
830
831 assert!(a.exists());
832 assert!(b.exists());
833 assert_eq!(*b.read::<true>(), 42);
834
835 drop(a);
836 assert!(!b.exists());
837 assert_eq!(*b.write::<true>(), 42);
838 }
839}