Skip to content

Commit

Permalink
IdentityManager: from_index method is unneeded.
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
jimblandy committed Jan 27, 2022
1 parent 77b2c25 commit fb422af
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 14 deletions.
2 changes: 1 addition & 1 deletion player/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl<I: Clone + Debug + wgc::id::TypedId> wgc::hub::IdentityHandlerFactory<I>
for IdentityPassThroughFactory
{
type Filter = IdentityPassThrough<I>;
fn spawn(&self, _min_index: u32) -> Self::Filter {
fn spawn(&self) -> Self::Filter {
IdentityPassThrough(PhantomData)
}
}
Expand Down
48 changes: 35 additions & 13 deletions wgpu-core/src/hub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Index>,

/// 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<Epoch>,
}

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<I: id::TypedId>(&mut self, backend: Backend) -> I {
match self.free.pop() {
Some(index) => I::zip(index, self.epochs[index as usize], backend),
Expand All @@ -43,6 +64,7 @@ impl IdentityManager {
}
}

/// Free `id`. It will never be returned from `alloc` again.
pub fn free<I: id::TypedId + Debug>(&mut self, id: I) {
let (index, epoch, _backend) = id.unzip();
let pe = &mut self.epochs[index as usize];
Expand Down Expand Up @@ -361,16 +383,16 @@ impl<I: id::TypedId + Debug> IdentityHandler<I> for Mutex<IdentityManager> {

pub trait IdentityHandlerFactory<I> {
type Filter: IdentityHandler<I>;
fn spawn(&self, min_index: Index) -> Self::Filter;
fn spawn(&self) -> Self::Filter;
}

#[derive(Debug)]
pub struct IdentityManagerFactory;

impl<I: id::TypedId + Debug> IdentityHandlerFactory<I> for IdentityManagerFactory {
type Filter = Mutex<IdentityManager>;
fn spawn(&self, min_index: Index) -> Self::Filter {
Mutex::new(IdentityManager::from_index(min_index))
fn spawn(&self) -> Self::Filter {
Mutex::new(IdentityManager::default())
}
}

Expand Down Expand Up @@ -419,7 +441,7 @@ pub struct Registry<T: Resource, I: id::TypedId, F: IdentityHandlerFactory<I>> {
impl<T: Resource, I: id::TypedId, F: IdentityHandlerFactory<I>> Registry<T, I, F> {
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,
Expand All @@ -431,7 +453,7 @@ impl<T: Resource, I: id::TypedId, F: IdentityHandlerFactory<I>> Registry<T, I, F

fn without_backend(factory: &F, kind: &'static str) -> Self {
Self {
identity: factory.spawn(1),
identity: factory.spawn(),
data: RwLock::new(Storage {
map: Vec::new(),
kind,
Expand Down
5 changes: 5 additions & 0 deletions wgpu-core/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ impl<T> Ord for Id<T> {
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub(crate) struct Valid<I>(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);
Expand Down

0 comments on commit fb422af

Please sign in to comment.