Skip to main content

ContainerLockGuard

Struct ContainerLockGuard 

Source
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

Source

pub fn lock_all<C>(containers: &[C]) -> Self
where 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.

Source

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

Source

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.

Source

pub fn get(&self, id: impl Into<ContainerId>) -> Option<&dyn Container>

Get immutable access to a locked container.

Source

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.

Source

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.

Source

pub fn remove_item( &mut self, id: impl Into<ContainerId>, slot: usize, amount: i32, ) -> Option<ItemStack>

Mirrors a container’s own conditional removeItem notification.

Source

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.

Source

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.

Source

fn notify_owner(&mut self, owner: Option<Arc<BlockEntityBase>>)

Source

pub fn get_typed<T>(&self, id: impl Into<ContainerId>) -> Option<&T>

Gets immutable access when the locked container has concrete type T.

Source

pub fn get_typed_mut<T>(&mut self, id: impl Into<ContainerId>) -> Option<&mut T>

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.

Source

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.

Source

pub fn contains(&self, id: ContainerId) -> bool

Check if a container is locked.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> IntoShared for T

Source§

fn into_shared(self) -> Arc<Mutex<RawMutex, Self>>

Wraps this value in an Arc<SyncMutex<>>
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more