1use crate::{
35 Finalize, Finalizer,
36 lifetime::{Lifetime, LifetimeLazy, ValueReadAccess, ValueWriteAccess},
37 managed::{
38 DynamicManagedLazy, DynamicManagedRef, DynamicManagedRefMut, ManagedLazy, ManagedRef,
39 ManagedRefMut,
40 value::{DynamicManagedValue, ManagedValue},
41 },
42 non_zero_alloc, non_zero_dealloc,
43 type_hash::TypeHash,
44};
45use std::{
46 alloc::{Layout, handle_alloc_error},
47 marker::PhantomData,
48 mem::MaybeUninit,
49};
50
51enum Kind {
53 Owned {
54 lifetime: Box<Lifetime>,
55 data: *mut u8,
56 },
57 Referenced {
58 lifetime: LifetimeLazy,
59 data: *mut u8,
60 },
61}
62
63pub enum ManagedGcLifetime<'a> {
67 Owned(&'a Lifetime),
69 Referenced(&'a LifetimeLazy),
71}
72
73pub struct ManagedGc<T> {
77 dynamic: DynamicManagedGc,
78 _phantom: PhantomData<fn() -> T>,
79}
80
81unsafe impl<T> Send for ManagedGc<T> {}
82unsafe impl<T> Sync for ManagedGc<T> {}
83
84impl<T: Default> Default for ManagedGc<T> {
85 fn default() -> Self {
86 Self::new(T::default())
87 }
88}
89
90impl<T> ManagedGc<T> {
91 pub fn new(data: T) -> Self {
93 Self {
94 dynamic: DynamicManagedGc::new(data),
95 _phantom: PhantomData,
96 }
97 }
98
99 pub unsafe fn new_cyclic(f: impl FnOnce(Self) -> T) -> Self {
110 Self {
111 dynamic: unsafe { DynamicManagedGc::new_cyclic(|dynamic| f(dynamic.into_typed())) },
112 _phantom: PhantomData,
113 }
114 }
115
116 pub fn reference(&self) -> Self {
118 Self {
119 dynamic: self.dynamic.reference(),
120 _phantom: PhantomData,
121 }
122 }
123
124 pub fn consume(self) -> Result<T, Self> {
129 self.dynamic.consume().map_err(|value| Self {
130 dynamic: value,
131 _phantom: PhantomData,
132 })
133 }
134
135 pub fn into_dynamic(self) -> DynamicManagedGc {
137 self.dynamic
138 }
139
140 pub fn renew(&mut self) {
143 self.dynamic.renew();
144 }
145
146 pub fn type_hash(&self) -> TypeHash {
148 self.dynamic.type_hash()
149 }
150
151 pub fn lifetime(&self) -> ManagedGcLifetime<'_> {
154 self.dynamic.lifetime()
155 }
156
157 pub fn exists(&self) -> bool {
161 self.dynamic.exists()
162 }
163
164 pub fn is_owning(&self) -> bool {
166 self.dynamic.is_owning()
167 }
168
169 pub fn is_referencing(&self) -> bool {
171 self.dynamic.is_referencing()
172 }
173
174 pub fn is_owned_by(&self, other: &Self) -> bool {
176 self.dynamic.is_owned_by(&other.dynamic)
177 }
178
179 pub fn transfer_ownership(&mut self, new_owner: &mut Self) -> bool {
184 self.dynamic.transfer_ownership(&mut new_owner.dynamic)
185 }
186
187 pub fn try_read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
190 self.dynamic.try_read::<T>()
191 }
192
193 pub fn try_write(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
196 self.dynamic.try_write::<T>()
197 }
198
199 pub fn read<const LOCKING: bool>(&'_ self) -> ValueReadAccess<'_, T> {
206 self.dynamic.read::<LOCKING, T>()
207 }
208
209 pub fn write<const LOCKING: bool>(&'_ mut self) -> ValueWriteAccess<'_, T> {
216 self.dynamic.write::<LOCKING, T>()
217 }
218
219 pub fn try_borrow(&self) -> Option<ManagedRef<T>> {
222 self.dynamic.try_borrow()?.into_typed().ok()
223 }
224
225 pub fn try_borrow_mut(&self) -> Option<ManagedRefMut<T>> {
228 self.dynamic.try_borrow_mut()?.into_typed().ok()
229 }
230
231 pub fn borrow<const LOCKING: bool>(&self) -> ManagedRef<T> {
238 self.dynamic
239 .borrow::<LOCKING>()
240 .into_typed()
241 .ok()
242 .expect("ManagedGc cannot be immutably borrowed")
243 }
244
245 pub fn borrow_mut<const LOCKING: bool>(&mut self) -> ManagedRefMut<T> {
252 self.dynamic
253 .borrow_mut::<LOCKING>()
254 .into_typed()
255 .ok()
256 .expect("ManagedGc cannot be mutably borrowed")
257 }
258
259 pub fn lazy(&self) -> ManagedLazy<T> {
265 self.dynamic
266 .lazy()
267 .into_typed()
268 .ok()
269 .expect("ManagedGc cannot be lazily borrowed")
270 }
271
272 pub unsafe fn as_ptr(&self) -> *const T {
279 unsafe { self.dynamic.as_ptr_raw().cast::<T>() }
280 }
281
282 pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
289 unsafe { self.dynamic.as_mut_ptr_raw().cast::<T>() }
290 }
291}
292
293impl<T> TryFrom<ManagedValue<T>> for ManagedGc<T> {
294 type Error = ();
295
296 fn try_from(value: ManagedValue<T>) -> Result<Self, Self::Error> {
297 match value {
298 ManagedValue::Gc(value) => Ok(value),
299 _ => Err(()),
300 }
301 }
302}
303
304pub struct DynamicManagedGc {
309 type_hash: TypeHash,
310 kind: Kind,
311 layout: Layout,
312 finalizer: Finalizer,
313 drop: bool,
314}
315
316unsafe impl Send for DynamicManagedGc {}
317unsafe impl Sync for DynamicManagedGc {}
318
319impl Drop for DynamicManagedGc {
320 fn drop(&mut self) {
321 if let Kind::Owned { lifetime, data } = &mut self.kind
322 && self.drop
323 {
324 while lifetime.state().is_in_use() {
325 std::hint::spin_loop();
326 }
327 lifetime.invalidate();
328 unsafe {
329 if data.is_null() {
330 return;
331 }
332 self.finalizer.finalize(data.cast::<()>());
333 non_zero_dealloc(*data, self.layout);
334 }
335 }
336 }
337}
338
339impl DynamicManagedGc {
340 pub fn new<T: Finalize>(data: T) -> Self {
342 let layout = Layout::new::<T>().pad_to_align();
343 unsafe {
344 let memory = non_zero_alloc(layout) as *mut T;
345 if memory.is_null() {
346 handle_alloc_error(layout);
347 }
348 memory.cast::<T>().write(data);
349 Self {
350 type_hash: TypeHash::of::<T>(),
351 kind: Kind::Owned {
352 lifetime: Default::default(),
353 data: memory.cast::<u8>(),
354 },
355 layout,
356 finalizer: Finalizer::of::<T>(),
357 drop: true,
358 }
359 }
360 }
361
362 pub unsafe fn new_cyclic<T: Finalize>(f: impl FnOnce(Self) -> T) -> Self {
373 let layout = Layout::new::<T>().pad_to_align();
374 unsafe {
375 let memory = non_zero_alloc(layout) as *mut T;
376 if memory.is_null() {
377 handle_alloc_error(layout);
378 }
379 let result = Self {
380 type_hash: TypeHash::of::<T>(),
381 kind: Kind::Owned {
382 lifetime: Default::default(),
383 data: memory.cast::<u8>(),
384 },
385 layout,
386 finalizer: Finalizer::of::<T>(),
387 drop: true,
388 };
389 let data = f(result.reference());
390 memory.cast::<T>().write(data);
391 result
392 }
393 }
394
395 pub fn new_raw(
403 type_hash: TypeHash,
404 lifetime: Lifetime,
405 memory: *mut u8,
406 layout: Layout,
407 finalizer: impl Into<Finalizer>,
408 ) -> Self {
409 if memory.is_null() {
410 handle_alloc_error(layout);
411 }
412 Self {
413 type_hash,
414 kind: Kind::Owned {
415 lifetime: Box::new(lifetime),
416 data: memory,
417 },
418 layout,
419 finalizer: finalizer.into(),
420 drop: true,
421 }
422 }
423
424 pub fn new_uninitialized(
429 type_hash: TypeHash,
430 layout: Layout,
431 finalizer: impl Into<Finalizer>,
432 ) -> Self {
433 let memory = unsafe { non_zero_alloc(layout) };
434 if memory.is_null() {
435 handle_alloc_error(layout);
436 }
437 Self {
438 type_hash,
439 kind: Kind::Owned {
440 lifetime: Default::default(),
441 data: memory,
442 },
443 layout,
444 finalizer: finalizer.into(),
445 drop: true,
446 }
447 }
448
449 pub fn reference(&self) -> Self {
451 match &self.kind {
452 Kind::Owned { lifetime, data } => Self {
453 type_hash: self.type_hash,
454 kind: Kind::Referenced {
455 lifetime: lifetime.lazy(),
456 data: *data,
457 },
458 layout: self.layout,
459 finalizer: self.finalizer.clone(),
460 drop: true,
461 },
462 Kind::Referenced { lifetime, data } => Self {
463 type_hash: self.type_hash,
464 kind: Kind::Referenced {
465 lifetime: lifetime.clone(),
466 data: *data,
467 },
468 layout: self.layout,
469 finalizer: self.finalizer.clone(),
470 drop: true,
471 },
472 }
473 }
474
475 pub fn consume<T>(mut self) -> Result<T, Self> {
480 if let Kind::Owned { lifetime, data } = &mut self.kind {
481 if self.type_hash == TypeHash::of::<T>() && !lifetime.state().is_in_use() {
482 if data.is_null() {
483 return Err(self);
484 }
485 self.drop = false;
486 let mut result = MaybeUninit::<T>::uninit();
487 unsafe {
488 result.as_mut_ptr().copy_from(data.cast::<T>(), 1);
489 non_zero_dealloc(*data, self.layout);
490 Ok(result.assume_init())
491 }
492 } else {
493 Err(self)
494 }
495 } else {
496 Err(self)
497 }
498 }
499
500 pub fn into_typed<T>(self) -> ManagedGc<T> {
502 ManagedGc {
503 dynamic: self,
504 _phantom: PhantomData,
505 }
506 }
507
508 pub fn renew(&mut self) {
511 if let Kind::Owned { lifetime, .. } = &mut self.kind {
512 **lifetime = Default::default();
513 }
514 }
515
516 pub fn type_hash(&self) -> TypeHash {
518 self.type_hash
519 }
520
521 pub fn lifetime(&self) -> ManagedGcLifetime<'_> {
524 match &self.kind {
525 Kind::Owned { lifetime, .. } => ManagedGcLifetime::Owned(lifetime),
526 Kind::Referenced { lifetime, .. } => ManagedGcLifetime::Referenced(lifetime),
527 }
528 }
529
530 pub fn layout(&self) -> &Layout {
532 &self.layout
533 }
534
535 pub fn finalizer(&self) -> &Finalizer {
537 &self.finalizer
538 }
539
540 pub unsafe fn memory(&self) -> &[u8] {
547 let memory = match &self.kind {
548 Kind::Owned { data, .. } => *data,
549 Kind::Referenced { data, .. } => *data,
550 };
551 unsafe { std::slice::from_raw_parts(memory, self.layout.size()) }
552 }
553
554 pub unsafe fn memory_mut(&mut self) -> &mut [u8] {
562 let memory = match &mut self.kind {
563 Kind::Owned { data, .. } => *data,
564 Kind::Referenced { data, .. } => *data,
565 };
566 unsafe { std::slice::from_raw_parts_mut(memory, self.layout.size()) }
567 }
568
569 pub fn exists(&self) -> bool {
573 match &self.kind {
574 Kind::Owned { .. } => true,
575 Kind::Referenced { lifetime, .. } => lifetime.exists(),
576 }
577 }
578
579 pub fn is_owning(&self) -> bool {
581 matches!(self.kind, Kind::Owned { .. })
582 }
583
584 pub fn is_referencing(&self) -> bool {
586 matches!(self.kind, Kind::Referenced { .. })
587 }
588
589 pub fn is_owned_by(&self, other: &Self) -> bool {
591 if let (
592 Kind::Referenced {
593 lifetime: l1,
594 data: d1,
595 },
596 Kind::Owned {
597 lifetime: l2,
598 data: d2,
599 },
600 ) = (&self.kind, &other.kind)
601 {
602 *d1 == *d2 && l1.state().is_owned_by(l2.state())
603 } else {
604 false
605 }
606 }
607
608 pub fn transfer_ownership(&mut self, new_owner: &mut Self) -> bool {
613 if let (
614 Kind::Owned {
615 lifetime: l1,
616 data: d1,
617 },
618 Kind::Referenced {
619 lifetime: l2,
620 data: d2,
621 },
622 ) = (&mut self.kind, &new_owner.kind)
623 && *d1 == *d2
624 && l2.state().is_owned_by(l1.state())
625 {
626 std::mem::swap(&mut self.kind, &mut new_owner.kind);
627 true
628 } else {
629 false
630 }
631 }
632
633 pub fn is<T>(&self) -> bool {
635 self.type_hash == TypeHash::of::<T>()
636 }
637
638 pub fn try_read<T>(&'_ self) -> Option<ValueReadAccess<'_, T>> {
645 if !self.is::<T>() {
646 panic!(
647 "DynamicManagedGc is not of the requested type: {}",
648 std::any::type_name::<T>()
649 );
650 }
651 unsafe {
652 match &self.kind {
653 Kind::Owned { lifetime, data } => {
654 let data = data.cast::<T>().as_ref()?;
655 lifetime.read(data)
656 }
657 Kind::Referenced { lifetime, data } => {
658 if lifetime.exists() {
659 let data = data.cast::<T>().as_ref()?;
660 lifetime.read(data)
661 } else {
662 None
663 }
664 }
665 }
666 }
667 }
668
669 pub fn try_write<T>(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
676 if !self.is::<T>() {
677 panic!(
678 "DynamicManagedGc is not of the requested type: {}",
679 std::any::type_name::<T>()
680 );
681 }
682 unsafe {
683 match &self.kind {
684 Kind::Owned { lifetime, data } => {
685 let data = data.cast::<T>().as_mut()?;
686 lifetime.write(data)
687 }
688 Kind::Referenced { lifetime, data } => {
689 if lifetime.exists() {
690 let data = data.cast::<T>().as_mut()?;
691 lifetime.write(data)
692 } else {
693 None
694 }
695 }
696 }
697 }
698 }
699
700 pub fn read<const LOCKING: bool, T>(&'_ self) -> ValueReadAccess<'_, T> {
707 if !self.is::<T>() {
708 panic!(
709 "DynamicManagedGc is not of the requested type: {}",
710 std::any::type_name::<T>()
711 );
712 }
713 unsafe {
714 if LOCKING {
715 match &self.kind {
716 Kind::Owned { lifetime, data } => loop {
717 let data = data
718 .cast::<T>()
719 .as_ref()
720 .expect("DynamicManagedGc data pointer is null");
721 if let Some(access) = lifetime.read(data) {
722 return access;
723 }
724 std::hint::spin_loop();
725 },
726 Kind::Referenced { lifetime, data } => loop {
727 if !lifetime.exists() {
728 panic!("DynamicManagedGc owner is dead");
729 }
730 let data = data
731 .cast::<T>()
732 .as_ref()
733 .expect("DynamicManagedGc data pointer is null");
734 if let Some(access) = lifetime.read(data) {
735 return access;
736 }
737 std::hint::spin_loop();
738 },
739 }
740 } else {
741 match &self.kind {
742 Kind::Owned { lifetime, data } => {
743 let data = data
744 .cast::<T>()
745 .as_ref()
746 .expect("DynamicManagedGc data pointer is null");
747 lifetime
748 .read(data)
749 .expect("DynamicManagedGc is inaccessible for reading")
750 }
751 Kind::Referenced { lifetime, data } => {
752 let data = data
753 .cast::<T>()
754 .as_ref()
755 .expect("DynamicManagedGc data pointer is null");
756 lifetime
757 .read(data)
758 .expect("DynamicManagedGc is inaccessible for reading")
759 }
760 }
761 }
762 }
763 }
764
765 pub fn write<const LOCKING: bool, T>(&'_ mut self) -> ValueWriteAccess<'_, T> {
772 if !self.is::<T>() {
773 panic!(
774 "DynamicManagedGc is not of the requested type: {}",
775 std::any::type_name::<T>()
776 );
777 }
778 unsafe {
779 if LOCKING {
780 match &self.kind {
781 Kind::Owned { lifetime, data } => loop {
782 let data = data
783 .cast::<T>()
784 .as_mut()
785 .expect("DynamicManagedGc data pointer is null");
786 if let Some(access) = lifetime.write(data) {
787 return access;
788 }
789 std::hint::spin_loop();
790 },
791 Kind::Referenced { lifetime, data } => loop {
792 if !lifetime.exists() {
793 panic!("DynamicManagedGc owner is dead");
794 }
795 let data = data
796 .cast::<T>()
797 .as_mut()
798 .expect("DynamicManagedGc data pointer is null");
799 if let Some(access) = lifetime.write(data) {
800 return access;
801 }
802 std::hint::spin_loop();
803 },
804 }
805 } else {
806 match &self.kind {
807 Kind::Owned { lifetime, data } => {
808 let data = data
809 .cast::<T>()
810 .as_mut()
811 .expect("DynamicManagedGc data pointer is null");
812 lifetime
813 .write(data)
814 .expect("DynamicManagedGc is inaccessible for writing")
815 }
816 Kind::Referenced { lifetime, data } => {
817 let data = data
818 .cast::<T>()
819 .as_mut()
820 .expect("DynamicManagedGc data pointer is null");
821 lifetime
822 .write(data)
823 .expect("DynamicManagedGc is inaccessible for writing")
824 }
825 }
826 }
827 }
828 }
829
830 pub fn try_borrow(&self) -> Option<DynamicManagedRef> {
833 unsafe {
834 match &self.kind {
835 Kind::Owned { lifetime, data } => {
836 DynamicManagedRef::new_raw(self.type_hash, lifetime.borrow()?, *data)
837 }
838 Kind::Referenced { lifetime, data } => {
839 DynamicManagedRef::new_raw(self.type_hash, lifetime.borrow()?, *data)
840 }
841 }
842 }
843 }
844
845 pub fn try_borrow_mut(&self) -> Option<DynamicManagedRefMut> {
848 unsafe {
849 match &self.kind {
850 Kind::Owned { lifetime, data } => {
851 DynamicManagedRefMut::new_raw(self.type_hash, lifetime.borrow_mut()?, *data)
852 }
853 Kind::Referenced { lifetime, data } => {
854 DynamicManagedRefMut::new_raw(self.type_hash, lifetime.borrow_mut()?, *data)
855 }
856 }
857 }
858 }
859
860 pub fn borrow<const LOCKING: bool>(&self) -> DynamicManagedRef {
867 unsafe {
868 if LOCKING {
869 match &self.kind {
870 Kind::Owned { lifetime, data } => loop {
871 if let Some(lifetime) = lifetime.borrow() {
872 return DynamicManagedRef::new_raw(self.type_hash, lifetime, *data)
873 .expect("DynamicManagedGc cannot be immutably borrowed");
874 }
875 std::hint::spin_loop();
876 },
877 Kind::Referenced { lifetime, data } => loop {
878 if !lifetime.exists() {
879 panic!("DynamicManagedGc owner is dead");
880 }
881 if let Some(lifetime) = lifetime.borrow() {
882 return DynamicManagedRef::new_raw(self.type_hash, lifetime, *data)
883 .expect("DynamicManagedGc cannot be immutably borrowed");
884 }
885 std::hint::spin_loop();
886 },
887 }
888 } else {
889 match &self.kind {
890 Kind::Owned { lifetime, data } => DynamicManagedRef::new_raw(
891 self.type_hash,
892 lifetime
893 .borrow()
894 .expect("DynamicManagedGc is inaccessible for immutable borrowing"),
895 *data,
896 )
897 .expect("DynamicManagedGc cannot be immutably borrowed"),
898 Kind::Referenced { lifetime, data } => DynamicManagedRef::new_raw(
899 self.type_hash,
900 lifetime
901 .borrow()
902 .expect("DynamicManagedGc is inaccessible for immutable borrowing"),
903 *data,
904 )
905 .expect("DynamicManagedGc cannot be immutably borrowed"),
906 }
907 }
908 }
909 }
910
911 pub fn borrow_mut<const LOCKING: bool>(&mut self) -> DynamicManagedRefMut {
918 unsafe {
919 if LOCKING {
920 match &self.kind {
921 Kind::Owned { lifetime, data } => loop {
922 if let Some(lifetime) = lifetime.borrow_mut() {
923 return DynamicManagedRefMut::new_raw(self.type_hash, lifetime, *data)
924 .expect("DynamicManagedGc cannot be mutably borrowed");
925 }
926 std::hint::spin_loop();
927 },
928 Kind::Referenced { lifetime, data } => loop {
929 if !lifetime.exists() {
930 panic!("DynamicManagedGc owner is dead");
931 }
932 if let Some(lifetime) = lifetime.borrow_mut() {
933 return DynamicManagedRefMut::new_raw(self.type_hash, lifetime, *data)
934 .expect("DynamicManagedGc cannot be mutably borrowed");
935 }
936 std::hint::spin_loop();
937 },
938 }
939 } else {
940 match &self.kind {
941 Kind::Owned { lifetime, data } => DynamicManagedRefMut::new_raw(
942 self.type_hash,
943 lifetime
944 .borrow_mut()
945 .expect("DynamicManagedGc is inaccessible for mutable borrowing"),
946 *data,
947 )
948 .expect("DynamicManagedGc cannot be mutably borrowed"),
949 Kind::Referenced { lifetime, data } => DynamicManagedRefMut::new_raw(
950 self.type_hash,
951 lifetime
952 .borrow_mut()
953 .expect("DynamicManagedGc is inaccessible for mutable borrowing"),
954 *data,
955 )
956 .expect("DynamicManagedGc cannot be mutably borrowed"),
957 }
958 }
959 }
960 }
961
962 pub fn lazy(&self) -> DynamicManagedLazy {
968 unsafe {
969 match &self.kind {
970 Kind::Owned { lifetime, data } => {
971 DynamicManagedLazy::new_raw(self.type_hash, lifetime.lazy(), *data)
972 .expect("DynamicManagedGc cannot be lazily borrowed")
973 }
974 Kind::Referenced { lifetime, data } => {
975 DynamicManagedLazy::new_raw(self.type_hash, lifetime.clone(), *data)
976 .expect("DynamicManagedGc cannot be lazily borrowed")
977 }
978 }
979 }
980 }
981
982 pub unsafe fn as_ptr_raw(&self) -> *const u8 {
989 match &self.kind {
990 Kind::Owned { data, .. } => *data as *const u8,
991 Kind::Referenced { data, .. } => *data as *const u8,
992 }
993 }
994
995 pub unsafe fn as_mut_ptr_raw(&mut self) -> *mut u8 {
1002 match &self.kind {
1003 Kind::Owned { data, .. } => *data,
1004 Kind::Referenced { data, .. } => *data,
1005 }
1006 }
1007}
1008
1009impl TryFrom<DynamicManagedValue> for DynamicManagedGc {
1010 type Error = ();
1011
1012 fn try_from(value: DynamicManagedValue) -> Result<Self, Self::Error> {
1013 match value {
1014 DynamicManagedValue::Gc(value) => Ok(value),
1015 _ => Err(()),
1016 }
1017 }
1018}
1019
1020#[cfg(test)]
1021mod tests {
1022 use super::*;
1023
1024 #[test]
1025 fn test_is_async() {
1026 fn is_async<T: Send + Sync>() {}
1027
1028 is_async::<ManagedGc<()>>();
1029 is_async::<DynamicManagedGc>();
1030 }
1031
1032 #[test]
1033 fn test_managed_gc() {
1034 let mut managed = ManagedGc::new(42);
1035 {
1036 let read_access = managed.read::<true>();
1037 assert_eq!(*read_access, 42);
1038 }
1039 {
1040 let mut write_access = managed.write::<true>();
1041 *write_access = 100;
1042 }
1043 {
1044 let read_access = managed.read::<true>();
1045 assert_eq!(*read_access, 100);
1046 }
1047 }
1048
1049 #[test]
1050 #[allow(unused)]
1051 fn test_managed_gc_lifetimes() {
1052 struct Car {
1053 gear: i32,
1054 engine: Option<ManagedGc<Engine>>,
1055 }
1056
1057 struct Engine {
1058 owning_car: Option<ManagedGc<Car>>,
1059 horsepower: i32,
1060 }
1061
1062 let mut car = ManagedGc::new(Car {
1063 gear: 1,
1064 engine: None,
1065 });
1066 let engine = ManagedGc::new(Engine {
1067 owning_car: Some(car.reference()),
1068 horsepower: 200,
1069 });
1070 let engine2 = engine.reference();
1071 car.write::<true>().engine = Some(engine);
1072
1073 assert!(car.exists());
1074 assert!(car.is_owning());
1075 assert!(engine2.exists());
1076 assert!(engine2.is_referencing());
1077 assert!(engine2.is_owned_by(car.read::<true>().engine.as_ref().unwrap()));
1078
1079 let car2 = car.reference();
1080 assert!(car2.exists());
1081 assert!(car2.is_referencing());
1082
1083 drop(car);
1084 assert!(!car2.exists());
1085 assert!(car2.try_read().is_none());
1086 assert!(!engine2.exists());
1087 assert!(engine2.try_read().is_none());
1088 }
1089
1090 #[test]
1091 fn test_managed_gc_cycles() {
1092 #[derive(Default)]
1093 struct Foo {
1094 other: Option<ManagedGc<Self>>,
1095 }
1096
1097 {
1098 let mut a = ManagedGc::<Foo>::default();
1099 let mut b = ManagedGc::<Foo>::default();
1100 a.write::<true>().other = Some(b.reference());
1101 b.write::<true>().other = Some(a.reference());
1102
1103 assert!(a.exists());
1104 assert!(a.is_owning());
1105 assert!(a.read::<true>().other.as_ref().unwrap().is_referencing());
1106 assert!(a.read::<true>().other.as_ref().unwrap().is_owned_by(&b));
1107
1108 assert!(b.exists());
1109 assert!(b.is_owning());
1110 assert!(b.read::<true>().other.as_ref().unwrap().is_referencing());
1111 assert!(b.read::<true>().other.as_ref().unwrap().is_owned_by(&a));
1112
1113 drop(b);
1114 assert!(!a.read::<true>().other.as_ref().unwrap().exists());
1115 }
1116
1117 {
1118 let mut a = ManagedGc::<Foo>::default();
1119 a.write::<true>().other = Some(a.reference());
1120
1121 assert!(a.exists());
1122 assert!(a.is_owning());
1123 assert!(a.read::<true>().other.as_ref().unwrap().is_referencing());
1124 assert!(a.read::<true>().other.as_ref().unwrap().is_owned_by(&a));
1125 }
1126 }
1127
1128 #[test]
1129 fn test_dynamic_managed_gc() {
1130 let mut managed = DynamicManagedGc::new(42);
1131 {
1132 let read_access = managed.read::<true, i32>();
1133 assert_eq!(*read_access, 42);
1134 }
1135 {
1136 let mut write_access = managed.write::<true, i32>();
1137 *write_access = 100;
1138 }
1139 {
1140 let read_access = managed.read::<true, i32>();
1141 assert_eq!(*read_access, 100);
1142 }
1143 }
1144
1145 #[test]
1146 fn test_dynamic_managed_gc_cycles() {
1147 #[derive(Default)]
1148 struct Foo {
1149 other: Option<DynamicManagedGc>,
1150 }
1151
1152 {
1153 let mut a = DynamicManagedGc::new(Foo::default());
1154 let mut b = DynamicManagedGc::new(Foo::default());
1155 a.write::<true, Foo>().other = Some(b.reference());
1156 b.write::<true, Foo>().other = Some(a.reference());
1157
1158 assert!(a.exists());
1159 assert!(a.is_owning());
1160 assert!(
1161 a.read::<true, Foo>()
1162 .other
1163 .as_ref()
1164 .unwrap()
1165 .is_referencing()
1166 );
1167 assert!(
1168 a.read::<true, Foo>()
1169 .other
1170 .as_ref()
1171 .unwrap()
1172 .is_owned_by(&b)
1173 );
1174
1175 assert!(b.exists());
1176 assert!(b.is_owning());
1177 assert!(
1178 b.read::<true, Foo>()
1179 .other
1180 .as_ref()
1181 .unwrap()
1182 .is_referencing()
1183 );
1184 assert!(
1185 b.read::<true, Foo>()
1186 .other
1187 .as_ref()
1188 .unwrap()
1189 .is_owned_by(&a)
1190 );
1191
1192 drop(b);
1193 assert!(!a.read::<true, Foo>().other.as_ref().unwrap().exists());
1194 }
1195
1196 {
1197 let mut a = DynamicManagedGc::new(Foo::default());
1198 a.write::<true, Foo>().other = Some(a.reference());
1199
1200 assert!(a.exists());
1201 assert!(a.is_owning());
1202 assert!(
1203 a.read::<true, Foo>()
1204 .other
1205 .as_ref()
1206 .unwrap()
1207 .is_referencing()
1208 );
1209 assert!(
1210 a.read::<true, Foo>()
1211 .other
1212 .as_ref()
1213 .unwrap()
1214 .is_owned_by(&a)
1215 );
1216 }
1217 }
1218
1219 #[test]
1220 fn test_managed_gc_conversions() {
1221 let managed = ManagedGc::new(42);
1222 assert_eq!(*managed.read::<true>(), 42);
1223
1224 let mut dynamic = managed.into_dynamic();
1225 *dynamic.write::<true, i32>() = 100;
1226
1227 let managed = dynamic.into_typed::<i32>();
1228 assert_eq!(*managed.read::<true>(), 100);
1229 }
1230
1231 #[test]
1232 fn test_managed_gc_dead_owner() {
1233 let a = ManagedGc::new(42);
1234 let mut b = a.reference();
1235
1236 assert!(a.exists());
1237 assert!(b.exists());
1238 assert_eq!(*b.read::<true>(), 42);
1239
1240 drop(a);
1241 assert!(!b.exists());
1242 assert!(b.try_write().is_none());
1243 }
1244
1245 #[test]
1246 #[should_panic]
1247 fn test_managed_gc_dead_owner_panic() {
1248 let a = ManagedGc::new(42);
1249 let mut b = a.reference();
1250
1251 assert!(a.exists());
1252 assert!(b.exists());
1253 assert_eq!(*b.read::<true>(), 42);
1254
1255 drop(a);
1256 assert!(!b.exists());
1257 assert_eq!(*b.write::<true>(), 42);
1258 }
1259
1260 #[test]
1261 fn test_managed_gc_cyclic() {
1262 struct SelfReferencial {
1263 value: i32,
1264 this: ManagedGc<SelfReferencial>,
1265 }
1266
1267 let v = unsafe { ManagedGc::new_cyclic(|this| SelfReferencial { value: 42, this }) };
1268 assert_eq!(v.read::<true>().value, 42);
1269 let this = v.read::<true>().this.reference();
1270 assert_eq!(this.read::<true>().value, 42);
1271 }
1272
1273 #[test]
1274 fn test_managed_gc_transfer_ownership() {
1275 let mut a = ManagedGc::new(42);
1276 let mut b = a.reference();
1277
1278 assert!(!a.is_owned_by(&b));
1279 assert!(b.is_owned_by(&a));
1280 assert!(!b.transfer_ownership(&mut a));
1281 assert!(a.transfer_ownership(&mut b));
1282 assert!(a.is_owned_by(&b));
1283 assert!(!b.is_owned_by(&a));
1284 drop(b);
1285 assert!(!a.exists());
1286 }
1287}