1use crate::{
2 Finalize,
3 lifetime::{Lifetime, LifetimeLazy, ValueReadAccess, ValueWriteAccess},
4 managed::{
5 DynamicManagedLazy, DynamicManagedRef, DynamicManagedRefMut, ManagedLazy, ManagedRef,
6 ManagedRefMut,
7 value::{DynamicManagedValue, ManagedValue},
8 },
9 non_zero_alloc, non_zero_dealloc,
10 type_hash::TypeHash,
11};
12use std::{
13 alloc::{Layout, handle_alloc_error},
14 marker::PhantomData,
15 mem::MaybeUninit,
16};
17
18enum Kind {
19 Owned {
20 lifetime: Box<Lifetime>,
21 data: *mut u8,
22 },
23 Referenced {
24 lifetime: LifetimeLazy,
25 data: *mut u8,
26 },
27}
28
29pub enum ManagedGcLifetime<'a> {
30 Owned(&'a Lifetime),
31 Referenced(&'a LifetimeLazy),
32}
33
34pub struct ManagedGc<T> {
35 dynamic: DynamicManagedGc,
36 _phantom: PhantomData<fn() -> T>,
37}
38
39unsafe impl<T> Send for ManagedGc<T> {}
40unsafe impl<T> Sync for ManagedGc<T> {}
41
42impl<T: Default> Default for ManagedGc<T> {
43 fn default() -> Self {
44 Self::new(T::default())
45 }
46}
47
48impl<T> ManagedGc<T> {
49 pub fn new(data: T) -> Self {
50 Self {
51 dynamic: DynamicManagedGc::new(data),
52 _phantom: PhantomData,
53 }
54 }
55
56 pub unsafe fn new_cyclic(f: impl FnOnce(Self) -> T) -> Self {
58 Self {
59 dynamic: unsafe { DynamicManagedGc::new_cyclic(|dynamic| f(dynamic.into_typed())) },
60 _phantom: PhantomData,
61 }
62 }
63
64 pub fn reference(&self) -> Self {
65 Self {
66 dynamic: self.dynamic.reference(),
67 _phantom: PhantomData,
68 }
69 }
70
71 pub fn consume(self) -> Result<T, Self> {
72 self.dynamic.consume().map_err(|value| Self {
73 dynamic: value,
74 _phantom: PhantomData,
75 })
76 }
77
78 pub fn into_dynamic(self) -> DynamicManagedGc {
79 self.dynamic
80 }
81
82 pub fn renew(&mut self) {
83 self.dynamic.renew();
84 }
85
86 pub fn type_hash(&self) -> TypeHash {
87 self.dynamic.type_hash()
88 }
89
90 pub fn lifetime(&self) -> ManagedGcLifetime<'_> {
91 self.dynamic.lifetime()
92 }
93
94 pub fn exists(&self) -> bool {
95 self.dynamic.exists()
96 }
97
98 pub fn is_owning(&self) -> bool {
99 self.dynamic.is_owning()
100 }
101
102 pub fn is_referencing(&self) -> bool {
103 self.dynamic.is_referencing()
104 }
105
106 pub fn is_owned_by(&self, other: &Self) -> bool {
107 self.dynamic.is_owned_by(&other.dynamic)
108 }
109
110 pub fn transfer_ownership(&mut self, new_owner: &mut Self) -> bool {
111 self.dynamic.transfer_ownership(&mut new_owner.dynamic)
112 }
113
114 pub fn try_read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
115 self.dynamic.try_read::<T>()
116 }
117
118 pub fn try_write(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
119 self.dynamic.try_write::<T>()
120 }
121
122 pub fn read<const LOCKING: bool>(&'_ self) -> ValueReadAccess<'_, T> {
123 self.dynamic.read::<LOCKING, T>()
124 }
125
126 pub fn write<const LOCKING: bool>(&'_ mut self) -> ValueWriteAccess<'_, T> {
127 self.dynamic.write::<LOCKING, T>()
128 }
129
130 pub fn try_borrow(&self) -> Option<ManagedRef<T>> {
131 self.dynamic.try_borrow()?.into_typed().ok()
132 }
133
134 pub fn try_borrow_mut(&self) -> Option<ManagedRefMut<T>> {
135 self.dynamic.try_borrow_mut()?.into_typed().ok()
136 }
137
138 pub fn borrow<const LOCKING: bool>(&self) -> ManagedRef<T> {
139 self.dynamic
140 .borrow::<LOCKING>()
141 .into_typed()
142 .ok()
143 .expect("ManagedGc cannot be immutably borrowed")
144 }
145
146 pub fn borrow_mut<const LOCKING: bool>(&mut self) -> ManagedRefMut<T> {
147 self.dynamic
148 .borrow_mut::<LOCKING>()
149 .into_typed()
150 .ok()
151 .expect("ManagedGc cannot be mutably borrowed")
152 }
153
154 pub fn lazy(&self) -> ManagedLazy<T> {
155 self.dynamic
156 .lazy()
157 .into_typed()
158 .ok()
159 .expect("ManagedGc cannot be lazily borrowed")
160 }
161
162 pub unsafe fn as_ptr(&self) -> *const T {
164 unsafe { self.dynamic.as_ptr_raw().cast::<T>() }
165 }
166
167 pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
169 unsafe { self.dynamic.as_mut_ptr_raw().cast::<T>() }
170 }
171}
172
173impl<T> TryFrom<ManagedValue<T>> for ManagedGc<T> {
174 type Error = ();
175
176 fn try_from(value: ManagedValue<T>) -> Result<Self, Self::Error> {
177 match value {
178 ManagedValue::Gc(value) => Ok(value),
179 _ => Err(()),
180 }
181 }
182}
183
184pub struct DynamicManagedGc {
185 type_hash: TypeHash,
186 kind: Kind,
187 layout: Layout,
188 finalizer: unsafe fn(*mut ()),
189 drop: bool,
190}
191
192unsafe impl Send for DynamicManagedGc {}
193unsafe impl Sync for DynamicManagedGc {}
194
195impl Drop for DynamicManagedGc {
196 fn drop(&mut self) {
197 if let Kind::Owned { lifetime, data } = &mut self.kind
198 && self.drop
199 {
200 while lifetime.state().is_in_use() {
201 std::hint::spin_loop();
202 }
203 lifetime.invalidate();
204 unsafe {
205 if data.is_null() {
206 return;
207 }
208 (self.finalizer)(data.cast::<()>());
209 non_zero_dealloc(*data, self.layout);
210 }
211 }
212 }
213}
214
215impl DynamicManagedGc {
216 pub fn new<T: Finalize>(data: T) -> Self {
217 let layout = Layout::new::<T>().pad_to_align();
218 unsafe {
219 let memory = non_zero_alloc(layout) as *mut T;
220 if memory.is_null() {
221 handle_alloc_error(layout);
222 }
223 memory.cast::<T>().write(data);
224 Self {
225 type_hash: TypeHash::of::<T>(),
226 kind: Kind::Owned {
227 lifetime: Default::default(),
228 data: memory.cast::<u8>(),
229 },
230 layout,
231 finalizer: T::finalize_raw,
232 drop: true,
233 }
234 }
235 }
236
237 pub unsafe fn new_cyclic<T: Finalize>(f: impl FnOnce(Self) -> T) -> Self {
239 let layout = Layout::new::<T>().pad_to_align();
240 unsafe {
241 let memory = non_zero_alloc(layout) as *mut T;
242 if memory.is_null() {
243 handle_alloc_error(layout);
244 }
245 let result = Self {
246 type_hash: TypeHash::of::<T>(),
247 kind: Kind::Owned {
248 lifetime: Default::default(),
249 data: memory.cast::<u8>(),
250 },
251 layout,
252 finalizer: T::finalize_raw,
253 drop: true,
254 };
255 let data = f(result.reference());
256 memory.cast::<T>().write(data);
257 result
258 }
259 }
260
261 pub fn new_raw(
262 type_hash: TypeHash,
263 lifetime: Lifetime,
264 memory: *mut u8,
265 layout: Layout,
266 finalizer: unsafe fn(*mut ()),
267 ) -> Self {
268 if memory.is_null() {
269 handle_alloc_error(layout);
270 }
271 Self {
272 type_hash,
273 kind: Kind::Owned {
274 lifetime: Box::new(lifetime),
275 data: memory,
276 },
277 layout,
278 finalizer,
279 drop: true,
280 }
281 }
282
283 pub fn new_uninitialized(
284 type_hash: TypeHash,
285 layout: Layout,
286 finalizer: unsafe fn(*mut ()),
287 ) -> Self {
288 let memory = unsafe { non_zero_alloc(layout) };
289 if memory.is_null() {
290 handle_alloc_error(layout);
291 }
292 Self {
293 type_hash,
294 kind: Kind::Owned {
295 lifetime: Default::default(),
296 data: memory,
297 },
298 layout,
299 finalizer,
300 drop: true,
301 }
302 }
303
304 pub fn reference(&self) -> Self {
305 match &self.kind {
306 Kind::Owned { lifetime, data } => Self {
307 type_hash: self.type_hash,
308 kind: Kind::Referenced {
309 lifetime: lifetime.lazy(),
310 data: *data,
311 },
312 layout: self.layout,
313 finalizer: self.finalizer,
314 drop: true,
315 },
316 Kind::Referenced { lifetime, data } => Self {
317 type_hash: self.type_hash,
318 kind: Kind::Referenced {
319 lifetime: lifetime.clone(),
320 data: *data,
321 },
322 layout: self.layout,
323 finalizer: self.finalizer,
324 drop: true,
325 },
326 }
327 }
328
329 pub fn consume<T>(mut self) -> Result<T, Self> {
330 if let Kind::Owned { lifetime, data } = &mut self.kind {
331 if self.type_hash == TypeHash::of::<T>() && !lifetime.state().is_in_use() {
332 if data.is_null() {
333 return Err(self);
334 }
335 self.drop = false;
336 let mut result = MaybeUninit::<T>::uninit();
337 unsafe {
338 result.as_mut_ptr().copy_from(data.cast::<T>(), 1);
339 non_zero_dealloc(*data, self.layout);
340 Ok(result.assume_init())
341 }
342 } else {
343 Err(self)
344 }
345 } else {
346 Err(self)
347 }
348 }
349
350 pub fn into_typed<T>(self) -> ManagedGc<T> {
351 ManagedGc {
352 dynamic: self,
353 _phantom: PhantomData,
354 }
355 }
356
357 pub fn renew(&mut self) {
358 if let Kind::Owned { lifetime, .. } = &mut self.kind {
359 **lifetime = Default::default();
360 }
361 }
362
363 pub fn type_hash(&self) -> TypeHash {
364 self.type_hash
365 }
366
367 pub fn lifetime(&self) -> ManagedGcLifetime<'_> {
368 match &self.kind {
369 Kind::Owned { lifetime, .. } => ManagedGcLifetime::Owned(lifetime),
370 Kind::Referenced { lifetime, .. } => ManagedGcLifetime::Referenced(lifetime),
371 }
372 }
373
374 pub fn layout(&self) -> &Layout {
375 &self.layout
376 }
377
378 pub fn finalizer(&self) -> unsafe fn(*mut ()) {
379 self.finalizer
380 }
381
382 pub unsafe fn memory(&self) -> &[u8] {
384 let memory = match &self.kind {
385 Kind::Owned { data, .. } => *data,
386 Kind::Referenced { data, .. } => *data,
387 };
388 unsafe { std::slice::from_raw_parts(memory, self.layout.size()) }
389 }
390
391 pub unsafe fn memory_mut(&mut self) -> &mut [u8] {
393 let memory = match &mut self.kind {
394 Kind::Owned { data, .. } => *data,
395 Kind::Referenced { data, .. } => *data,
396 };
397 unsafe { std::slice::from_raw_parts_mut(memory, self.layout.size()) }
398 }
399
400 pub fn exists(&self) -> bool {
401 match &self.kind {
402 Kind::Owned { .. } => true,
403 Kind::Referenced { lifetime, .. } => lifetime.exists(),
404 }
405 }
406
407 pub fn is_owning(&self) -> bool {
408 matches!(self.kind, Kind::Owned { .. })
409 }
410
411 pub fn is_referencing(&self) -> bool {
412 matches!(self.kind, Kind::Referenced { .. })
413 }
414
415 pub fn is_owned_by(&self, other: &Self) -> bool {
416 if let (
417 Kind::Referenced {
418 lifetime: l1,
419 data: d1,
420 },
421 Kind::Owned {
422 lifetime: l2,
423 data: d2,
424 },
425 ) = (&self.kind, &other.kind)
426 {
427 *d1 == *d2 && l1.state().is_owned_by(l2.state())
428 } else {
429 false
430 }
431 }
432
433 pub fn transfer_ownership(&mut self, new_owner: &mut Self) -> bool {
434 if let (
435 Kind::Owned {
436 lifetime: l1,
437 data: d1,
438 },
439 Kind::Referenced {
440 lifetime: l2,
441 data: d2,
442 },
443 ) = (&mut self.kind, &new_owner.kind)
444 && *d1 == *d2
445 && l2.state().is_owned_by(l1.state())
446 {
447 std::mem::swap(&mut self.kind, &mut new_owner.kind);
448 true
449 } else {
450 false
451 }
452 }
453
454 pub fn is<T>(&self) -> bool {
455 self.type_hash == TypeHash::of::<T>()
456 }
457
458 pub fn try_read<T>(&'_ self) -> Option<ValueReadAccess<'_, T>> {
459 if !self.is::<T>() {
460 panic!(
461 "DynamicManagedGc is not of the requested type: {}",
462 std::any::type_name::<T>()
463 );
464 }
465 unsafe {
466 match &self.kind {
467 Kind::Owned { lifetime, data } => {
468 let data = data.cast::<T>().as_ref()?;
469 lifetime.read(data)
470 }
471 Kind::Referenced { lifetime, data } => {
472 if lifetime.exists() {
473 let data = data.cast::<T>().as_ref()?;
474 lifetime.read(data)
475 } else {
476 None
477 }
478 }
479 }
480 }
481 }
482
483 pub fn try_write<T>(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
484 if !self.is::<T>() {
485 panic!(
486 "DynamicManagedGc is not of the requested type: {}",
487 std::any::type_name::<T>()
488 );
489 }
490 unsafe {
491 match &self.kind {
492 Kind::Owned { lifetime, data } => {
493 let data = data.cast::<T>().as_mut()?;
494 lifetime.write(data)
495 }
496 Kind::Referenced { lifetime, data } => {
497 if lifetime.exists() {
498 let data = data.cast::<T>().as_mut()?;
499 lifetime.write(data)
500 } else {
501 None
502 }
503 }
504 }
505 }
506 }
507
508 pub fn read<const LOCKING: bool, T>(&'_ self) -> ValueReadAccess<'_, T> {
509 if !self.is::<T>() {
510 panic!(
511 "DynamicManagedGc is not of the requested type: {}",
512 std::any::type_name::<T>()
513 );
514 }
515 unsafe {
516 if LOCKING {
517 match &self.kind {
518 Kind::Owned { lifetime, data } => loop {
519 let data = data
520 .cast::<T>()
521 .as_ref()
522 .expect("DynamicManagedGc data pointer is null");
523 if let Some(access) = lifetime.read(data) {
524 return access;
525 }
526 std::hint::spin_loop();
527 },
528 Kind::Referenced { lifetime, data } => loop {
529 if !lifetime.exists() {
530 panic!("DynamicManagedGc owner is dead");
531 }
532 let data = data
533 .cast::<T>()
534 .as_ref()
535 .expect("DynamicManagedGc data pointer is null");
536 if let Some(access) = lifetime.read(data) {
537 return access;
538 }
539 std::hint::spin_loop();
540 },
541 }
542 } else {
543 match &self.kind {
544 Kind::Owned { lifetime, data } => {
545 let data = data
546 .cast::<T>()
547 .as_ref()
548 .expect("DynamicManagedGc data pointer is null");
549 lifetime
550 .read(data)
551 .expect("DynamicManagedGc is inaccessible for reading")
552 }
553 Kind::Referenced { lifetime, data } => {
554 let data = data
555 .cast::<T>()
556 .as_ref()
557 .expect("DynamicManagedGc data pointer is null");
558 lifetime
559 .read(data)
560 .expect("DynamicManagedGc is inaccessible for reading")
561 }
562 }
563 }
564 }
565 }
566
567 pub fn write<const LOCKING: bool, T>(&'_ mut self) -> ValueWriteAccess<'_, T> {
568 if !self.is::<T>() {
569 panic!(
570 "DynamicManagedGc is not of the requested type: {}",
571 std::any::type_name::<T>()
572 );
573 }
574 unsafe {
575 if LOCKING {
576 match &self.kind {
577 Kind::Owned { lifetime, data } => loop {
578 let data = data
579 .cast::<T>()
580 .as_mut()
581 .expect("DynamicManagedGc data pointer is null");
582 if let Some(access) = lifetime.write(data) {
583 return access;
584 }
585 std::hint::spin_loop();
586 },
587 Kind::Referenced { lifetime, data } => loop {
588 if !lifetime.exists() {
589 panic!("DynamicManagedGc owner is dead");
590 }
591 let data = data
592 .cast::<T>()
593 .as_mut()
594 .expect("DynamicManagedGc data pointer is null");
595 if let Some(access) = lifetime.write(data) {
596 return access;
597 }
598 std::hint::spin_loop();
599 },
600 }
601 } else {
602 match &self.kind {
603 Kind::Owned { lifetime, data } => {
604 let data = data
605 .cast::<T>()
606 .as_mut()
607 .expect("DynamicManagedGc data pointer is null");
608 lifetime
609 .write(data)
610 .expect("DynamicManagedGc is inaccessible for writing")
611 }
612 Kind::Referenced { lifetime, data } => {
613 let data = data
614 .cast::<T>()
615 .as_mut()
616 .expect("DynamicManagedGc data pointer is null");
617 lifetime
618 .write(data)
619 .expect("DynamicManagedGc is inaccessible for writing")
620 }
621 }
622 }
623 }
624 }
625
626 pub fn try_borrow(&self) -> Option<DynamicManagedRef> {
627 unsafe {
628 match &self.kind {
629 Kind::Owned { lifetime, data } => {
630 DynamicManagedRef::new_raw(self.type_hash, lifetime.borrow()?, *data)
631 }
632 Kind::Referenced { lifetime, data } => {
633 DynamicManagedRef::new_raw(self.type_hash, lifetime.borrow()?, *data)
634 }
635 }
636 }
637 }
638
639 pub fn try_borrow_mut(&self) -> Option<DynamicManagedRefMut> {
640 unsafe {
641 match &self.kind {
642 Kind::Owned { lifetime, data } => {
643 DynamicManagedRefMut::new_raw(self.type_hash, lifetime.borrow_mut()?, *data)
644 }
645 Kind::Referenced { lifetime, data } => {
646 DynamicManagedRefMut::new_raw(self.type_hash, lifetime.borrow_mut()?, *data)
647 }
648 }
649 }
650 }
651
652 pub fn borrow<const LOCKING: bool>(&self) -> DynamicManagedRef {
653 unsafe {
654 if LOCKING {
655 match &self.kind {
656 Kind::Owned { lifetime, data } => loop {
657 if let Some(lifetime) = lifetime.borrow() {
658 return DynamicManagedRef::new_raw(self.type_hash, lifetime, *data)
659 .expect("DynamicManagedGc cannot be immutably borrowed");
660 }
661 std::hint::spin_loop();
662 },
663 Kind::Referenced { lifetime, data } => loop {
664 if !lifetime.exists() {
665 panic!("DynamicManagedGc owner is dead");
666 }
667 if let Some(lifetime) = lifetime.borrow() {
668 return DynamicManagedRef::new_raw(self.type_hash, lifetime, *data)
669 .expect("DynamicManagedGc cannot be immutably borrowed");
670 }
671 std::hint::spin_loop();
672 },
673 }
674 } else {
675 match &self.kind {
676 Kind::Owned { lifetime, data } => DynamicManagedRef::new_raw(
677 self.type_hash,
678 lifetime
679 .borrow()
680 .expect("DynamicManagedGc is inaccessible for immutable borrowing"),
681 *data,
682 )
683 .expect("DynamicManagedGc cannot be immutably borrowed"),
684 Kind::Referenced { lifetime, data } => DynamicManagedRef::new_raw(
685 self.type_hash,
686 lifetime
687 .borrow()
688 .expect("DynamicManagedGc is inaccessible for immutable borrowing"),
689 *data,
690 )
691 .expect("DynamicManagedGc cannot be immutably borrowed"),
692 }
693 }
694 }
695 }
696
697 pub fn borrow_mut<const LOCKING: bool>(&mut self) -> DynamicManagedRefMut {
698 unsafe {
699 if LOCKING {
700 match &self.kind {
701 Kind::Owned { lifetime, data } => loop {
702 if let Some(lifetime) = lifetime.borrow_mut() {
703 return DynamicManagedRefMut::new_raw(self.type_hash, lifetime, *data)
704 .expect("DynamicManagedGc cannot be mutably borrowed");
705 }
706 std::hint::spin_loop();
707 },
708 Kind::Referenced { lifetime, data } => loop {
709 if !lifetime.exists() {
710 panic!("DynamicManagedGc owner is dead");
711 }
712 if let Some(lifetime) = lifetime.borrow_mut() {
713 return DynamicManagedRefMut::new_raw(self.type_hash, lifetime, *data)
714 .expect("DynamicManagedGc cannot be mutably borrowed");
715 }
716 std::hint::spin_loop();
717 },
718 }
719 } else {
720 match &self.kind {
721 Kind::Owned { lifetime, data } => DynamicManagedRefMut::new_raw(
722 self.type_hash,
723 lifetime
724 .borrow_mut()
725 .expect("DynamicManagedGc is inaccessible for mutable borrowing"),
726 *data,
727 )
728 .expect("DynamicManagedGc cannot be mutably borrowed"),
729 Kind::Referenced { lifetime, data } => DynamicManagedRefMut::new_raw(
730 self.type_hash,
731 lifetime
732 .borrow_mut()
733 .expect("DynamicManagedGc is inaccessible for mutable borrowing"),
734 *data,
735 )
736 .expect("DynamicManagedGc cannot be mutably borrowed"),
737 }
738 }
739 }
740 }
741
742 pub fn lazy(&self) -> DynamicManagedLazy {
743 unsafe {
744 match &self.kind {
745 Kind::Owned { lifetime, data } => {
746 DynamicManagedLazy::new_raw(self.type_hash, lifetime.lazy(), *data)
747 .expect("DynamicManagedGc cannot be lazily borrowed")
748 }
749 Kind::Referenced { lifetime, data } => {
750 DynamicManagedLazy::new_raw(self.type_hash, lifetime.clone(), *data)
751 .expect("DynamicManagedGc cannot be lazily borrowed")
752 }
753 }
754 }
755 }
756
757 pub unsafe fn as_ptr_raw(&self) -> *const u8 {
759 match &self.kind {
760 Kind::Owned { data, .. } => *data as *const u8,
761 Kind::Referenced { data, .. } => *data as *const u8,
762 }
763 }
764
765 pub unsafe fn as_mut_ptr_raw(&mut self) -> *mut u8 {
767 match &self.kind {
768 Kind::Owned { data, .. } => *data,
769 Kind::Referenced { data, .. } => *data,
770 }
771 }
772}
773
774impl TryFrom<DynamicManagedValue> for DynamicManagedGc {
775 type Error = ();
776
777 fn try_from(value: DynamicManagedValue) -> Result<Self, Self::Error> {
778 match value {
779 DynamicManagedValue::Gc(value) => Ok(value),
780 _ => Err(()),
781 }
782 }
783}
784
785#[cfg(test)]
786mod tests {
787 use super::*;
788
789 #[test]
790 fn test_is_async() {
791 fn is_async<T: Send + Sync>() {}
792
793 is_async::<ManagedGc<()>>();
794 is_async::<DynamicManagedGc>();
795 }
796
797 #[test]
798 fn test_managed_gc() {
799 let mut managed = ManagedGc::new(42);
800 {
801 let read_access = managed.read::<true>();
802 assert_eq!(*read_access, 42);
803 }
804 {
805 let mut write_access = managed.write::<true>();
806 *write_access = 100;
807 }
808 {
809 let read_access = managed.read::<true>();
810 assert_eq!(*read_access, 100);
811 }
812 }
813
814 #[test]
815 #[allow(unused)]
816 fn test_managed_gc_lifetimes() {
817 struct Car {
818 gear: i32,
819 engine: Option<ManagedGc<Engine>>,
820 }
821
822 struct Engine {
823 owning_car: Option<ManagedGc<Car>>,
824 horsepower: i32,
825 }
826
827 let mut car = ManagedGc::new(Car {
828 gear: 1,
829 engine: None,
830 });
831 let engine = ManagedGc::new(Engine {
832 owning_car: Some(car.reference()),
833 horsepower: 200,
834 });
835 let engine2 = engine.reference();
836 car.write::<true>().engine = Some(engine);
837
838 assert!(car.exists());
839 assert!(car.is_owning());
840 assert!(engine2.exists());
841 assert!(engine2.is_referencing());
842 assert!(engine2.is_owned_by(car.read::<true>().engine.as_ref().unwrap()));
843
844 let car2 = car.reference();
845 assert!(car2.exists());
846 assert!(car2.is_referencing());
847
848 drop(car);
849 assert!(!car2.exists());
850 assert!(car2.try_read().is_none());
851 assert!(!engine2.exists());
852 assert!(engine2.try_read().is_none());
853 }
854
855 #[test]
856 fn test_managed_gc_cycles() {
857 #[derive(Default)]
858 struct Foo {
859 other: Option<ManagedGc<Self>>,
860 }
861
862 {
863 let mut a = ManagedGc::<Foo>::default();
864 let mut b = ManagedGc::<Foo>::default();
865 a.write::<true>().other = Some(b.reference());
866 b.write::<true>().other = Some(a.reference());
867
868 assert!(a.exists());
869 assert!(a.is_owning());
870 assert!(a.read::<true>().other.as_ref().unwrap().is_referencing());
871 assert!(a.read::<true>().other.as_ref().unwrap().is_owned_by(&b));
872
873 assert!(b.exists());
874 assert!(b.is_owning());
875 assert!(b.read::<true>().other.as_ref().unwrap().is_referencing());
876 assert!(b.read::<true>().other.as_ref().unwrap().is_owned_by(&a));
877
878 drop(b);
879 assert!(!a.read::<true>().other.as_ref().unwrap().exists());
880 }
881
882 {
883 let mut a = ManagedGc::<Foo>::default();
884 a.write::<true>().other = Some(a.reference());
885
886 assert!(a.exists());
887 assert!(a.is_owning());
888 assert!(a.read::<true>().other.as_ref().unwrap().is_referencing());
889 assert!(a.read::<true>().other.as_ref().unwrap().is_owned_by(&a));
890 }
891 }
892
893 #[test]
894 fn test_dynamic_managed_gc() {
895 let mut managed = DynamicManagedGc::new(42);
896 {
897 let read_access = managed.read::<true, i32>();
898 assert_eq!(*read_access, 42);
899 }
900 {
901 let mut write_access = managed.write::<true, i32>();
902 *write_access = 100;
903 }
904 {
905 let read_access = managed.read::<true, i32>();
906 assert_eq!(*read_access, 100);
907 }
908 }
909
910 #[test]
911 fn test_dynamic_managed_gc_cycles() {
912 #[derive(Default)]
913 struct Foo {
914 other: Option<DynamicManagedGc>,
915 }
916
917 {
918 let mut a = DynamicManagedGc::new(Foo::default());
919 let mut b = DynamicManagedGc::new(Foo::default());
920 a.write::<true, Foo>().other = Some(b.reference());
921 b.write::<true, Foo>().other = Some(a.reference());
922
923 assert!(a.exists());
924 assert!(a.is_owning());
925 assert!(
926 a.read::<true, Foo>()
927 .other
928 .as_ref()
929 .unwrap()
930 .is_referencing()
931 );
932 assert!(
933 a.read::<true, Foo>()
934 .other
935 .as_ref()
936 .unwrap()
937 .is_owned_by(&b)
938 );
939
940 assert!(b.exists());
941 assert!(b.is_owning());
942 assert!(
943 b.read::<true, Foo>()
944 .other
945 .as_ref()
946 .unwrap()
947 .is_referencing()
948 );
949 assert!(
950 b.read::<true, Foo>()
951 .other
952 .as_ref()
953 .unwrap()
954 .is_owned_by(&a)
955 );
956
957 drop(b);
958 assert!(!a.read::<true, Foo>().other.as_ref().unwrap().exists());
959 }
960
961 {
962 let mut a = DynamicManagedGc::new(Foo::default());
963 a.write::<true, Foo>().other = Some(a.reference());
964
965 assert!(a.exists());
966 assert!(a.is_owning());
967 assert!(
968 a.read::<true, Foo>()
969 .other
970 .as_ref()
971 .unwrap()
972 .is_referencing()
973 );
974 assert!(
975 a.read::<true, Foo>()
976 .other
977 .as_ref()
978 .unwrap()
979 .is_owned_by(&a)
980 );
981 }
982 }
983
984 #[test]
985 fn test_managed_gc_conversions() {
986 let managed = ManagedGc::new(42);
987 assert_eq!(*managed.read::<true>(), 42);
988
989 let mut dynamic = managed.into_dynamic();
990 *dynamic.write::<true, i32>() = 100;
991
992 let managed = dynamic.into_typed::<i32>();
993 assert_eq!(*managed.read::<true>(), 100);
994 }
995
996 #[test]
997 fn test_managed_gc_dead_owner() {
998 let a = ManagedGc::new(42);
999 let mut b = a.reference();
1000
1001 assert!(a.exists());
1002 assert!(b.exists());
1003 assert_eq!(*b.read::<true>(), 42);
1004
1005 drop(a);
1006 assert!(!b.exists());
1007 assert!(b.try_write().is_none());
1008 }
1009
1010 #[test]
1011 #[should_panic]
1012 fn test_managed_gc_dead_owner_panic() {
1013 let a = ManagedGc::new(42);
1014 let mut b = a.reference();
1015
1016 assert!(a.exists());
1017 assert!(b.exists());
1018 assert_eq!(*b.read::<true>(), 42);
1019
1020 drop(a);
1021 assert!(!b.exists());
1022 assert_eq!(*b.write::<true>(), 42);
1023 }
1024
1025 #[test]
1026 fn test_managed_gc_cyclic() {
1027 struct SelfReferencial {
1028 value: i32,
1029 this: ManagedGc<SelfReferencial>,
1030 }
1031
1032 let v = unsafe { ManagedGc::new_cyclic(|this| SelfReferencial { value: 42, this }) };
1033 assert_eq!(v.read::<true>().value, 42);
1034 let this = v.read::<true>().this.reference();
1035 assert_eq!(this.read::<true>().value, 42);
1036 }
1037
1038 #[test]
1039 fn test_managed_gc_transfer_ownership() {
1040 let mut a = ManagedGc::new(42);
1041 let mut b = a.reference();
1042
1043 assert!(!a.is_owned_by(&b));
1044 assert!(b.is_owned_by(&a));
1045 assert!(!b.transfer_ownership(&mut a));
1046 assert!(a.transfer_ownership(&mut b));
1047 assert!(a.is_owned_by(&b));
1048 assert!(!b.is_owned_by(&a));
1049 drop(b);
1050 assert!(!a.exists());
1051 }
1052}