From fb422af6633f51ea98bc36abdea70440ccb4da0b Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Wed, 26 Jan 2022 21:49:47 -0800 Subject: [PATCH] IdentityManager: `from_index` method is unneeded. The `min_index` parameter has no useful effect. Because the range 0..n is pushed on the free list, index values less than `min_index` do get allocated. Document `IdentityManager` and `TypedId`. --- player/src/lib.rs | 2 +- wgpu-core/src/hub.rs | 48 ++++++++++++++++++++++++++++++++------------ wgpu-core/src/id.rs | 5 +++++ 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/player/src/lib.rs b/player/src/lib.rs index 1cb42e7c35c..dffb7c069d9 100644 --- a/player/src/lib.rs +++ b/player/src/lib.rs @@ -28,7 +28,7 @@ impl wgc::hub::IdentityHandlerFactory for IdentityPassThroughFactory { type Filter = IdentityPassThrough; - fn spawn(&self, _min_index: u32) -> Self::Filter { + fn spawn(&self) -> Self::Filter { IdentityPassThrough(PhantomData) } } diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 2f78ab5faf7..9f11ddfbd09 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -16,21 +16,42 @@ use wgt::Backend; use std::cell::Cell; use std::{fmt::Debug, marker::PhantomData, mem, ops}; -/// A simple structure to manage identities of objects. +/// A simple structure to allocate [`Id`] identifiers. +/// +/// Calling [`alloc`] returns a fresh, never-before-seen id. Calling [`free`] +/// marks an id as dead; it will never be returned again by `alloc`. +/// +/// Use `IdentityManager::default` to construct new instances. +/// +/// The index values of `Id`s allocated by an `IdentityManager` are suitable for +/// use as indices into a vector of information about the ids' referents. The +/// `alloc` method returns an id with a given index only if there is some extant +/// live id with a higher index (so your vector needs to be at least that large +/// anyway), or all lower non-negative index values are currently in use by +/// other live ids (so all entries in your vector are full). +/// +/// [`Id`]: crate::id::Id +/// [`Backend`]: wgt::Backend; +/// [`alloc`]: IdentityManager::alloc +/// [`free`]: IdentityManager::free #[derive(Debug, Default)] pub struct IdentityManager { + /// Available index values. If empty, then `epochs.len()` is the next index + /// to allocate. free: Vec, + + /// The next or currently-live epoch value associated with each `Id` index. + /// + /// If there is a live id with index `i`, then `epochs[i]` is its epoch; any + /// id with the same index but an older epoch is dead. + /// + /// If index `i` is currently unused, `epochs[i]` is the epoch to use in its + /// next `Id`. epochs: Vec, } impl IdentityManager { - pub fn from_index(min_index: u32) -> Self { - Self { - free: (0..min_index).collect(), - epochs: vec![1; min_index as usize], - } - } - + /// Allocate a fresh, never-before-seen [`Id`] with the given `backend`. pub fn alloc(&mut self, backend: Backend) -> I { match self.free.pop() { Some(index) => I::zip(index, self.epochs[index as usize], backend), @@ -43,6 +64,7 @@ impl IdentityManager { } } + /// Free `id`. It will never be returned from `alloc` again. pub fn free(&mut self, id: I) { let (index, epoch, _backend) = id.unzip(); let pe = &mut self.epochs[index as usize]; @@ -361,7 +383,7 @@ impl IdentityHandler for Mutex { pub trait IdentityHandlerFactory { type Filter: IdentityHandler; - fn spawn(&self, min_index: Index) -> Self::Filter; + fn spawn(&self) -> Self::Filter; } #[derive(Debug)] @@ -369,8 +391,8 @@ pub struct IdentityManagerFactory; impl IdentityHandlerFactory for IdentityManagerFactory { type Filter = Mutex; - fn spawn(&self, min_index: Index) -> Self::Filter { - Mutex::new(IdentityManager::from_index(min_index)) + fn spawn(&self) -> Self::Filter { + Mutex::new(IdentityManager::default()) } } @@ -419,7 +441,7 @@ pub struct Registry> { impl> Registry { fn new(backend: Backend, factory: &F) -> Self { Self { - identity: factory.spawn(0), + identity: factory.spawn(), data: RwLock::new(Storage { map: Vec::new(), kind: T::TYPE, @@ -431,7 +453,7 @@ impl> Registry Self { Self { - identity: factory.spawn(1), + identity: factory.spawn(), data: RwLock::new(Storage { map: Vec::new(), kind, diff --git a/wgpu-core/src/id.rs b/wgpu-core/src/id.rs index d102eb61834..e75d5278c66 100644 --- a/wgpu-core/src/id.rs +++ b/wgpu-core/src/id.rs @@ -114,6 +114,11 @@ impl Ord for Id { #[cfg_attr(feature = "replay", derive(serde::Deserialize))] pub(crate) struct Valid(pub I); +/// Trait carrying methods for direct `Id` access. +/// +/// Most `wgpu-core` clients should not use this trait. Unusual clients that +/// need to construct `Id` values directly, or access their components, like the +/// WGPU recording player, may use this trait to do so. pub trait TypedId { fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self; fn unzip(self) -> (Index, Epoch, Backend);