pub struct ContainerLockGuard {
sources: Vec<(ContainerId, ContainerRef)>,
guards: Vec<(ContainerId, LockedContainer)>,
id_to_index: FxHashMap<ContainerId, usize>,
}Expand description
A guard that holds locks on multiple containers in a deterministic order.
This struct ensures that when multiple containers need to be locked simultaneously, they are always locked in the same order (by pointer address) to prevent deadlocks.
§Example
let player_inv = ContainerRef::from(player_inv_arc);
let chest = ContainerRef::from(chest_arc);
let mut guard = ContainerLockGuard::lock_all(&[&player_inv, &chest]);
// Access containers by their IDs
let player_id = player_inv.container_id();
if let Some(inv) = guard.get_mut(player_id) {
// Modify the player inventory
}Fields§
§sources: Vec<(ContainerId, ContainerRef)>§guards: Vec<(ContainerId, LockedContainer)>§id_to_index: FxHashMap<ContainerId, usize>Implementations§
Source§impl ContainerLockGuard
impl ContainerLockGuard
Sourcepub fn lock_all<C>(containers: &[C]) -> Selfwhere
C: Borrow<ContainerRef>,
pub fn lock_all<C>(containers: &[C]) -> Selfwhere
C: Borrow<ContainerRef>,
Create a new lock guard and lock all containers in deterministic order.
Containers are sorted by their pointer address before locking to ensure a consistent lock order across all call sites, preventing deadlocks. Duplicate containers (same Arc) are automatically deduplicated.
Sourcepub fn get_disjoint_mut<const N: usize>(
&mut self,
ids: [ContainerId; N],
) -> Option<[&mut dyn Container; N]>
pub fn get_disjoint_mut<const N: usize>( &mut self, ids: [ContainerId; N], ) -> Option<[&mut dyn Container; N]>
Get mutable access to N locked containers simultaneously
Returns None if any ID is not locked or if any IDs are duplicates
Sourcepub fn relock(self, containers: &[&ContainerRef]) -> Self
pub fn relock(self, containers: &[&ContainerRef]) -> Self
Unlock all containers and relock with a new set.
This should only be called when you need to add more containers
mid-operation. All existing references from get()/get_mut() are invalidated.
Sourcepub fn get(&self, id: impl Into<ContainerId>) -> Option<&dyn Container>
pub fn get(&self, id: impl Into<ContainerId>) -> Option<&dyn Container>
Get immutable access to a locked container.
Sourcepub fn get_mut(
&mut self,
id: impl Into<ContainerId>,
) -> Option<&mut dyn Container>
pub fn get_mut( &mut self, id: impl Into<ContainerId>, ) -> Option<&mut dyn Container>
Get mutable access to a locked container.
This bypasses owner notification and is only for deliberate no-update mutation or callers that establish the notification boundary separately.
Sourcepub fn set_item(
&mut self,
id: impl Into<ContainerId>,
slot: usize,
stack: ItemStack,
) -> bool
pub fn set_item( &mut self, id: impl Into<ContainerId>, slot: usize, stack: ItemStack, ) -> bool
Mirrors a container’s own setItem call.
Vanilla block-entity containers call BlockEntity::setChanged from
setItem, before a Slot::set performs its separate notification.
Sourcepub fn remove_item(
&mut self,
id: impl Into<ContainerId>,
slot: usize,
amount: i32,
) -> Option<ItemStack>
pub fn remove_item( &mut self, id: impl Into<ContainerId>, slot: usize, amount: i32, ) -> Option<ItemStack>
Mirrors a container’s own conditional removeItem notification.
Sourcepub fn set_changed(&mut self, id: impl Into<ContainerId>) -> bool
pub fn set_changed(&mut self, id: impl Into<ContainerId>) -> bool
Calls Container::set_changed and synchronously notifies its owner
after releasing every lock held by this guard.
Sourcepub(crate) fn run_unlocked<R>(&mut self, callback: impl FnOnce() -> R) -> R
pub(crate) fn run_unlocked<R>(&mut self, callback: impl FnOnce() -> R) -> R
Runs a callback after releasing every container, then reacquires the same sources in deterministic order before returning.
fn notify_owner(&mut self, owner: Option<Arc<BlockEntityBase>>)
Sourcepub fn get_typed<T>(&self, id: impl Into<ContainerId>) -> Option<&T>where
T: Container + DowncastType,
pub fn get_typed<T>(&self, id: impl Into<ContainerId>) -> Option<&T>where
T: Container + DowncastType,
Gets immutable access when the locked container has concrete type T.
Sourcepub fn get_typed_mut<T>(&mut self, id: impl Into<ContainerId>) -> Option<&mut T>where
T: Container + DowncastType,
pub fn get_typed_mut<T>(&mut self, id: impl Into<ContainerId>) -> Option<&mut T>where
T: Container + DowncastType,
Gets mutable access when the locked container has concrete type T.
This bypasses owner notification and is only for deliberate no-update mutation or callers that establish the notification boundary separately.
Sourcepub fn get_two_typed_mut<A, B>(
&mut self,
first: impl Into<ContainerId>,
second: impl Into<ContainerId>,
) -> Option<(&mut A, &mut B)>
pub fn get_two_typed_mut<A, B>( &mut self, first: impl Into<ContainerId>, second: impl Into<ContainerId>, ) -> Option<(&mut A, &mut B)>
Gets mutable access to two distinct concrete containers.
This bypasses owner notification and is only for deliberate no-update mutation or callers that establish the notification boundary separately.
Sourcepub fn contains(&self, id: ContainerId) -> bool
pub fn contains(&self, id: ContainerId) -> bool
Check if a container is locked.
Auto Trait Implementations§
impl !RefUnwindSafe for ContainerLockGuard
impl !Send for ContainerLockGuard
impl !UnwindSafe for ContainerLockGuard
impl Freeze for ContainerLockGuard
impl Sync for ContainerLockGuard
impl Unpin for ContainerLockGuard
impl UnsafeUnpin for ContainerLockGuard
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreArc<SyncMutex<>>