Skip to content

Commit 1600566

Browse files
committed
add parking_lot examples
1 parent 7ed15b2 commit 1600566

File tree

6 files changed

+198
-4
lines changed

6 files changed

+198
-4
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
[workspace]
2-
members = ["thread", "pool", "asyncwait", "primitive", "collections", "process", "syncs", "channel","special"]
2+
members = ["thread", "pool", "asyncwait", "primitive", "collections", "process", "syncs", "channel","parking_lot_examples", "special"]

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
## chapter 7: channel
1717

18-
## chapter 8: xxxx
18+
## chapter 8: parking_lot
1919

2020
## chapter 9: xxxx
2121

parking_lot_examples/Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "parking_lot_examples"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
parking_lot = "0.12.1"

parking_lot_examples/src/lib.rs

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
use std::sync::{mpsc::channel, Arc};
2+
use std::thread;
3+
4+
use parking_lot::RwLock;
5+
use parking_lot::{FairMutex, Mutex, Once, ReentrantMutex};
6+
7+
pub fn mutex_example() {
8+
const N: usize = 10;
9+
10+
let data = Arc::new(Mutex::new(0));
11+
let data2 = &data.clone();
12+
13+
let (tx, rx) = channel();
14+
for _ in 0..10 {
15+
let (data, tx) = (Arc::clone(&data), tx.clone());
16+
thread::spawn(move || {
17+
// The shared state can only be accessed once the lock is held.
18+
// Our non-atomic increment is safe because we're the only thread
19+
// which can access the shared state when the lock is held.
20+
let mut data = data.lock();
21+
*data += 1;
22+
if *data == N {
23+
tx.send(()).unwrap();
24+
}
25+
// the lock is unlocked here when `data` goes out of scope.
26+
});
27+
}
28+
29+
rx.recv().unwrap();
30+
31+
println!("mutex_example: {}", data2.lock());
32+
}
33+
34+
pub fn mutex_example2() {
35+
const N: usize = 10;
36+
37+
let mutex = Arc::new(Mutex::new(()));
38+
39+
let handles: Vec<_> = (0..N)
40+
.map(|i| {
41+
let mutex = Arc::clone(&mutex);
42+
thread::spawn(move || {
43+
let _lock = mutex.lock();
44+
println!("thread {} done", i);
45+
})
46+
})
47+
.collect();
48+
49+
for handle in handles {
50+
handle.join().unwrap();
51+
}
52+
53+
println!("mutex_example2: done");
54+
}
55+
56+
pub fn fairmutex_example() {
57+
const N: usize = 10;
58+
59+
let data = Arc::new(FairMutex::new(0));
60+
61+
let (tx, rx) = channel();
62+
for _ in 0..10 {
63+
let (data, tx) = (Arc::clone(&data), tx.clone());
64+
thread::spawn(move || {
65+
// The shared state can only be accessed once the lock is held.
66+
// Our non-atomic increment is safe because we're the only thread
67+
// which can access the shared state when the lock is held.
68+
let mut data = data.lock();
69+
*data += 1;
70+
if *data == N {
71+
tx.send(()).unwrap();
72+
}
73+
// the lock is unlocked here when `data` goes out of scope.
74+
});
75+
}
76+
77+
rx.recv().unwrap();
78+
79+
println!("fairmutex_example: done");
80+
}
81+
82+
pub fn rwmutex_example() {
83+
const N: usize = 10;
84+
85+
let lock = Arc::new(RwLock::new(5));
86+
87+
let handles: Vec<_> = (0..N)
88+
.map(|i| {
89+
let lock = Arc::clone(&lock);
90+
thread::spawn(move || {
91+
if i % 2 == 0 {
92+
let mut num = lock.write();
93+
*num += 1;
94+
} else {
95+
let num = lock.read();
96+
println!("thread {} read {}", i, num);
97+
}
98+
})
99+
})
100+
.collect();
101+
102+
for handle in handles {
103+
handle.join().unwrap();
104+
}
105+
106+
println!("rwmutex_example: {}", lock.read());
107+
}
108+
pub fn reentrantmutex_example() {
109+
let lock = ReentrantMutex::new(());
110+
111+
reentrant(&lock, 10);
112+
113+
println!("reentrantMutex_example: done");
114+
}
115+
116+
fn reentrant(lock: &ReentrantMutex<()>, i: usize) {
117+
if i == 0 {
118+
return;
119+
}
120+
121+
let _lock = lock.lock();
122+
reentrant(lock, i - 1);
123+
}
124+
125+
pub fn once_example() {
126+
static mut VAL: usize = 0;
127+
static INIT: Once = Once::new();
128+
fn get_cached_val() -> usize {
129+
unsafe {
130+
INIT.call_once(|| {
131+
println!("initializing once");
132+
thread::sleep(std::time::Duration::from_secs(1));
133+
VAL = 100;
134+
});
135+
VAL
136+
}
137+
}
138+
139+
140+
let handle = thread::spawn(|| {
141+
println!("thread 1 get_cached_val: {}", get_cached_val());
142+
});
143+
144+
println!("get_cached_val: {}", get_cached_val());
145+
146+
handle.join().unwrap();
147+
}
148+
149+
150+
pub fn condvar_example() {
151+
use std::sync::Condvar;
152+
use std::sync::Mutex;
153+
154+
let pair = Arc::new((Mutex::new(false), Condvar::new()));
155+
let pair2 = Arc::clone(&pair);
156+
157+
thread::spawn(move || {
158+
let (lock, cvar) = &*pair2;
159+
let mut started = lock.lock().unwrap();
160+
*started = true;
161+
cvar.notify_one();
162+
});
163+
164+
let (lock, cvar) = &*pair;
165+
let mut started = lock.lock().unwrap();
166+
while !*started {
167+
started = cvar.wait(started).unwrap(); // block until notified
168+
}
169+
println!("condvar_example: done");
170+
}

parking_lot_examples/src/main.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use parking_lot_examples::*;
2+
3+
fn main() {
4+
mutex_example();
5+
mutex_example2();
6+
fairmutex_example();
7+
8+
rwmutex_example();
9+
10+
reentrantmutex_example();
11+
12+
once_example();
13+
14+
condvar_example();
15+
}

thread/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ pub use threads::*;
66
pub fn panic_example() {
77
println!("Hello, world!");
88

9-
let h = thread::spawn(|| {
10-
thread::sleep_ms(1000);
9+
let h = std::thread::spawn(|| {
10+
std::thread::sleep(std::time::Duration::from_millis(1000));
1111
panic!("boom");
1212
});
1313

0 commit comments

Comments
 (0)