PyMutex

Struct PyMutex 

Source
pub struct PyMutex<T: ?Sized> { /* private fields */ }
Expand description

Wrapper for PyMutex, exposing an RAII guard interface.

Compared with std::sync::Mutex or parking_lot::Mutex, this is a very stripped-down locking primitive that only supports blocking lock and unlock operations and does not support try_lock or APIs that depend on try_lock. For this reason, it is not possible to avoid the possibility of possibly blocking when calling lock and extreme care must be taken to avoid introducing a deadlock.

This type is most useful when arbitrary Python code might execute while the lock is held. On the GIL-enabled build, PyMutex will release the GIL if the thread is blocked on acquiring the lock. On the free-threaded build, threads blocked on acquiring a PyMutex will not prevent the garbage collector from running.

§Poisoning

Like std::sync::Mutex, PyMutex implements poisoning. A mutex is considered poisoned whenever a thread panics while holding the mutex. Once a mutex is poisoned, all other threads are unable to access the data by default as it is likely to be tainted (some invariant is not being held).

This means that the lock method returns a Result which indicated whether the mutex has been poisoned or not. Must usage will simple unwrap() these results, propagating panics among threads to ensure a possible invalid invariant is not being observed.

A poisoned mutex, however, does not prevent all access to the underlying data. The PoisonError type has an into_inner method which will return the guard that would have otherwise been returned on a successful lock. This allows access to the data, despite the lock being poisoned.

Implementations§

Source§

impl<T> PyMutex<T>

Source

pub fn lock(&self) -> LockResult<PyMutexGuard<'_, T>>

Acquire the mutex, blocking the current thread until it is able to do so.

Source

pub const fn new(value: T) -> Self

Create a new mutex in an unlocked state ready for use.

Source

pub fn is_locked(&self) -> bool

Check if the mutex is locked.

Note that this is only useful for debugging or test purposes and should not be used to make concurrency control decisions, as the lock state may change immediately after the check.

Source

pub fn into_inner(self) -> LockResult<T>
where T: Sized,

Consumes this mutex, returning the underlying data.

§Errors

If another user of this mutex panicked while holding the mutex, then this call will return an error containing the underlying data instead.

Source

pub fn clear_poison(&self)

Clear the poisoned state from a mutex.

If the mutex is poisoned, it will remain poisoned until this function is called. This allows recovering from a poisoned state and marking that it has recovered. For example, if the value is overwritten by a known-good value, then the mutex can be marked as un-poisoned. Or possibly, the value could be inspected to determine if it is in a consistent state, and if so the poison is removed.

Trait Implementations§

Source§

impl<T: ?Sized + Send> Send for PyMutex<T>

T must be Send for a PyMutex to be Send because it is possible to acquire the owned T from the PyMutex via into_inner.

Source§

impl<T: ?Sized + Send> Sync for PyMutex<T>

T must be Send for PyMutex to be Sync. This ensures that the protected data can be accessed safely from multiple threads without causing data races or other unsafe behavior.

PyMutex<T> provides mutable access to T to one thread at a time. However, it’s essential for T to be Send because it’s not safe for non-Send structures to be accessed in this manner. For instance, consider Rc, a non-atomic reference counted smart pointer, which is not Send. With Rc, we can have multiple copies pointing to the same heap allocation with a non-atomic reference count. If we were to use Mutex<Rc<_>>, it would only protect one instance of Rc from shared access, leaving other copies vulnerable to potential data races.

Also note that it is not necessary for T to be Sync as &T is only made available to one thread at a time if T is not Sync.

Auto Trait Implementations§

§

impl<T> !Freeze for PyMutex<T>

§

impl<T> !RefUnwindSafe for PyMutex<T>

§

impl<T> Unpin for PyMutex<T>
where T: Unpin + ?Sized,

§

impl<T> UnwindSafe for PyMutex<T>
where T: UnwindSafe + ?Sized,

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.

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, 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.
Source§

impl<T> Ungil for T
where T: Send,