boa_gc/pointers/
weak.rs

1use crate::{Ephemeron, Finalize, Gc, Trace};
2use std::hash::{Hash, Hasher};
3
4/// A weak reference to a [`Gc`].
5///
6/// This type allows keeping references to [`Gc`] managed values without keeping them alive for
7/// garbage collections. However, this also means [`WeakGc::upgrade`] could return `None` at any moment.
8#[derive(Debug, Trace, Finalize)]
9#[repr(transparent)]
10pub struct WeakGc<T: Trace + ?Sized + 'static> {
11    inner: Ephemeron<T, ()>,
12}
13
14impl<T: Trace + ?Sized> WeakGc<T> {
15    /// Creates a new weak pointer for a garbage collected value.
16    #[inline]
17    #[must_use]
18    pub fn new(value: &Gc<T>) -> Self {
19        Self {
20            inner: Ephemeron::new(value, ()),
21        }
22    }
23
24    /// Upgrade returns a `Gc` pointer for the internal value if the pointer is still live, or `None`
25    /// if the value was already garbage collected.
26    #[inline]
27    #[must_use]
28    pub fn upgrade(&self) -> Option<Gc<T>> {
29        self.inner.key()
30    }
31
32    /// Check if the [`WeakGc`] can be upgraded.
33    #[inline]
34    #[must_use]
35    pub fn is_upgradable(&self) -> bool {
36        self.inner.has_value()
37    }
38
39    #[must_use]
40    pub(crate) const fn inner(&self) -> &Ephemeron<T, ()> {
41        &self.inner
42    }
43}
44
45impl<T: Trace> Clone for WeakGc<T> {
46    fn clone(&self) -> Self {
47        Self {
48            inner: self.inner.clone(),
49        }
50    }
51}
52
53impl<T: Trace> From<Ephemeron<T, ()>> for WeakGc<T> {
54    fn from(inner: Ephemeron<T, ()>) -> Self {
55        Self { inner }
56    }
57}
58
59impl<T: Trace> PartialEq for WeakGc<T> {
60    fn eq(&self, other: &Self) -> bool {
61        match (self.upgrade(), other.upgrade()) {
62            (Some(a), Some(b)) => std::ptr::eq(a.as_ref(), b.as_ref()),
63            _ => false,
64        }
65    }
66}
67
68impl<T: Trace> Eq for WeakGc<T> {}
69
70impl<T: Trace> Hash for WeakGc<T> {
71    fn hash<H: Hasher>(&self, state: &mut H) {
72        if let Some(obj) = self.upgrade() {
73            std::ptr::hash(obj.as_ref(), state);
74        } else {
75            std::ptr::hash(self, state);
76        }
77    }
78}