Struct glommio::sync::RwLock[][src]

pub struct RwLock<T> { /* fields omitted */ }

A reader-writer lock

This type of lock allows a number of readers or at most one writer at any point in time. The write portion of this lock typically allows modification of the underlying data (exclusive access) and the read portion of this lock typically allows for read-only access (shared access).

An RwLock will allow any number of readers to acquire the lock as long as a writer is not holding the lock.

The priority policy of the lock is based on FIFO policy. Fibers will be granted access in the order in which access to the lock was requested.

Lock is not reentrant, yet. That means that two subsequent calls to request write access to the lock will lead to dead lock problem.

The type parameter T represents the data that this lock protects. The RAII guards returned from the locking methods implement Deref (and DerefMut for the write methods) to allow access to the content of the lock.

Examples

use glommio::{sync::RwLock, LocalExecutor};

let lock = RwLock::new(5);
let ex = LocalExecutor::default();

ex.run(async move {
    // many reader locks can be held at once
    {
        let r1 = lock.read().await.unwrap();
        let r2 = lock.read().await.unwrap();
        assert_eq!(*r1, 5);
        assert_eq!(*r2, 5);
    } // read locks are dropped at this point

    // only one write lock may be held, however
    {
        let mut w = lock.write().await.unwrap();
        *w += 1;
        assert_eq!(*w, 6);
    } // write lock is dropped here
});

Implementations

impl<T> RwLock<T>[src]

pub fn new(value: T) -> Self[src]

Creates a new instance of an RwLock<T> which is unlocked.

Examples

use glommio::sync::RwLock;

let lock = RwLock::new(5);

pub fn get_mut(&mut self) -> LockResult<&mut T>[src]

Returns a mutable reference to the underlying data.

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

Errors

This function will return an error if the RwLock is closed.

Examples

use glommio::{sync::RwLock, LocalExecutor};

let mut lock = RwLock::new(0);
let ex = LocalExecutor::default();

ex.run(async move {
    *lock.get_mut().unwrap() = 10;
    assert_eq!(*lock.read().await.unwrap(), 10);
});

pub async fn read(&self) -> LockResult<RwLockReadGuard<'_, T>>[src]

Locks this RwLock with shared read access, suspending the current fiber until lock can be acquired.

The calling fiber will be suspended until there are no more writers which hold the lock. There may be other readers currently inside the lock when this method returns.

Returns an RAII guard which will release this fiber’s shared access once guard is dropped.

Errors

This function will return an error if the RwLock is closed.

Examples

use futures::future::join;
use glommio::{sync::RwLock, Local, LocalExecutor};
use std::rc::Rc;

let lock = Rc::new(RwLock::new(1));
let c_lock = lock.clone();

let ex = LocalExecutor::default();

ex.run(async move {
    let first_reader = Local::local(async move {
        let n = lock.read().await.unwrap();
        assert_eq!(*n, 1);
    })
    .detach();

    let second_reader = Local::local(async move {
        let r = c_lock.read().await;
        assert!(r.is_ok());
    })
    .detach();

    join(first_reader, second_reader).await;
});

pub async fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>>[src]

Locks this RwLock with exclusive write access, suspending the current finber until RwLock can be acquired.

This function will not return while other writers or other readers currently have access to the lock.

Returns an RAII guard which will drop the write access of this RwLock when dropped.

Errors

This function will return an error if the RwLock is closed.

Examples

use glommio::{sync::RwLock, LocalExecutor};

let lock = RwLock::new(1);
let ex = LocalExecutor::default();

ex.run(async move {
    let mut n = lock.write().await.unwrap();
    *n = 2;

    assert!(lock.try_read().is_err());
});

pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>>[src]

Attempts to acquire this RwLock with shared read access.

If the access could not be granted at this time, then Err is returned. Otherwise, an RAII guard is returned which will release the shared access when guard is dropped.

This function does not suspend.

Errors

This function will return an error if the RwLock is closed.

Examples

use glommio::sync::RwLock;

let lock = RwLock::new(1);

match lock.try_read() {
    Ok(n) => assert_eq!(*n, 1),
    Err(_) => unreachable!(),
};

pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>>[src]

Attempts to lock this RwLock with exclusive write access.

If the lock could not be acquired at this time, then Err is returned. Otherwise, an RAII guard is returned which will release the lock when guard is dropped.

This function does not suspend.

Errors

This function will return an error if the RwLock is closed.

Examples

use glommio::{sync::RwLock, LocalExecutor};

let lock = RwLock::new(1);
let ex = LocalExecutor::default();

ex.run(async move {
    let n = lock.read().await.unwrap();
    assert_eq!(*n, 1);

    assert!(lock.try_write().is_err());
});

pub fn is_closed(&self) -> bool[src]

Indicates whether current RwLock is closed. Once lock is closed all subsequent calls to the methods which requests lock access will return Err.

Examples

use glommio::sync::RwLock;

let lock = RwLock::new(());

lock.close();

assert!(lock.is_closed());

pub fn close(&self)[src]

Closes current RwLock. Once lock is closed all being hold accesses will be released and all subsequent calls to the methods to request lock access will return Err.

Examples

use glommio::{
    sync::{RwLock, Semaphore},
    Local,
    LocalExecutor,
};
use std::{cell::RefCell, rc::Rc};

let lock = Rc::new(RwLock::new(()));
let c_lock = lock.clone();

let semaphore = Rc::new(Semaphore::new(0));
let c_semaphore = semaphore.clone();

let ex = LocalExecutor::default();
ex.run(async move {
    let closer = Local::local(async move {
        //await till read lock will be acquired
        c_semaphore.acquire(1).await.unwrap();
        c_lock.close();

        assert!(c_lock.try_write().is_err());
    })
    .detach();

    let dead_locker = Local::local(async move {
        let _r = lock.read().await.unwrap();

        //allow another fiber close RwLock
        semaphore.signal(1);

        // this situation leads to deadlock unless lock is closed
        let lock_result = lock.write().await;
        assert!(lock_result.is_err());
    })
    .detach();

    dead_locker.await;
});

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

Consumes this RwLock, returning the underlying data.

Errors

This function will return an error if the ReadWritreLock is closed.

Examples

use glommio::{sync::RwLock, LocalExecutor};

let lock = RwLock::new(String::new());
let ex = LocalExecutor::default();

ex.run(async move {
    {
        let mut s = lock.write().await.unwrap();
        *s = "modified".to_owned();
    }

    assert_eq!(lock.into_inner().unwrap(), "modified");
});

Trait Implementations

impl<T: Debug> Debug for RwLock<T>[src]

impl<T> Drop for RwLock<T>[src]

Auto Trait Implementations

impl<T> !RefUnwindSafe for RwLock<T>

impl<T> !Send for RwLock<T>

impl<T> !Sync for RwLock<T>

impl<T> Unpin for RwLock<T> where
    T: Unpin

impl<T> !UnwindSafe for RwLock<T>

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.