[][src]Struct sunrise_kernel::sync::spin_lock::SpinLock

#[repr(transparent)]pub struct SpinLock<T: ?Sized>(Mutex<T>);

This type provides mutual exclusion based on spinning. It will panic if used in the context of an interrupt.

Description

The behaviour of these locks is similar to std::sync::Mutex. they differ on the following:

Simple examples

use crate::sync::SpinLock;
let spin_lock = SpinLock::new(0);

// Modify the data
{
    let mut data = spin_lock.lock();
    *data = 2;
}

// Read the data
let answer =
{
    let data = spin_lock.lock();
    *data
};

assert_eq!(answer, 2);

Thread-safety example

use crate::sync::SpinLock;
use std::sync::{Arc, Barrier};

let numthreads = 1000;
let spin_lock = Arc::new(SpinLock::new(0));

// We use a barrier to ensure the readout happens after all writing
let barrier = Arc::new(Barrier::new(numthreads + 1));

for _ in (0..numthreads)
{
    let my_barrier = barrier.clone();
    let my_lock = spin_lock.clone();
    std::thread::spawn(move||
    {
        let mut guard = my_lock.lock();
        *guard += 1;

        // Release the lock to prevent a deadlock
        drop(guard);
        my_barrier.wait();
    });
}

barrier.wait();

let answer = { *spin_lock.lock() };
assert_eq!(answer, numthreads);

Implementations

impl<T> SpinLock<T>[src]

pub const fn new(data: T) -> SpinLock<T>[src]

Creates a new spinlock wrapping the supplied data.

May be used statically:

use crate::sync::SpinLock;

static SPINLOCK: SpinLock<()> = SpinLock::new(());

fn demo() {
    let lock = SPINLOCK.lock();
    // do something with lock
    drop(lock);
}

pub fn into_inner(self) -> T[src]

Consumes this spinlock, returning the underlying data.

impl<T: ?Sized> SpinLock<T>[src]

pub fn lock(&self) -> SpinLockGuard<T>[src]

Locks the spinlock and returns a guard.

The returned value may be dereferenced for data access and the lock will be dropped when the guard falls out of scope.

Panics if called in an interrupt context.

let mylock = crate::sync::SpinLock::new(0);
{
    let mut data = mylock.lock();
    // The lock is now locked and the data can be accessed
    *data += 1;
    // The lock is implicitly dropped
}

pub unsafe fn force_unlock(&self)[src]

Force unlock the spinlock. If the lock isn't held, this is a no-op.

Safety

This is extremely unsafe if the lock is not held by the current thread. However, this can be useful in some instances for exposing the lock to FFI that doesn't know how to deal with RAII.

pub fn try_lock(&self) -> Option<SpinLockGuard<T>>[src]

Tries to lock the spinlock. If it is already locked, it will return None. Otherwise it returns a guard within Some.

Trait Implementations

impl<T: ?Sized + Debug> Debug for SpinLock<T>[src]

impl<T: ?Sized + Default> Default for SpinLock<T>[src]

impl<'a, T> Lock<'a, MutexGuard<'a, T>> for SpinLock<T>[src]

Auto Trait Implementations

impl<T> !RefUnwindSafe for SpinLock<T>

impl<T: ?Sized> Send for SpinLock<T> where
    T: Send

impl<T: ?Sized> Sync for SpinLock<T> where
    T: Send

impl<T: ?Sized> Unpin for SpinLock<T> where
    T: Unpin

impl<T: ?Sized> UnwindSafe for SpinLock<T> where
    T: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.