classic_sync/
lock.rs

1use crate::semaphore::{Semaphore, SemaphoreError};
2use std::time::Duration;
3
4/// ReentrantLock implemented using Semaphore(1).
5/// 
6/// This Lock does not need to be mutable on calling, it is safe to share across multiple threads even with read only mode.
7/// 
8/// Example:
9/// ```
10/// use std::sync::Arc;
11/// use std::time::Duration;
12/// use std::thread;
13/// use classic_sync::lock::ReentrantLock;
14/// let lock = ReentrantLock::new();
15/// let arc_lock = Arc::new(lock);
16/// for i in 0..3 {
17///     let lock_copy = Arc::clone(&arc_lock);
18///     let tid = i;
19///     thread::spawn(move || {
20///         lock_copy.lock();
21///         println!("Now we are in critical section!");
22///         std::thread::sleep(Duration::from_secs(3));
23///         // Other people can't acquire the lock even when I am sleeping.
24///         lock_copy.unlock(); // You have to manually unlock it to release the lock
25///     });
26/// }
27/// ```
28pub struct ReentrantLock {
29    sem:Semaphore
30}
31
32
33/// Implementation of ReentrantLock
34impl ReentrantLock {
35    /// Create a new Lock object. Lock can be shared using Arc<ReentrantLock> with readonly access
36    pub fn new() -> ReentrantLock {
37        let sem = Semaphore::new(1);
38        return ReentrantLock {
39            sem
40        };
41    }
42
43    /// Acquire the lock and wait indefinitely for it to happen
44    /// Calling on already locked lock will block forever (dead lock)
45    /// It is calling internal semaphore's p() operation effectively.
46    pub fn lock(&self)  {
47        self.sem.p();
48    }
49
50    /// Release the lock. Do not call unlock multiple times. It will give non-exclusive access any more!
51    /// It is calling internal semaphore's v() operation effectively.
52    pub fn unlock(&self) {
53        self.sem.v();
54    }
55
56    /// Try to acquire a lock. Return true if lock is acquired. Return false if acquire timed out.
57    pub fn try_lock(&self, timeout:Duration) -> bool {
58        return self.sem.p_timeout(timeout);
59    }
60}