mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00

StaticMutex is only ever used with as a static (as the name already suggests). So it doesn't have to be generic over a lifetime, but can simply assume 'static. This 'static lifetime guarantees the object is never moved, so this is no longer a manually checked requirement for unsafe calls to lock().
101 lines
2.6 KiB
Rust
101 lines
2.6 KiB
Rust
use crate::sys::mutex as imp;
|
|
|
|
/// An OS-based mutual exclusion lock, meant for use in static variables.
|
|
///
|
|
/// This mutex has a const constructor ([`StaticMutex::new`]), does not
|
|
/// implement `Drop` to cleanup resources, and causes UB when used reentrantly.
|
|
///
|
|
/// This mutex does not implement poisoning.
|
|
///
|
|
/// This is a wrapper around `imp::Mutex` that does *not* call `init()` and
|
|
/// `destroy()`.
|
|
pub struct StaticMutex(imp::Mutex);
|
|
|
|
unsafe impl Sync for StaticMutex {}
|
|
|
|
impl StaticMutex {
|
|
/// Creates a new mutex for use.
|
|
pub const fn new() -> Self {
|
|
Self(imp::Mutex::new())
|
|
}
|
|
|
|
/// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
|
|
/// will be unlocked.
|
|
///
|
|
/// It is undefined behaviour to call this function while locked by the
|
|
/// same thread.
|
|
#[inline]
|
|
pub unsafe fn lock(&'static self) -> StaticMutexGuard {
|
|
self.0.lock();
|
|
StaticMutexGuard(&self.0)
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub struct StaticMutexGuard(&'static imp::Mutex);
|
|
|
|
impl Drop for StaticMutexGuard {
|
|
#[inline]
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
self.0.unlock();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// An OS-based mutual exclusion lock.
|
|
///
|
|
/// This mutex does *not* have a const constructor, cleans up its resources in
|
|
/// its `Drop` implementation, may safely be moved (when not borrowed), and
|
|
/// does not cause UB when used reentrantly.
|
|
///
|
|
/// This mutex does not implement poisoning.
|
|
///
|
|
/// This is either a wrapper around `Box<imp::Mutex>` or `imp::Mutex`,
|
|
/// depending on the platform. It is boxed on platforms where `imp::Mutex` may
|
|
/// not be moved.
|
|
pub struct MovableMutex(imp::MovableMutex);
|
|
|
|
unsafe impl Sync for MovableMutex {}
|
|
|
|
impl MovableMutex {
|
|
/// Creates a new mutex.
|
|
pub fn new() -> Self {
|
|
let mut mutex = imp::MovableMutex::from(imp::Mutex::new());
|
|
unsafe { mutex.init() };
|
|
Self(mutex)
|
|
}
|
|
|
|
pub(super) fn raw(&self) -> &imp::Mutex {
|
|
&self.0
|
|
}
|
|
|
|
/// Locks the mutex blocking the current thread until it is available.
|
|
#[inline]
|
|
pub fn raw_lock(&self) {
|
|
unsafe { self.0.lock() }
|
|
}
|
|
|
|
/// Attempts to lock the mutex without blocking, returning whether it was
|
|
/// successfully acquired or not.
|
|
#[inline]
|
|
pub fn try_lock(&self) -> bool {
|
|
unsafe { self.0.try_lock() }
|
|
}
|
|
|
|
/// Unlocks the mutex.
|
|
///
|
|
/// Behavior is undefined if the current thread does not actually hold the
|
|
/// mutex.
|
|
#[inline]
|
|
pub unsafe fn raw_unlock(&self) {
|
|
self.0.unlock()
|
|
}
|
|
}
|
|
|
|
impl Drop for MovableMutex {
|
|
fn drop(&mut self) {
|
|
unsafe { self.0.destroy() };
|
|
}
|
|
}
|