1//! Module containing the [`WeakVec`] API.
23use alloc::{sync::Weak, vec::Vec};
45/// An optimized container for `Weak` references of `T` that minimizes reallocations by
6/// dropping older elements that no longer have strong references to them.
7#[derive(Debug)]
8pub(crate) struct WeakVec<T> {
9 inner: Vec<Weak<T>>,
10}
1112impl<T> Default for WeakVec<T> {
13fn default() -> Self {
14Self {
15 inner: Default::default(),
16 }
17 }
18}
1920impl<T> WeakVec<T> {
21pub(crate) fn new() -> Self {
22Self { inner: Vec::new() }
23 }
2425/// Pushes a new element to this collection.
26 ///
27 /// If the inner Vec needs to be reallocated, we will first drop older elements that
28 /// no longer have strong references to them.
29pub(crate) fn push(&mut self, value: Weak<T>) {
30if self.inner.len() == self.inner.capacity() {
31// Iterating backwards has the advantage that we don't do more work than we have to.
32for i in (0..self.inner.len()).rev() {
33if self.inner[i].strong_count() == 0 {
34self.inner.swap_remove(i);
35 }
36 }
3738// Make sure our capacity is twice the number of live elements.
39 // Leaving some spare capacity ensures that we won't re-scan immediately.
40self.inner.reserve_exact(self.inner.len());
41 }
4243self.inner.push(value);
44 }
45}
4647pub(crate) struct WeakVecIter<T> {
48 inner: alloc::vec::IntoIter<Weak<T>>,
49}
5051impl<T> Iterator for WeakVecIter<T> {
52type Item = Weak<T>;
53fn next(&mut self) -> Option<Self::Item> {
54self.inner.next()
55 }
56}
5758impl<T> IntoIterator for WeakVec<T> {
59type Item = Weak<T>;
60type IntoIter = WeakVecIter<T>;
61fn into_iter(self) -> Self::IntoIter {
62 WeakVecIter {
63 inner: self.inner.into_iter(),
64 }
65 }
66}