wgpu_core/
weak_vec.rs

1//! Module containing the [`WeakVec`] API.
2
3use alloc::{sync::Weak, vec::Vec};
4
5/// 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}
11
12impl<T> Default for WeakVec<T> {
13    fn default() -> Self {
14        Self {
15            inner: Default::default(),
16        }
17    }
18}
19
20impl<T> WeakVec<T> {
21    pub(crate) fn new() -> Self {
22        Self { inner: Vec::new() }
23    }
24
25    pub(crate) fn iter(&self) -> impl Iterator<Item = &Weak<T>> {
26        self.inner.iter()
27    }
28
29    /// Pushes a new element to this collection.
30    ///
31    /// If the inner Vec needs to be reallocated, we will first drop older elements that
32    /// no longer have strong references to them.
33    pub(crate) fn push(&mut self, value: Weak<T>) {
34        if self.inner.len() == self.inner.capacity() {
35            // Iterating backwards has the advantage that we don't do more work than we have to.
36            for i in (0..self.inner.len()).rev() {
37                if self.inner[i].strong_count() == 0 {
38                    self.inner.swap_remove(i);
39                }
40            }
41
42            // Make sure our capacity is twice the number of live elements.
43            // Leaving some spare capacity ensures that we won't re-scan immediately.
44            self.inner.reserve_exact(self.inner.len());
45        }
46
47        self.inner.push(value);
48    }
49}
50
51pub(crate) struct WeakVecIter<T> {
52    inner: alloc::vec::IntoIter<Weak<T>>,
53}
54
55impl<T> Iterator for WeakVecIter<T> {
56    type Item = Weak<T>;
57    fn next(&mut self) -> Option<Self::Item> {
58        self.inner.next()
59    }
60}
61
62impl<T> IntoIterator for WeakVec<T> {
63    type Item = Weak<T>;
64    type IntoIter = WeakVecIter<T>;
65    fn into_iter(self) -> Self::IntoIter {
66        WeakVecIter {
67            inner: self.inner.into_iter(),
68        }
69    }
70}