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 60
use crate::semaphore::{Semaphore, SemaphoreError};
use std::time::Duration;
/// ReentrantLock implemented using Semaphore(1).
///
/// This Lock does not need to be mutable on calling, it is safe to share across multiple threads even with read only mode.
///
/// Example:
/// ```
/// use std::sync::Arc;
/// use std::time::Duration;
/// use std::thread;
/// use classic_sync::lock::ReentrantLock;
/// let lock = ReentrantLock::new();
/// let arc_lock = Arc::new(lock);
/// for i in 0..3 {
/// let lock_copy = Arc::clone(&arc_lock);
/// let tid = i;
/// thread::spawn(move || {
/// lock_copy.lock();
/// println!("Now we are in critical section!");
/// std::thread::sleep(Duration::from_secs(3));
/// // Other people can't acquire the lock even when I am sleeping.
/// lock_copy.unlock(); // You have to manually unlock it to release the lock
/// });
/// }
/// ```
pub struct ReentrantLock {
sem:Semaphore
}
/// Implementation of ReentrantLock
impl ReentrantLock {
/// Create a new Lock object. Lock can be shared using Arc<ReentrantLock> with readonly access
pub fn new() -> ReentrantLock {
let sem = Semaphore::new(1);
return ReentrantLock {
sem
};
}
/// Acquire the lock and wait indefinitely for it to happen
/// Calling on already locked lock will block forever (dead lock)
/// It is calling internal semaphore's p() operation effectively.
pub fn lock(&self) {
self.sem.p();
}
/// Release the lock. Do not call unlock multiple times. It will give non-exclusive access any more!
/// It is calling internal semaphore's v() operation effectively.
pub fn unlock(&self) {
self.sem.v();
}
/// Try to acquire a lock. Return true if lock is acquired. Return false if acquire timed out.
pub fn try_lock(&self, timeout:Duration) -> bool {
return self.sem.p_timeout(timeout);
}
}