WeakDynamic<T>

This commit is contained in:
Jonathan Johnson 2023-12-02 07:05:18 -08:00
parent 9ee00106a3
commit d1e21178e0
No known key found for this signature in database
GPG key ID: A66D6A34D6620579

View file

@ -8,7 +8,7 @@ use std::ops::{Deref, DerefMut, Not};
use std::panic::UnwindSafe;
use std::str::FromStr;
use std::sync::atomic::{self, AtomicBool};
use std::sync::{Arc, Mutex, MutexGuard, TryLockError};
use std::sync::{Arc, Mutex, MutexGuard, TryLockError, Weak};
use std::task::{Poll, Waker};
use std::thread::ThreadId;
use std::time::Duration;
@ -50,6 +50,15 @@ impl<T> Dynamic<T> {
}))
}
/// Returns a weak reference to this dynamic.
///
/// This is powered by [`Arc`]/[`Weak`] and follows the same semantics for
/// reference counting.
#[must_use]
pub fn downgrade(&self) -> WeakDynamic<T> {
WeakDynamic::from(self)
}
/// Returns a new dynamic that has its contents linked with `self` by the
/// pair of mapping functions provided.
///
@ -1104,6 +1113,59 @@ impl<T> Drop for DynamicGuard<'_, T> {
}
}
/// A weak reference to a [`Dynamic`].
///
/// This is powered by [`Arc`]/[`Weak`] and follows the same semantics for
/// reference counting.
pub struct WeakDynamic<T>(Weak<DynamicData<T>>);
impl<T> WeakDynamic<T> {
/// Returns the [`Dynamic`] this weak reference points to, unless no
/// remaining [`Dynamic`] instances exist for the underlying value.
#[must_use]
pub fn upgrade(&self) -> Option<Dynamic<T>> {
self.0.upgrade().map(Dynamic)
}
}
impl<'a, T> From<&'a Dynamic<T>> for WeakDynamic<T> {
fn from(value: &'a Dynamic<T>) -> Self {
Self(Arc::downgrade(&value.0))
}
}
impl<T> From<Dynamic<T>> for WeakDynamic<T> {
fn from(value: Dynamic<T>) -> Self {
Self::from(&value)
}
}
impl<T> Clone for WeakDynamic<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T> Eq for WeakDynamic<T> {}
impl<T> PartialEq for WeakDynamic<T> {
fn eq(&self, other: &Self) -> bool {
Weak::ptr_eq(&self.0, &other.0)
}
}
impl<T> PartialEq<Dynamic<T>> for WeakDynamic<T> {
fn eq(&self, other: &Dynamic<T>) -> bool {
Weak::as_ptr(&self.0) == Arc::as_ptr(&other.0)
}
}
impl<T> PartialEq<WeakDynamic<T>> for Dynamic<T> {
fn eq(&self, other: &WeakDynamic<T>) -> bool {
Arc::as_ptr(&self.0) == Weak::as_ptr(&other.0)
}
}
/// A reader that tracks the last generation accessed through this reader.
#[derive(Debug)]
pub struct DynamicReader<T> {