1use crate::{
41 Finalize, Finalizer,
42 lifetime::{Lifetime, LifetimeLazy, ValueReadAccess, ValueWriteAccess},
43 managed::{
44 DynamicManagedLazy, DynamicManagedRef, DynamicManagedRefMut, ManagedLazy, ManagedRef,
45 ManagedRefMut,
46 value::{DynamicManagedValue, ManagedValue},
47 },
48 non_zero_alloc, non_zero_dealloc,
49 type_hash::TypeHash,
50};
51use std::{
52 alloc::{Layout, handle_alloc_error},
53 marker::PhantomData,
54 mem::MaybeUninit,
55};
56
57enum Kind {
59 Owned {
60 lifetime: Box<Lifetime>,
61 data: *mut u8,
62 },
63 Referenced {
64 lifetime: LifetimeLazy,
65 data: *mut u8,
66 },
67}
68
69pub enum ManagedGcLifetime<'a> {
73 Owned(&'a Lifetime),
75 Referenced(&'a LifetimeLazy),
77}
78
79pub struct ManagedGc<T> {
83 dynamic: DynamicManagedGc,
84 _phantom: PhantomData<fn() -> T>,
85}
86
87unsafe impl<T> Send for ManagedGc<T> {}
88unsafe impl<T> Sync for ManagedGc<T> {}
89
90impl<T: Default> Default for ManagedGc<T> {
91 fn default() -> Self {
92 Self::new(T::default())
93 }
94}
95
96impl<T> ManagedGc<T> {
97 pub fn new(data: T) -> Self {
99 Self {
100 dynamic: DynamicManagedGc::new(data),
101 _phantom: PhantomData,
102 }
103 }
104
105 pub unsafe fn borrowed(value: &mut T) -> Self {
116 Self {
117 dynamic: unsafe { DynamicManagedGc::borrowed(value) },
118 _phantom: PhantomData,
119 }
120 }
121
122 pub unsafe fn new_cyclic(f: impl FnOnce(Self) -> T) -> Self {
133 Self {
134 dynamic: unsafe { DynamicManagedGc::new_cyclic(|dynamic| f(dynamic.into_typed())) },
135 _phantom: PhantomData,
136 }
137 }
138
139 pub fn reference(&self) -> Self {
141 Self {
142 dynamic: self.dynamic.reference(),
143 _phantom: PhantomData,
144 }
145 }
146
147 pub fn consume(self) -> Result<T, Self> {
152 self.dynamic.consume().map_err(|value| Self {
153 dynamic: value,
154 _phantom: PhantomData,
155 })
156 }
157
158 pub fn into_dynamic(self) -> DynamicManagedGc {
160 self.dynamic
161 }
162
163 pub fn renew(&mut self) {
166 self.dynamic.renew();
167 }
168
169 pub fn type_hash(&self) -> TypeHash {
171 self.dynamic.type_hash()
172 }
173
174 pub fn lifetime(&self) -> ManagedGcLifetime<'_> {
177 self.dynamic.lifetime()
178 }
179
180 pub fn exists(&self) -> bool {
184 self.dynamic.exists()
185 }
186
187 pub fn is_owning(&self) -> bool {
189 self.dynamic.is_owning()
190 }
191
192 pub fn is_borrowed(&self) -> bool {
196 self.dynamic.is_borrowed()
197 }
198
199 pub fn is_referencing(&self) -> bool {
201 self.dynamic.is_referencing()
202 }
203
204 pub fn is_owned_by(&self, other: &Self) -> bool {
206 self.dynamic.is_owned_by(&other.dynamic)
207 }
208
209 pub fn transfer_ownership(&mut self, new_owner: &mut Self) -> bool {
214 self.dynamic.transfer_ownership(&mut new_owner.dynamic)
215 }
216
217 pub fn try_read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
220 self.dynamic.try_read::<T>()
221 }
222
223 pub fn try_write(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
226 self.dynamic.try_write::<T>()
227 }
228
229 pub fn read<const LOCKING: bool>(&'_ self) -> ValueReadAccess<'_, T> {
236 self.dynamic.read::<LOCKING, T>()
237 }
238
239 pub fn write<const LOCKING: bool>(&'_ mut self) -> ValueWriteAccess<'_, T> {
246 self.dynamic.write::<LOCKING, T>()
247 }
248
249 pub fn try_borrow(&self) -> Option<ManagedRef<T>> {
252 self.dynamic.try_borrow()?.into_typed().ok()
253 }
254
255 pub fn try_borrow_mut(&self) -> Option<ManagedRefMut<T>> {
258 self.dynamic.try_borrow_mut()?.into_typed().ok()
259 }
260
261 pub fn borrow<const LOCKING: bool>(&self) -> ManagedRef<T> {
268 self.dynamic
269 .borrow::<LOCKING>()
270 .into_typed()
271 .ok()
272 .expect("ManagedGc cannot be immutably borrowed")
273 }
274
275 pub fn borrow_mut<const LOCKING: bool>(&mut self) -> ManagedRefMut<T> {
282 self.dynamic
283 .borrow_mut::<LOCKING>()
284 .into_typed()
285 .ok()
286 .expect("ManagedGc cannot be mutably borrowed")
287 }
288
289 pub fn lazy(&self) -> ManagedLazy<T> {
295 self.dynamic
296 .lazy()
297 .into_typed()
298 .ok()
299 .expect("ManagedGc cannot be lazily borrowed")
300 }
301
302 pub unsafe fn as_ptr(&self) -> *const T {
309 unsafe { self.dynamic.as_ptr_raw().cast::<T>() }
310 }
311
312 pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
319 unsafe { self.dynamic.as_mut_ptr_raw().cast::<T>() }
320 }
321}
322
323impl<T> TryFrom<ManagedValue<T>> for ManagedGc<T> {
324 type Error = ();
325
326 fn try_from(value: ManagedValue<T>) -> Result<Self, Self::Error> {
327 match value {
328 ManagedValue::Gc(value) => Ok(value),
329 _ => Err(()),
330 }
331 }
332}
333
334pub struct DynamicManagedGc {
339 type_hash: TypeHash,
340 kind: Kind,
341 layout: Layout,
342 finalizer: Finalizer,
343 drop: bool,
344 borrowed: bool,
345}
346
347unsafe impl Send for DynamicManagedGc {}
348unsafe impl Sync for DynamicManagedGc {}
349
350impl Drop for DynamicManagedGc {
351 fn drop(&mut self) {
352 if let Kind::Owned { lifetime, data } = &mut self.kind {
353 while lifetime.state().is_in_use() {
356 std::hint::spin_loop();
357 }
358 lifetime.invalidate();
359 if !self.drop {
360 return;
361 }
362 unsafe {
363 if data.is_null() {
364 return;
365 }
366 self.finalizer.finalize(data.cast::<()>());
367 non_zero_dealloc(*data, self.layout);
368 }
369 }
370 }
371}
372
373impl DynamicManagedGc {
374 pub fn new<T: Finalize>(data: T) -> Self {
376 let layout = Layout::new::<T>().pad_to_align();
377 unsafe {
378 let memory = non_zero_alloc(layout) as *mut T;
379 if memory.is_null() {
380 handle_alloc_error(layout);
381 }
382 memory.cast::<T>().write(data);
383 Self {
384 type_hash: TypeHash::of::<T>(),
385 kind: Kind::Owned {
386 lifetime: Default::default(),
387 data: memory.cast::<u8>(),
388 },
389 layout,
390 finalizer: Finalizer::of::<T>(),
391 drop: true,
392 borrowed: false,
393 }
394 }
395 }
396
397 pub unsafe fn new_cyclic<T: Finalize>(f: impl FnOnce(Self) -> T) -> Self {
408 let layout = Layout::new::<T>().pad_to_align();
409 unsafe {
410 let memory = non_zero_alloc(layout) as *mut T;
411 if memory.is_null() {
412 handle_alloc_error(layout);
413 }
414 let result = Self {
415 type_hash: TypeHash::of::<T>(),
416 kind: Kind::Owned {
417 lifetime: Default::default(),
418 data: memory.cast::<u8>(),
419 },
420 layout,
421 finalizer: Finalizer::of::<T>(),
422 drop: true,
423 borrowed: false,
424 };
425 let data = f(result.reference());
426 memory.cast::<T>().write(data);
427 result
428 }
429 }
430
431 pub fn new_raw(
439 type_hash: TypeHash,
440 lifetime: Lifetime,
441 memory: *mut u8,
442 layout: Layout,
443 finalizer: impl Into<Finalizer>,
444 ) -> Self {
445 if memory.is_null() {
446 handle_alloc_error(layout);
447 }
448 Self {
449 type_hash,
450 kind: Kind::Owned {
451 lifetime: Box::new(lifetime),
452 data: memory,
453 },
454 layout,
455 finalizer: finalizer.into(),
456 drop: true,
457 borrowed: false,
458 }
459 }
460
461 pub fn new_uninitialized(
466 type_hash: TypeHash,
467 layout: Layout,
468 finalizer: impl Into<Finalizer>,
469 ) -> Self {
470 let memory = unsafe { non_zero_alloc(layout) };
471 if memory.is_null() {
472 handle_alloc_error(layout);
473 }
474 Self {
475 type_hash,
476 kind: Kind::Owned {
477 lifetime: Default::default(),
478 data: memory,
479 },
480 layout,
481 finalizer: finalizer.into(),
482 drop: true,
483 borrowed: false,
484 }
485 }
486
487 pub unsafe fn borrowed_raw(
513 type_hash: TypeHash,
514 memory: *mut u8,
515 layout: Layout,
516 finalizer: impl Into<Finalizer>,
517 ) -> Self {
518 if memory.is_null() {
519 handle_alloc_error(layout);
520 }
521 Self {
522 type_hash,
523 kind: Kind::Owned {
524 lifetime: Default::default(),
525 data: memory,
526 },
527 layout,
528 finalizer: finalizer.into(),
529 drop: false,
530 borrowed: true,
531 }
532 }
533
534 pub unsafe fn borrowed<T: Finalize>(value: &mut T) -> Self {
542 unsafe {
543 Self::borrowed_raw(
544 TypeHash::of::<T>(),
545 (value as *mut T).cast::<u8>(),
546 Layout::new::<T>().pad_to_align(),
547 Finalizer::of::<T>(),
548 )
549 }
550 }
551
552 pub fn reference(&self) -> Self {
554 match &self.kind {
555 Kind::Owned { lifetime, data } => Self {
556 type_hash: self.type_hash,
557 kind: Kind::Referenced {
558 lifetime: lifetime.lazy(),
559 data: *data,
560 },
561 layout: self.layout,
562 finalizer: self.finalizer.clone(),
563 drop: true,
564 borrowed: false,
565 },
566 Kind::Referenced { lifetime, data } => Self {
567 type_hash: self.type_hash,
568 kind: Kind::Referenced {
569 lifetime: lifetime.clone(),
570 data: *data,
571 },
572 layout: self.layout,
573 finalizer: self.finalizer.clone(),
574 drop: true,
575 borrowed: false,
576 },
577 }
578 }
579
580 pub fn consume<T>(mut self) -> Result<T, Self> {
585 if self.borrowed {
586 return Err(self);
587 }
588 if let Kind::Owned { lifetime, data } = &mut self.kind {
589 if self.type_hash == TypeHash::of::<T>() && !lifetime.state().is_in_use() {
590 if data.is_null() {
591 return Err(self);
592 }
593 self.drop = false;
594 let mut result = MaybeUninit::<T>::uninit();
595 unsafe {
596 result.as_mut_ptr().copy_from(data.cast::<T>(), 1);
597 non_zero_dealloc(*data, self.layout);
598 Ok(result.assume_init())
599 }
600 } else {
601 Err(self)
602 }
603 } else {
604 Err(self)
605 }
606 }
607
608 pub fn into_typed<T>(self) -> ManagedGc<T> {
610 ManagedGc {
611 dynamic: self,
612 _phantom: PhantomData,
613 }
614 }
615
616 pub fn renew(&mut self) {
619 if let Kind::Owned { lifetime, .. } = &mut self.kind {
620 **lifetime = Default::default();
621 }
622 }
623
624 pub fn type_hash(&self) -> TypeHash {
626 self.type_hash
627 }
628
629 pub fn lifetime(&self) -> ManagedGcLifetime<'_> {
632 match &self.kind {
633 Kind::Owned { lifetime, .. } => ManagedGcLifetime::Owned(lifetime),
634 Kind::Referenced { lifetime, .. } => ManagedGcLifetime::Referenced(lifetime),
635 }
636 }
637
638 pub fn layout(&self) -> &Layout {
640 &self.layout
641 }
642
643 pub fn finalizer(&self) -> &Finalizer {
645 &self.finalizer
646 }
647
648 pub unsafe fn memory(&self) -> &[u8] {
655 let memory = match &self.kind {
656 Kind::Owned { data, .. } => *data,
657 Kind::Referenced { data, .. } => *data,
658 };
659 unsafe { std::slice::from_raw_parts(memory, self.layout.size()) }
660 }
661
662 pub unsafe fn memory_mut(&mut self) -> &mut [u8] {
670 let memory = match &mut self.kind {
671 Kind::Owned { data, .. } => *data,
672 Kind::Referenced { data, .. } => *data,
673 };
674 unsafe { std::slice::from_raw_parts_mut(memory, self.layout.size()) }
675 }
676
677 pub fn exists(&self) -> bool {
681 match &self.kind {
682 Kind::Owned { .. } => true,
683 Kind::Referenced { lifetime, .. } => lifetime.exists(),
684 }
685 }
686
687 pub fn is_owning(&self) -> bool {
689 matches!(self.kind, Kind::Owned { .. })
690 }
691
692 pub fn is_borrowed(&self) -> bool {
697 self.borrowed
698 }
699
700 pub fn is_referencing(&self) -> bool {
702 matches!(self.kind, Kind::Referenced { .. })
703 }
704
705 pub fn is_owned_by(&self, other: &Self) -> bool {
707 if let (
708 Kind::Referenced {
709 lifetime: l1,
710 data: d1,
711 },
712 Kind::Owned {
713 lifetime: l2,
714 data: d2,
715 },
716 ) = (&self.kind, &other.kind)
717 {
718 *d1 == *d2 && l1.state().is_owned_by(l2.state())
719 } else {
720 false
721 }
722 }
723
724 pub fn transfer_ownership(&mut self, new_owner: &mut Self) -> bool {
729 if let (
730 Kind::Owned {
731 lifetime: l1,
732 data: d1,
733 },
734 Kind::Referenced {
735 lifetime: l2,
736 data: d2,
737 },
738 ) = (&mut self.kind, &new_owner.kind)
739 && *d1 == *d2
740 && l2.state().is_owned_by(l1.state())
741 {
742 std::mem::swap(&mut self.kind, &mut new_owner.kind);
743 std::mem::swap(&mut self.drop, &mut new_owner.drop);
746 std::mem::swap(&mut self.borrowed, &mut new_owner.borrowed);
747 true
748 } else {
749 false
750 }
751 }
752
753 pub fn is<T>(&self) -> bool {
755 self.type_hash == TypeHash::of::<T>()
756 }
757
758 pub fn try_read<T>(&'_ self) -> Option<ValueReadAccess<'_, T>> {
765 if !self.is::<T>() {
766 panic!(
767 "DynamicManagedGc is not of the requested type: {}",
768 std::any::type_name::<T>()
769 );
770 }
771 unsafe {
772 match &self.kind {
773 Kind::Owned { lifetime, data } => {
774 let data = data.cast::<T>().as_ref()?;
775 lifetime.read(data)
776 }
777 Kind::Referenced { lifetime, data } => {
778 if lifetime.exists() {
779 let data = data.cast::<T>().as_ref()?;
780 lifetime.read(data)
781 } else {
782 None
783 }
784 }
785 }
786 }
787 }
788
789 pub fn try_write<T>(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
796 if !self.is::<T>() {
797 panic!(
798 "DynamicManagedGc is not of the requested type: {}",
799 std::any::type_name::<T>()
800 );
801 }
802 unsafe {
803 match &self.kind {
804 Kind::Owned { lifetime, data } => {
805 let data = data.cast::<T>().as_mut()?;
806 lifetime.write(data)
807 }
808 Kind::Referenced { lifetime, data } => {
809 if lifetime.exists() {
810 let data = data.cast::<T>().as_mut()?;
811 lifetime.write(data)
812 } else {
813 None
814 }
815 }
816 }
817 }
818 }
819
820 pub fn read<const LOCKING: bool, T>(&'_ self) -> ValueReadAccess<'_, T> {
827 if !self.is::<T>() {
828 panic!(
829 "DynamicManagedGc is not of the requested type: {}",
830 std::any::type_name::<T>()
831 );
832 }
833 unsafe {
834 if LOCKING {
835 match &self.kind {
836 Kind::Owned { lifetime, data } => loop {
837 let data = data
838 .cast::<T>()
839 .as_ref()
840 .expect("DynamicManagedGc data pointer is null");
841 if let Some(access) = lifetime.read(data) {
842 return access;
843 }
844 std::hint::spin_loop();
845 },
846 Kind::Referenced { lifetime, data } => loop {
847 if !lifetime.exists() {
848 panic!("DynamicManagedGc owner is dead");
849 }
850 let data = data
851 .cast::<T>()
852 .as_ref()
853 .expect("DynamicManagedGc data pointer is null");
854 if let Some(access) = lifetime.read(data) {
855 return access;
856 }
857 std::hint::spin_loop();
858 },
859 }
860 } else {
861 match &self.kind {
862 Kind::Owned { lifetime, data } => {
863 let data = data
864 .cast::<T>()
865 .as_ref()
866 .expect("DynamicManagedGc data pointer is null");
867 lifetime
868 .read(data)
869 .expect("DynamicManagedGc is inaccessible for reading")
870 }
871 Kind::Referenced { lifetime, data } => {
872 let data = data
873 .cast::<T>()
874 .as_ref()
875 .expect("DynamicManagedGc data pointer is null");
876 lifetime
877 .read(data)
878 .expect("DynamicManagedGc is inaccessible for reading")
879 }
880 }
881 }
882 }
883 }
884
885 pub fn write<const LOCKING: bool, T>(&'_ mut self) -> ValueWriteAccess<'_, T> {
892 if !self.is::<T>() {
893 panic!(
894 "DynamicManagedGc is not of the requested type: {}",
895 std::any::type_name::<T>()
896 );
897 }
898 unsafe {
899 if LOCKING {
900 match &self.kind {
901 Kind::Owned { lifetime, data } => loop {
902 let data = data
903 .cast::<T>()
904 .as_mut()
905 .expect("DynamicManagedGc data pointer is null");
906 if let Some(access) = lifetime.write(data) {
907 return access;
908 }
909 std::hint::spin_loop();
910 },
911 Kind::Referenced { lifetime, data } => loop {
912 if !lifetime.exists() {
913 panic!("DynamicManagedGc owner is dead");
914 }
915 let data = data
916 .cast::<T>()
917 .as_mut()
918 .expect("DynamicManagedGc data pointer is null");
919 if let Some(access) = lifetime.write(data) {
920 return access;
921 }
922 std::hint::spin_loop();
923 },
924 }
925 } else {
926 match &self.kind {
927 Kind::Owned { lifetime, data } => {
928 let data = data
929 .cast::<T>()
930 .as_mut()
931 .expect("DynamicManagedGc data pointer is null");
932 lifetime
933 .write(data)
934 .expect("DynamicManagedGc is inaccessible for writing")
935 }
936 Kind::Referenced { lifetime, data } => {
937 let data = data
938 .cast::<T>()
939 .as_mut()
940 .expect("DynamicManagedGc data pointer is null");
941 lifetime
942 .write(data)
943 .expect("DynamicManagedGc is inaccessible for writing")
944 }
945 }
946 }
947 }
948 }
949
950 pub fn try_borrow(&self) -> Option<DynamicManagedRef> {
953 unsafe {
954 match &self.kind {
955 Kind::Owned { lifetime, data } => {
956 DynamicManagedRef::new_raw(self.type_hash, lifetime.borrow()?, *data)
957 }
958 Kind::Referenced { lifetime, data } => {
959 DynamicManagedRef::new_raw(self.type_hash, lifetime.borrow()?, *data)
960 }
961 }
962 }
963 }
964
965 pub fn try_borrow_mut(&self) -> Option<DynamicManagedRefMut> {
968 unsafe {
969 match &self.kind {
970 Kind::Owned { lifetime, data } => {
971 DynamicManagedRefMut::new_raw(self.type_hash, lifetime.borrow_mut()?, *data)
972 }
973 Kind::Referenced { lifetime, data } => {
974 DynamicManagedRefMut::new_raw(self.type_hash, lifetime.borrow_mut()?, *data)
975 }
976 }
977 }
978 }
979
980 pub fn borrow<const LOCKING: bool>(&self) -> DynamicManagedRef {
987 unsafe {
988 if LOCKING {
989 match &self.kind {
990 Kind::Owned { lifetime, data } => loop {
991 if let Some(lifetime) = lifetime.borrow() {
992 return DynamicManagedRef::new_raw(self.type_hash, lifetime, *data)
993 .expect("DynamicManagedGc cannot be immutably borrowed");
994 }
995 std::hint::spin_loop();
996 },
997 Kind::Referenced { lifetime, data } => loop {
998 if !lifetime.exists() {
999 panic!("DynamicManagedGc owner is dead");
1000 }
1001 if let Some(lifetime) = lifetime.borrow() {
1002 return DynamicManagedRef::new_raw(self.type_hash, lifetime, *data)
1003 .expect("DynamicManagedGc cannot be immutably borrowed");
1004 }
1005 std::hint::spin_loop();
1006 },
1007 }
1008 } else {
1009 match &self.kind {
1010 Kind::Owned { lifetime, data } => DynamicManagedRef::new_raw(
1011 self.type_hash,
1012 lifetime
1013 .borrow()
1014 .expect("DynamicManagedGc is inaccessible for immutable borrowing"),
1015 *data,
1016 )
1017 .expect("DynamicManagedGc cannot be immutably borrowed"),
1018 Kind::Referenced { lifetime, data } => DynamicManagedRef::new_raw(
1019 self.type_hash,
1020 lifetime
1021 .borrow()
1022 .expect("DynamicManagedGc is inaccessible for immutable borrowing"),
1023 *data,
1024 )
1025 .expect("DynamicManagedGc cannot be immutably borrowed"),
1026 }
1027 }
1028 }
1029 }
1030
1031 pub fn borrow_mut<const LOCKING: bool>(&mut self) -> DynamicManagedRefMut {
1038 unsafe {
1039 if LOCKING {
1040 match &self.kind {
1041 Kind::Owned { lifetime, data } => loop {
1042 if let Some(lifetime) = lifetime.borrow_mut() {
1043 return DynamicManagedRefMut::new_raw(self.type_hash, lifetime, *data)
1044 .expect("DynamicManagedGc cannot be mutably borrowed");
1045 }
1046 std::hint::spin_loop();
1047 },
1048 Kind::Referenced { lifetime, data } => loop {
1049 if !lifetime.exists() {
1050 panic!("DynamicManagedGc owner is dead");
1051 }
1052 if let Some(lifetime) = lifetime.borrow_mut() {
1053 return DynamicManagedRefMut::new_raw(self.type_hash, lifetime, *data)
1054 .expect("DynamicManagedGc cannot be mutably borrowed");
1055 }
1056 std::hint::spin_loop();
1057 },
1058 }
1059 } else {
1060 match &self.kind {
1061 Kind::Owned { lifetime, data } => DynamicManagedRefMut::new_raw(
1062 self.type_hash,
1063 lifetime
1064 .borrow_mut()
1065 .expect("DynamicManagedGc is inaccessible for mutable borrowing"),
1066 *data,
1067 )
1068 .expect("DynamicManagedGc cannot be mutably borrowed"),
1069 Kind::Referenced { lifetime, data } => DynamicManagedRefMut::new_raw(
1070 self.type_hash,
1071 lifetime
1072 .borrow_mut()
1073 .expect("DynamicManagedGc is inaccessible for mutable borrowing"),
1074 *data,
1075 )
1076 .expect("DynamicManagedGc cannot be mutably borrowed"),
1077 }
1078 }
1079 }
1080 }
1081
1082 pub fn lazy(&self) -> DynamicManagedLazy {
1088 unsafe {
1089 match &self.kind {
1090 Kind::Owned { lifetime, data } => {
1091 DynamicManagedLazy::new_raw(self.type_hash, lifetime.lazy(), *data)
1092 .expect("DynamicManagedGc cannot be lazily borrowed")
1093 }
1094 Kind::Referenced { lifetime, data } => {
1095 DynamicManagedLazy::new_raw(self.type_hash, lifetime.clone(), *data)
1096 .expect("DynamicManagedGc cannot be lazily borrowed")
1097 }
1098 }
1099 }
1100 }
1101
1102 pub unsafe fn as_ptr_raw(&self) -> *const u8 {
1109 match &self.kind {
1110 Kind::Owned { data, .. } => *data as *const u8,
1111 Kind::Referenced { data, .. } => *data as *const u8,
1112 }
1113 }
1114
1115 pub unsafe fn as_mut_ptr_raw(&mut self) -> *mut u8 {
1122 match &self.kind {
1123 Kind::Owned { data, .. } => *data,
1124 Kind::Referenced { data, .. } => *data,
1125 }
1126 }
1127}
1128
1129impl TryFrom<DynamicManagedValue> for DynamicManagedGc {
1130 type Error = ();
1131
1132 fn try_from(value: DynamicManagedValue) -> Result<Self, Self::Error> {
1133 match value {
1134 DynamicManagedValue::Gc(value) => Ok(value),
1135 _ => Err(()),
1136 }
1137 }
1138}
1139
1140#[cfg(test)]
1141mod tests {
1142 use super::*;
1143 use std::sync::{
1144 Arc,
1145 atomic::{AtomicUsize, Ordering},
1146 };
1147
1148 #[test]
1149 fn test_is_async() {
1150 fn is_async<T: Send + Sync>() {}
1151
1152 is_async::<ManagedGc<()>>();
1153 is_async::<DynamicManagedGc>();
1154 }
1155
1156 #[test]
1157 fn test_managed_gc() {
1158 let mut managed = ManagedGc::new(42);
1159 {
1160 let read_access = managed.read::<true>();
1161 assert_eq!(*read_access, 42);
1162 }
1163 {
1164 let mut write_access = managed.write::<true>();
1165 *write_access = 100;
1166 }
1167 {
1168 let read_access = managed.read::<true>();
1169 assert_eq!(*read_access, 100);
1170 }
1171 }
1172
1173 #[test]
1174 #[allow(unused)]
1175 fn test_managed_gc_lifetimes() {
1176 struct Car {
1177 gear: i32,
1178 engine: Option<ManagedGc<Engine>>,
1179 }
1180
1181 struct Engine {
1182 owning_car: Option<ManagedGc<Car>>,
1183 horsepower: i32,
1184 }
1185
1186 let mut car = ManagedGc::new(Car {
1187 gear: 1,
1188 engine: None,
1189 });
1190 let engine = ManagedGc::new(Engine {
1191 owning_car: Some(car.reference()),
1192 horsepower: 200,
1193 });
1194 let engine2 = engine.reference();
1195 car.write::<true>().engine = Some(engine);
1196
1197 assert!(car.exists());
1198 assert!(car.is_owning());
1199 assert!(engine2.exists());
1200 assert!(engine2.is_referencing());
1201 assert!(engine2.is_owned_by(car.read::<true>().engine.as_ref().unwrap()));
1202
1203 let car2 = car.reference();
1204 assert!(car2.exists());
1205 assert!(car2.is_referencing());
1206
1207 drop(car);
1208 assert!(!car2.exists());
1209 assert!(car2.try_read().is_none());
1210 assert!(!engine2.exists());
1211 assert!(engine2.try_read().is_none());
1212 }
1213
1214 #[test]
1215 fn test_managed_gc_cycles() {
1216 #[derive(Default)]
1217 struct Foo {
1218 other: Option<ManagedGc<Self>>,
1219 }
1220
1221 {
1222 let mut a = ManagedGc::<Foo>::default();
1223 let mut b = ManagedGc::<Foo>::default();
1224 a.write::<true>().other = Some(b.reference());
1225 b.write::<true>().other = Some(a.reference());
1226
1227 assert!(a.exists());
1228 assert!(a.is_owning());
1229 assert!(a.read::<true>().other.as_ref().unwrap().is_referencing());
1230 assert!(a.read::<true>().other.as_ref().unwrap().is_owned_by(&b));
1231
1232 assert!(b.exists());
1233 assert!(b.is_owning());
1234 assert!(b.read::<true>().other.as_ref().unwrap().is_referencing());
1235 assert!(b.read::<true>().other.as_ref().unwrap().is_owned_by(&a));
1236
1237 drop(b);
1238 assert!(!a.read::<true>().other.as_ref().unwrap().exists());
1239 }
1240
1241 {
1242 let mut a = ManagedGc::<Foo>::default();
1243 a.write::<true>().other = Some(a.reference());
1244
1245 assert!(a.exists());
1246 assert!(a.is_owning());
1247 assert!(a.read::<true>().other.as_ref().unwrap().is_referencing());
1248 assert!(a.read::<true>().other.as_ref().unwrap().is_owned_by(&a));
1249 }
1250 }
1251
1252 #[test]
1253 fn test_dynamic_managed_gc() {
1254 let mut managed = DynamicManagedGc::new(42);
1255 {
1256 let read_access = managed.read::<true, i32>();
1257 assert_eq!(*read_access, 42);
1258 }
1259 {
1260 let mut write_access = managed.write::<true, i32>();
1261 *write_access = 100;
1262 }
1263 {
1264 let read_access = managed.read::<true, i32>();
1265 assert_eq!(*read_access, 100);
1266 }
1267 }
1268
1269 #[test]
1270 fn test_dynamic_managed_gc_cycles() {
1271 #[derive(Default)]
1272 struct Foo {
1273 other: Option<DynamicManagedGc>,
1274 }
1275
1276 {
1277 let mut a = DynamicManagedGc::new(Foo::default());
1278 let mut b = DynamicManagedGc::new(Foo::default());
1279 a.write::<true, Foo>().other = Some(b.reference());
1280 b.write::<true, Foo>().other = Some(a.reference());
1281
1282 assert!(a.exists());
1283 assert!(a.is_owning());
1284 assert!(
1285 a.read::<true, Foo>()
1286 .other
1287 .as_ref()
1288 .unwrap()
1289 .is_referencing()
1290 );
1291 assert!(
1292 a.read::<true, Foo>()
1293 .other
1294 .as_ref()
1295 .unwrap()
1296 .is_owned_by(&b)
1297 );
1298
1299 assert!(b.exists());
1300 assert!(b.is_owning());
1301 assert!(
1302 b.read::<true, Foo>()
1303 .other
1304 .as_ref()
1305 .unwrap()
1306 .is_referencing()
1307 );
1308 assert!(
1309 b.read::<true, Foo>()
1310 .other
1311 .as_ref()
1312 .unwrap()
1313 .is_owned_by(&a)
1314 );
1315
1316 drop(b);
1317 assert!(!a.read::<true, Foo>().other.as_ref().unwrap().exists());
1318 }
1319
1320 {
1321 let mut a = DynamicManagedGc::new(Foo::default());
1322 a.write::<true, Foo>().other = Some(a.reference());
1323
1324 assert!(a.exists());
1325 assert!(a.is_owning());
1326 assert!(
1327 a.read::<true, Foo>()
1328 .other
1329 .as_ref()
1330 .unwrap()
1331 .is_referencing()
1332 );
1333 assert!(
1334 a.read::<true, Foo>()
1335 .other
1336 .as_ref()
1337 .unwrap()
1338 .is_owned_by(&a)
1339 );
1340 }
1341 }
1342
1343 #[test]
1344 fn test_managed_gc_conversions() {
1345 let managed = ManagedGc::new(42);
1346 assert_eq!(*managed.read::<true>(), 42);
1347
1348 let mut dynamic = managed.into_dynamic();
1349 *dynamic.write::<true, i32>() = 100;
1350
1351 let managed = dynamic.into_typed::<i32>();
1352 assert_eq!(*managed.read::<true>(), 100);
1353 }
1354
1355 #[test]
1356 fn test_managed_gc_dead_owner() {
1357 let a = ManagedGc::new(42);
1358 let mut b = a.reference();
1359
1360 assert!(a.exists());
1361 assert!(b.exists());
1362 assert_eq!(*b.read::<true>(), 42);
1363
1364 drop(a);
1365 assert!(!b.exists());
1366 assert!(b.try_write().is_none());
1367 }
1368
1369 #[test]
1370 #[should_panic]
1371 fn test_managed_gc_dead_owner_panic() {
1372 let a = ManagedGc::new(42);
1373 let mut b = a.reference();
1374
1375 assert!(a.exists());
1376 assert!(b.exists());
1377 assert_eq!(*b.read::<true>(), 42);
1378
1379 drop(a);
1380 assert!(!b.exists());
1381 assert_eq!(*b.write::<true>(), 42);
1382 }
1383
1384 #[test]
1385 fn test_managed_gc_cyclic() {
1386 struct SelfReferencial {
1387 value: i32,
1388 this: ManagedGc<SelfReferencial>,
1389 }
1390
1391 let v = unsafe { ManagedGc::new_cyclic(|this| SelfReferencial { value: 42, this }) };
1392 assert_eq!(v.read::<true>().value, 42);
1393 let this = v.read::<true>().this.reference();
1394 assert_eq!(this.read::<true>().value, 42);
1395 }
1396
1397 #[test]
1398 fn test_managed_gc_transfer_ownership() {
1399 let mut a = ManagedGc::new(42);
1400 let mut b = a.reference();
1401
1402 assert!(!a.is_owned_by(&b));
1403 assert!(b.is_owned_by(&a));
1404 assert!(!b.transfer_ownership(&mut a));
1405 assert!(a.transfer_ownership(&mut b));
1406 assert!(a.is_owned_by(&b));
1407 assert!(!b.is_owned_by(&a));
1408 drop(b);
1409 assert!(!a.exists());
1410 }
1411
1412 struct Probe(Arc<AtomicUsize>);
1413
1414 impl Drop for Probe {
1415 fn drop(&mut self) {
1416 self.0.fetch_add(1, Ordering::SeqCst);
1417 }
1418 }
1419
1420 #[test]
1421 fn test_borrowed_gc_leaves_the_value_to_its_owner() {
1422 let drops = Arc::new(AtomicUsize::new(0));
1423 let mut value = Probe(drops.clone());
1424 let handle = {
1425 let owner = unsafe { DynamicManagedGc::borrowed(&mut value) };
1426 assert!(owner.is_owning());
1427 assert!(owner.is_borrowed());
1428 let handle = owner.reference();
1429 assert!(handle.exists());
1430 handle
1431 };
1432
1433 assert!(!handle.exists());
1434 assert!(handle.try_read::<Probe>().is_none());
1435
1436 assert_eq!(drops.load(Ordering::SeqCst), 0);
1437 drop(value);
1438 assert_eq!(drops.load(Ordering::SeqCst), 1);
1439 }
1440
1441 #[test]
1442 fn test_borrowed_gc_refuses_to_be_consumed() {
1443 let drops = Arc::new(AtomicUsize::new(0));
1444 let mut value = Probe(drops.clone());
1445
1446 let owner = unsafe { DynamicManagedGc::borrowed(&mut value) };
1447 assert!(owner.consume::<Probe>().is_err());
1448 assert_eq!(drops.load(Ordering::SeqCst), 0);
1449 }
1450
1451 #[test]
1452 fn test_a_transferred_borrow_still_frees_nothing() {
1453 let drops = Arc::new(AtomicUsize::new(0));
1454 let mut value = Probe(drops.clone());
1455 {
1456 let mut owner = unsafe { DynamicManagedGc::borrowed(&mut value) };
1457 let mut taker = owner.reference();
1458 assert!(owner.transfer_ownership(&mut taker));
1459
1460 assert!(taker.is_owning());
1461 assert!(taker.is_borrowed());
1462 assert!(!owner.is_borrowed());
1463 }
1464 assert_eq!(drops.load(Ordering::SeqCst), 0);
1465 }
1466
1467 #[test]
1468 fn test_a_consumed_value_reports_gone_to_its_references() {
1469 let owner = DynamicManagedGc::new(42i32);
1470 let handle = owner.reference();
1471 assert!(handle.exists());
1472
1473 assert_eq!(owner.consume::<i32>().ok(), Some(42));
1474 assert!(!handle.exists());
1475 }
1476}