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}