[−][src]Struct spin_sync::RwLock
A reader-writer lock.
It behaves like std::sync::RwLock except for using spinlock.
What is more, the constructor is a const function; i.e. it is possible to declare
static RwLock<T>
variable as long as the inner data can be built statically.
This type of lock allows either a number of readers or at most one writer at the same time. Readers are allowed read-only access (shared access) to the underlying data while the writer is allowed read/write access (exclusive access.)
In comparison, a Mutex
does not distinguish between readers and writers,
therefore blocking any threads waiting for the lock to become available.
An RwLock
will allow any number of readers to acquire the lock as long as
a writer is not holding the lock.
There is no priority difference with respect to the ordering of whether contentious readers or writers will acquire the lock first.
Poisoning
An RwLock
, like Mutex
, will become poisoned on a panic. Note, however,
that an RwLock
may only be poisoned if a panic occurs while it is locked
exclusively (write mode). If a panic occurs in any reader, then the lock
will not be poisoned.
Examples
Create a variable protected by a RwLock, increment it by 2 in worker threads at the same time, and check the variable was updated rightly.
use spin_sync::RwLock; use std::sync::Arc; use std::thread; const WORKER_NUM: usize = 10; let mut handles = Vec::with_capacity(WORKER_NUM); // We can declare static RwLock<usize> variable because RwLock::new is a const function. static RWLOCK: RwLock<usize> = RwLock::new(0); // Create worker threads to inclement the value by 2. for _ in 0..WORKER_NUM { let handle = thread::spawn(move || { let mut num = RWLOCK.write().unwrap(); *num += 2; }); handles.push(handle); } // Make sure the value is always multipile of 2 even if some worker threads // are working. // // Enclosing the lock with `{}` to drop it before waiting for the worker // threads; otherwise, deadlocks could be occurred. { let num = RWLOCK.read().unwrap(); assert_eq!(0, *num % 2); } // Wait for the all worker threads are finished. for handle in handles { handle.join().unwrap(); } // Make sure the value is incremented by 2 times the worker count. let num = RWLOCK.read().unwrap(); assert_eq!(2 * WORKER_NUM, *num);
Implementations
impl<T> RwLock<T>
[src]
pub const fn new(t: T) -> Self
[src]
Creates a new instance in unlocked state ready for use.
Examples
Declare as a static variable.
use spin_sync::RwLock; static LOCK: RwLock<i32> = RwLock::new(5);
Declare as a local variable.
use spin_sync::RwLock; let lock = RwLock::new(5);
pub fn into_inner(self) -> LockResult<T>
[src]
Consumes this instance and returns the underlying data.
Note that this method won't acquire any lock because we know there is
no other references to self
.
Errors
If another user panicked while holding the exclusive write lock of this instance, this method call wraps the guard in an error and returns it.
Examples
use spin_sync::RwLock; let rwlock = RwLock::new(0); assert_eq!(0, rwlock.into_inner().unwrap());
impl<T: ?Sized> RwLock<T>
[src]
pub const MAX_READ_LOCK_COUNT: u64
[src]
The maximum shared read locks of each instance.
pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>>
[src]
Blocks the current thread until acquiring a shared read lock, and returns an RAII guard object.
The actual flow will be as follows.
- User calls this method.
- Blocks until this thread acquires a shared read lock (i.e. until the exclusive write lock is held.)
- Creates an RAII guard object.
- Wrapps the guard in
Result
and returns it. If this instance has been poisoned, it is wrapped in anErr
; otherwise wrapped in anOk
.
- User accesses to the underlying data to read through the guard. (No write access is then.)
- The guard is dropped (falls out of scope) and the lock is released.
Errors
If another user panicked while holding the exclusive write lock of this instance, this method call wraps the guard in an error and returns it.
Panics
This method panics if MAX_READ_LOCK_COUNT
shared locks are.
Examples
use spin_sync::RwLock; let lock = RwLock::new(1); let guard1 = lock.read().unwrap(); assert_eq!(1, *guard1); let guard2 = lock.read().unwrap(); assert_eq!(1, *guard2);
pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>>
[src]
Attempts to acquire a shared read lock and returns an RAII guard object if succeeded.
Behaves like read
except for this method returns an error immediately
if the exclusive write lock is being held.
This function does not block.
The actual flow will be as follows.
- User calls this method.
- Tries to acquire a shared read lock. If failed (i.e. if the exclusive write lock is being held,) returns an error immediately and this flow is finished here.
- Creates an RAII guard object.
- Wrapps the guard in
Result
and returns it. If this instance has been poisoned, it is wrapped in anErr
; otherwise wrapped in anOk
.
- User accesses to the underlying data to read through the guard. (No write access is at then.)
- The guard is dropped (falls out of scope) and the lock is released.
Panics
This method panics if MAX_READ_LOCK
shared read locks are.
Errors
- If another user is holding the exclusive write lock,
TryLockError::WouldBlock
is returned. - If this method call succeeded to acquire a shared read lock, and if another
user had panicked while holding the exclusive write lock,
TryLockError::Poisoned
is returned.
Examples
use spin_sync::RwLock; let lock = RwLock::new(1); let guard0 = lock.try_read().unwrap(); assert_eq!(1, *guard0); let guard1 = lock.try_read().unwrap(); assert_eq!(1, *guard1);
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>>
[src]
Attempts to acquire the exclusive write lock and returns an RAII guard object if succeeded.
Behaves like write
except for this method returns an error immediately
if any other lock (either read lock or write lock) is being held.
This method does not block.
The actual flow will be as follows.
- User calls this method.
- Tries to acquire the exclusive write lock. If failed (i.e. if any other lock is being held,) returns an error immediately and this flow is finished here.
- Creates an RAII guard object.
- Wraps the guard in
Result
and returns it. If this instance has been poisoned, it is wrapped in anErr
; otherwise wrapped in anOk
.
- User accesses to the underlying data to read/write through the guard. (No other access is then.)
- The guard is dropped (falls out of scope) and the lock is released.
Errors
- If another user is holding any other lock (either read lock or write lock),
TryLockError::WouldBlock
is returned. - If this method call succeeded to acquire the lock, and if another user had panicked
while holding the exclusive write lock,
TryLockError::Poisoned
is returned.
Examples
use spin_sync::RwLock; let lock = RwLock::new(1); let mut guard = lock.try_write().unwrap(); assert_eq!(1, *guard); *guard += 1; assert_eq!(2, *guard); assert!(lock.try_write().is_err()); assert!(lock.try_read().is_err());
pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>>
[src]
Blocks the current thread until acquiring the exclusive write lock, and returns an RAII guard object.
The actual flow will be as follows.
- User calls this method.
- Blocks until this thread acquires the exclusive write lock (i.e. until any other lock is held.)
- Creates an RAII guard object.
- Wrapps the guard in Result and returns it. If this instance has been
poisoned, it is wrapped in an
Err
; otherwise wrapped in anOk
.
- User accesses to the underlying data to read/write through the guard. (No other access is then.)
- The guard is dropped (falls out of scope) and the lock is released.
Errors
If another user panicked while holding the exclusive write lock of this instance, this method call wraps the guard in an error and returns it.
Examples
use spin_sync::RwLock; let lock = RwLock::new(0); let mut guard = lock.write().unwrap(); assert_eq!(0, *guard); *guard += 1; assert_eq!(1, *guard); assert_eq!(true, lock.try_read().is_err()); assert_eq!(true, lock.try_write().is_err());
pub fn is_poisoned(&self) -> bool
[src]
Determines whether the lock is poisoned or not.
Warning
This function won't acquire any lock. If another thread is active,
the rwlock can become poisoned at any time. You should not trust a false
value for program correctness without additional synchronization.
Examples
use spin_sync::RwLock; use std::sync::Arc; use std::thread; let lock = Arc::new(RwLock::new(0)); assert_eq!(false, lock.is_poisoned()); { let lock = lock.clone(); let _ = thread::spawn(move || { // This panic while holding the lock (`_guard` is in scope) will poison // the instance. let _guard = lock.write().unwrap(); panic!("Poison here"); }).join(); } assert_eq!(true, lock.is_poisoned());
pub fn get_mut(&mut self) -> LockResult<&mut T>
[src]
Returns a mutable reference to the underlying data.
Note that this method won't acquire any lock because we know there is
no other references to self
.
Errors
If another user panicked while holding the exclusive write lock of this instance, this method call wraps the guard in an error and returns it.
Examples
use spin_sync::RwLock; let mut lock = RwLock::new(0); *lock.get_mut().unwrap() = 10; assert_eq!(*lock.read().unwrap(), 10);
Trait Implementations
impl<T: ?Sized + Debug> Debug for RwLock<T>
[src]
impl<T: Default> Default for RwLock<T>
[src]
impl<T> From<T> for RwLock<T>
[src]
impl<T: ?Sized> RefUnwindSafe for RwLock<T>
[src]
impl<T: ?Sized + Send> Send for RwLock<T>
[src]
impl<T: ?Sized + Send + Sync> Sync for RwLock<T>
[src]
impl<T: ?Sized> UnwindSafe for RwLock<T>
[src]
Auto Trait Implementations
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<!> for T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,