1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use std::sync::{
    RwLock,
    RwLockReadGuard,
    atomic::spin_loop_hint
};

/// Aquire a RwLock read lock, passing the lock to the lambda.
/// The lock is released when the lambda finishes.
/// This function returns whatever the lambda returns,
/// allowing you to extract data from a lock without having
/// to worry about releasing the lock.
/// ```ignore
/// let extracted = padlock::rw_read_lock(&arc_rwlock_var, |lock| lock.clone());
/// ```
pub fn rw_read_lock<T, F, R>(l: &RwLock<T>, f: F) -> R
    where F: FnOnce(&T) -> R {

    let r: R;

    loop {

        match l.try_read() {

            Ok(lock) => {
                r = f(&lock);
                drop(lock);
                break;
            },

            Err(_) => spin_loop_hint()

        }

    }

    r

}

/// Get the RwLockReadGuard directly, aquired with a spinlock.
///
/// Important: Don't forget to drop the lock! Locks release
/// themselfs when they go out of scope but the faster you
/// drop it, the faster other threads get access.
pub fn get_rw_read_lock<T>(l: &RwLock<T>) -> RwLockReadGuard<'_, T> {

    loop {

        match l.try_read() {

            Ok(lock) => return lock,

            Err(_) => spin_loop_hint()

        }

    }

}