Struct mcslock::barging::Mutex

source ·
pub struct Mutex<T: ?Sized, R> { /* private fields */ }
Available on crate feature barging only.
Expand description

A mutual exclusion primitive useful for protecting shared data.

This mutex will block threads waiting for the lock to become available. The mutex can also be statically initialized or created via a new constructor. Each mutex has a type parameter which represents the data that it is protecting. The data can only be accessed through the RAII guards returned from lock and try_lock, which guarantees that the data is only ever accessed when the mutex is locked.

Examples

use std::sync::Arc;
use std::thread;
use std::sync::mpsc::channel;

use mcslock::barging::Mutex;
use mcslock::relax::Spin;

type SpinMutex<T> = Mutex<T, Spin>;

const N: usize = 10;

// Spawn a few threads to increment a shared variable (non-atomically), and
// let the main thread know once all increments are done.
//
// Here we're using an Arc to share memory among threads, and the data inside
// the Arc is protected with a mutex.
let data = Arc::new(SpinMutex::new(0));

let (tx, rx) = channel();
for _ in 0..N {
    let (data, tx) = (data.clone(), tx.clone());
    thread::spawn(move || {
        // The shared state can only be accessed once the lock is held.
        // Our non-atomic increment is safe because we're the only thread
        // which can access the shared state when the lock is held.
        //
        // We unwrap() the return value to assert that we are not expecting
        // threads to ever fail while holding the lock.
        let mut data = data.lock();
        *data += 1;
        if *data == N {
            tx.send(()).unwrap();
        }
        // the lock is unlocked here when `data` goes out of scope.
    });
}

rx.recv().unwrap();

Implementations§

source§

impl<T, R> Mutex<T, R>

source

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

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

Examples
use mcslock::barging::Mutex;
use mcslock::relax::Spin;

type SpinMutex<T> = Mutex<T, Spin>;

const MUTEX: SpinMutex<i32> = SpinMutex::new(0);
let mutex = SpinMutex::new(0);
source

pub fn into_inner(self) -> T

Consumes this mutex, returning the underlying data.

Examples
use mcslock::barging::Mutex;
use mcslock::relax::Spin;

type SpinMutex<T> = Mutex<T, Spin>;

let mutex = SpinMutex::new(0);
assert_eq!(mutex.into_inner(), 0);
source§

impl<T: ?Sized, R: Relax> Mutex<T, R>

source

pub fn lock(&self) -> MutexGuard<'_, T, R>

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

This function will block the local thread until it is available to acquire the mutex. Upon returning, the thread is the only thread with the lock held. An RAII guard is returned to allow scoped unlock of the lock. When the guard goes out of scope, the mutex will be unlocked. To acquire a MCS lock, it’s also required a mutably borrowed queue node, which is a record that keeps a link for forming the queue, see MutexNode.

This function will block if the lock is unavailable.

Examples
use std::sync::Arc;
use std::thread;

use mcslock::barging::Mutex;
use mcslock::relax::Spin;

type SpinMutex<T> = Mutex<T, Spin>;

let mutex = Arc::new(SpinMutex::new(0));
let c_mutex = Arc::clone(&mutex);

thread::spawn(move || {
    *c_mutex.lock() = 10;
})
.join().expect("thread::spawn failed");

assert_eq!(*mutex.lock(), 10);
source

pub fn lock_with<F, Ret>(&self, f: F) -> Ret
where F: FnOnce(MutexGuard<'_, T, R>) -> Ret,

Acquires this mutex and then runs the closure against its guard.

This function will block the local thread until it is available to acquire the mutex. Upon acquiring the mutex, the user provided closure will be executed against the mutex guard. Once the guard goes out of scope, it will unlock the mutex.

This function will block if the lock is unavailable.

Examples
use std::sync::Arc;
use std::thread;

use mcslock::barging::Mutex;
use mcslock::relax::Spin;

type SpinMutex<T> = Mutex<T, Spin>;

let mutex = Arc::new(SpinMutex::new(0));
let c_mutex = Arc::clone(&mutex);

thread::spawn(move || {
    c_mutex.lock_with(|mut guard| *guard = 10);
})
.join().expect("thread::spawn failed");

assert_eq!(mutex.lock_with(|guard| *guard), 10);

Borrows of the guard or its data cannot escape the given closure.

use mcslock::barging::spins::Mutex;

let mutex = Mutex::new(1);
let data = mutex.lock_with(|guard| &*guard);
source§

impl<T: ?Sized, R> Mutex<T, R>

source

pub fn try_lock(&self) -> Option<MutexGuard<'_, T, R>>

Attempts to acquire this mutex without blocking the thread.

If the lock could not be acquired at this time, then None is returned. Otherwise, an RAII guard is returned. The lock will be unlocked when the guard is dropped. To acquire a MCS lock, it’s also required a mutably borrowed queue node, which is a record that keeps a link for forming the queue, see MutexNode.

This function does not block.

Examples
use std::sync::Arc;
use std::thread;

use mcslock::barging::Mutex;
use mcslock::relax::Spin;

type SpinMutex<T> = Mutex<T, Spin>;

let mutex = Arc::new(SpinMutex::new(0));
let c_mutex = Arc::clone(&mutex);

thread::spawn(move || {
    let mut guard = c_mutex.try_lock();
    if let Some(mut guard) = guard {
        *guard = 10;
    } else {
        println!("try_lock failed");
    }
})
.join().expect("thread::spawn failed");

assert_eq!(*mutex.lock(), 10);
source

pub fn try_lock_with<F, Ret>(&self, f: F) -> Ret
where F: FnOnce(Option<MutexGuard<'_, T, R>>) -> Ret,

Attempts to acquire this mutex and then runs a closure against its guard.

If the lock could not be acquired at this time, then a None value is given back as the closure argument. If the lock has been acquired, then a Some value with the mutex guard is given instead. The lock will be unlocked when the guard is dropped.

This function does not block.

Examples
use std::sync::Arc;
use std::thread;

use mcslock::barging::Mutex;
use mcslock::relax::Spin;

type SpinMutex<T> = Mutex<T, Spin>;

let mutex = Arc::new(SpinMutex::new(0));
let c_mutex = Arc::clone(&mutex);

thread::spawn(move || {
    c_mutex.try_lock_with(|guard| {
        if let Some(mut guard) = guard {
            *guard = 10;
        } else {
            println!("try_lock failed");
        }
    });
})
.join().expect("thread::spawn failed");

assert_eq!(mutex.lock_with(|guard| *guard), 10);

Borrows of the guard or its data cannot escape the given closure.

use mcslock::barging::spins::Mutex;

let mutex = Mutex::new(1);
let data = mutex.try_lock_with(|guard| &*guard.unwrap());
source

pub fn is_locked(&self) -> bool

Returns true if the lock is currently held.

This method does not provide any synchronization guarantees, so its only useful as a heuristic, and so must be considered not up to date.

Example
use mcslock::barging::Mutex;
use mcslock::relax::Spin;

type SpinMutex<T> = Mutex<T, Spin>;

let mutex = SpinMutex::new(0);
let guard = mutex.lock();
drop(guard);

assert_eq!(mutex.is_locked(), false);
source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to the underlying data.

Since this call borrows the Mutex mutably, no actual locking needs to take place - the mutable borrow statically guarantees no locks exist.

Examples
use mcslock::barging::Mutex;
use mcslock::relax::Spin;

type SpinMutex<T> = Mutex<T, Spin>;

let mut mutex = SpinMutex::new(0);
*mutex.get_mut() = 10;

assert_eq!(*mutex.lock(), 10);

Trait Implementations§

source§

impl<T: ?Sized + Debug, R: Relax> Debug for Mutex<T, R>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: ?Sized + Default, R> Default for Mutex<T, R>

source§

fn default() -> Self

Creates a Mutex<T, R>, with the Default value for T.

source§

impl<T, R> From<T> for Mutex<T, R>

source§

fn from(data: T) -> Self

Creates a Mutex<T, R> from a instance of T.

source§

impl<R: Relax> RawMutex for Mutex<(), R>

§

type GuardMarker = GuardSend

Marker type which determines whether a lock guard should be Send. Use one of the GuardSend or GuardNoSend helper types here.
source§

const INIT: Self = _

Initial value for an unlocked mutex.
source§

fn lock(&self)

Acquires this mutex, blocking the current thread until it is able to do so.
source§

fn try_lock(&self) -> bool

Attempts to acquire this mutex without blocking. Returns true if the lock was successfully acquired and false otherwise.
source§

unsafe fn unlock(&self)

Unlocks this mutex. Read more
source§

fn is_locked(&self) -> bool

Checks whether the mutex is currently locked.

Auto Trait Implementations§

§

impl<T, R> !RefUnwindSafe for Mutex<T, R>

§

impl<T: ?Sized, R> Send for Mutex<T, R>
where R: Send, T: Send,

§

impl<T: ?Sized, R> Sync for Mutex<T, R>
where R: Sync, T: Send,

§

impl<T: ?Sized, R> Unpin for Mutex<T, R>
where R: Unpin, T: Unpin,

§

impl<T: ?Sized, R> UnwindSafe for Mutex<T, R>
where R: UnwindSafe, T: UnwindSafe,

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<!> for T

source§

fn from(t: !) -> T

Converts to this type from the input type.
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, U> TryFrom<U> for T
where U: Into<T>,

§

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>,

§

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.