mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-28 17:53:40 +00:00
[WeakVec] scan all weak references only before a reallocation would happen
This commit is contained in:
parent
8ba5c82831
commit
f669024eeb
@ -2,45 +2,55 @@
|
|||||||
|
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
|
|
||||||
/// A container that holds Weak references of T.
|
/// An optimized container for `Weak` references of `T` that minimizes reallocations by
|
||||||
///
|
/// dropping older elements that no longer have strong references to them.
|
||||||
/// On `push` it scans its contents for weak references with no strong references still alive and drops them.
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct WeakVec<T> {
|
pub(crate) struct WeakVec<T> {
|
||||||
inner: Vec<Option<Weak<T>>>,
|
inner: Vec<Option<Weak<T>>>,
|
||||||
|
empty_slots: Vec<usize>,
|
||||||
|
scan_slots_on_next_push: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Default for WeakVec<T> {
|
impl<T> Default for WeakVec<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Default::default(),
|
inner: Default::default(),
|
||||||
|
empty_slots: Default::default(),
|
||||||
|
scan_slots_on_next_push: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> WeakVec<T> {
|
impl<T> WeakVec<T> {
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
Self { inner: Vec::new() }
|
Self {
|
||||||
|
inner: Vec::new(),
|
||||||
|
empty_slots: Vec::default(),
|
||||||
|
scan_slots_on_next_push: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes a new element to this collection, dropping older elements that no longer have
|
/// Pushes a new element to this collection.
|
||||||
/// a strong reference to them.
|
|
||||||
///
|
///
|
||||||
/// NOTE: The length and capacity of this collection do not change when old elements are
|
/// If the inner Vec needs to be reallocated, we will first drop older elements that
|
||||||
/// dropped.
|
/// no longer have strong references to them.
|
||||||
pub(crate) fn push(&mut self, value: Weak<T>) {
|
pub(crate) fn push(&mut self, value: Weak<T>) {
|
||||||
let mut to_insert = Some(value);
|
if self.scan_slots_on_next_push {
|
||||||
for slot in &mut self.inner {
|
for (i, value) in self.inner.iter_mut().enumerate() {
|
||||||
if let Some(w) = slot {
|
if let Some(w) = value {
|
||||||
if w.strong_count() == 0 {
|
if w.strong_count() == 0 {
|
||||||
*slot = to_insert.take();
|
*value = None;
|
||||||
|
self.empty_slots.push(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
*slot = to_insert.take();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(to_insert) = to_insert {
|
if let Some(i) = self.empty_slots.pop() {
|
||||||
self.inner.push(Some(to_insert));
|
self.inner[i] = Some(value);
|
||||||
|
self.scan_slots_on_next_push = false;
|
||||||
|
} else {
|
||||||
|
self.inner.push(Some(value));
|
||||||
|
self.scan_slots_on_next_push = self.inner.len() == self.inner.capacity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user