Mutex

Struct Mutex 

Source
pub struct Mutex<T> { /* private fields */ }
Expand description

The RedisMutex struct.

It is used to lock a value in Redis, so that only one instance can access it at a time. You have to use RedisGeneric as the data type. It is a wrapper around the data type you want to store like the Mutex in std.

The lock is released when the guard is dropped or it expires. The default expiration time is 1000ms. If you need more time, use the Guard::expand() function.

Implementations§

Source§

impl<T> Mutex<T>

Source

pub fn new(data: Generic<T>) -> Self

Source

pub fn lock(&mut self) -> Result<Guard<'_, T>, LockError>

Locks the value in Redis. This function blocks until the lock is acquired. It returns a guard that can be used to access the value. The guard will unlock the value when it is dropped.

Beware that the value is not locked in the Rust sense and can be set by other instances, if they skip the locking process and its LOCK_SCRIPT.

If you try to lock a value that is already locked by another instance in the same scope, this function will block until the lock is released, which will be happen after the lock expires (1000ms). If you need to extend this time, you can use the Guard::expand() function.

§Example
use dtypes::redis::types::Di32 as i32;
use dtypes::redis::sync::Mutex;
use std::thread::scope;

let client = redis::Client::open("redis://localhost:6379").unwrap();
let client2 = client.clone();

scope(|s| {
   let t1 = s.spawn(move || {
        let mut i32 = i32::new("test_add_example1", client2);
        let mut lock = Mutex::new(i32);
        let mut guard = lock.lock().unwrap();
        guard.store(2).expect("TODO: panic message");
        assert_eq!(*guard, 2);
    });
    {  
        let mut i32 = i32::new("test_add_example1", client);
        let mut lock = Mutex::new(i32);
        let mut guard = lock.lock().unwrap();
        guard.store(1).expect("Failed to store value");
        assert_eq!(*guard, 1);
    }
    t1.join().expect("Failed to join thread1");
});

It does not allow any deadlocks, because the lock will automatically release after some time. So you have to check for errors, if you want to handle them.

Beware: Your CPU can anytime switch to another thread, so you have to check for errors! But if you are brave enough, you can drop the result and hope for the best.

§Example
use std::thread::sleep;
use dtypes::redis::types::Di32 as i32;
use dtypes::redis::sync::Mutex;

let client = redis::Client::open("redis://localhost:6379").unwrap();
let mut i32 = i32::new("test_add_example2", client.clone());
i32.store(1);
assert_eq!(i32.acquire(), &1);
let mut lock = Mutex::new(i32);

let mut guard = lock.lock().unwrap();
sleep(std::time::Duration::from_millis(1500));
let res = guard.store(3);
assert!(res.is_err(), "{:?}", res);

Methods from Deref<Target = Generic<T>>§

Source

pub fn store(&mut self, value: T)

The store method sets the value of the type.

Examples found in repository?
examples/2services.rs (line 15)
5fn main() {
6    thread::scope(|s| {
7        let client = redis::Client::open("redis://localhost:6379").unwrap();
8        let client2 = client.clone();
9
10        let t1 = s.spawn(move || {
11            let mut string = String::with_value("Hello".to_string(), "test", client);
12            println!("Thread1: {}", string.cached().unwrap());
13            assert_eq!(string, "Hello");
14            sleep(std::time::Duration::from_secs(1));
15            string.store("World".to_string());
16            println!("Thread1: {}", string.cached().unwrap());
17            assert_eq!(string, "World");
18        });
19
20        let t2 = s.spawn(move || {
21            sleep(std::time::Duration::from_micros(100));
22            let mut string = String::with_load("test", client2);
23            println!("Thread2: {}", string.cached().unwrap());
24            assert_eq!(string, "Hello");
25            sleep(std::time::Duration::from_secs(2));
26            string.acquire();
27            println!("Thread2: {}", string.cached().unwrap());
28            assert_eq!(string, "World");
29        });
30        t1.join().expect("Failed to join thread1");
31        t2.join().expect("Failed to join thread2");
32    });
33}
Source

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

The acquire method returns a reference to the value stored in the type. Loads it from the redis directly.

§Example
use dtypes::redis::types::Di32 as i32;

let client = redis::Client::open("redis://localhost:6379").unwrap();
let mut i32 = i32::with_value(1, "test_add", client.clone());
i32 = i32 + i32::with_value(2, "test_add2", client);
assert_eq!(i32.acquire(), &3);
Examples found in repository?
examples/2services.rs (line 26)
5fn main() {
6    thread::scope(|s| {
7        let client = redis::Client::open("redis://localhost:6379").unwrap();
8        let client2 = client.clone();
9
10        let t1 = s.spawn(move || {
11            let mut string = String::with_value("Hello".to_string(), "test", client);
12            println!("Thread1: {}", string.cached().unwrap());
13            assert_eq!(string, "Hello");
14            sleep(std::time::Duration::from_secs(1));
15            string.store("World".to_string());
16            println!("Thread1: {}", string.cached().unwrap());
17            assert_eq!(string, "World");
18        });
19
20        let t2 = s.spawn(move || {
21            sleep(std::time::Duration::from_micros(100));
22            let mut string = String::with_load("test", client2);
23            println!("Thread2: {}", string.cached().unwrap());
24            assert_eq!(string, "Hello");
25            sleep(std::time::Duration::from_secs(2));
26            string.acquire();
27            println!("Thread2: {}", string.cached().unwrap());
28            assert_eq!(string, "World");
29        });
30        t1.join().expect("Failed to join thread1");
31        t2.join().expect("Failed to join thread2");
32    });
33}
Source

pub fn cached(&self) -> Option<&T>

The get method returns a reference to the value stored in the type.

Examples found in repository?
examples/2services.rs (line 12)
5fn main() {
6    thread::scope(|s| {
7        let client = redis::Client::open("redis://localhost:6379").unwrap();
8        let client2 = client.clone();
9
10        let t1 = s.spawn(move || {
11            let mut string = String::with_value("Hello".to_string(), "test", client);
12            println!("Thread1: {}", string.cached().unwrap());
13            assert_eq!(string, "Hello");
14            sleep(std::time::Duration::from_secs(1));
15            string.store("World".to_string());
16            println!("Thread1: {}", string.cached().unwrap());
17            assert_eq!(string, "World");
18        });
19
20        let t2 = s.spawn(move || {
21            sleep(std::time::Duration::from_micros(100));
22            let mut string = String::with_load("test", client2);
23            println!("Thread2: {}", string.cached().unwrap());
24            assert_eq!(string, "Hello");
25            sleep(std::time::Duration::from_secs(2));
26            string.acquire();
27            println!("Thread2: {}", string.cached().unwrap());
28            assert_eq!(string, "World");
29        });
30        t1.join().expect("Failed to join thread1");
31        t2.join().expect("Failed to join thread2");
32    });
33}

Trait Implementations§

Source§

impl<T> Deref for Mutex<T>

Source§

type Target = Generic<T>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<T> DerefMut for Mutex<T>

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.

Auto Trait Implementations§

§

impl<T> Freeze for Mutex<T>
where T: Freeze,

§

impl<T> !RefUnwindSafe for Mutex<T>

§

impl<T> Send for Mutex<T>
where T: Send,

§

impl<T> Sync for Mutex<T>
where T: Sync,

§

impl<T> Unpin for Mutex<T>
where T: Unpin,

§

impl<T> !UnwindSafe for Mutex<T>

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<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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

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

Source§

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.