Skip to content

Commit 6b28540

Browse files
committed
add more special examples
1 parent 1d999e0 commit 6b28540

12 files changed

+293
-15
lines changed

special/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,12 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9+
async-lock = "2.5.0"
10+
concurrent-queue = "1.2.4"
11+
dashmap = "5.4.0"
12+
event-listener = "2.5.3"
913
process_lock = "0.1.0"
14+
sharded-slab = "0.1.4"
15+
slab = "0.4.7"
16+
smol = "1.2.5"
17+
try-lock = "0.2.3"

special/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
pub mod oslock;
22
pub mod oneshot;
33
pub mod map;
4+
pub mod primitive;
5+
pub mod notify;
6+
pub mod queue;
47

58
pub use oslock::*;
69
pub use oneshot::*;
7-
pub use map::*;
10+
pub use map::*;
11+
pub use primitive::*;
12+
pub use notify::*;
13+
pub use queue::*;

special/src/main.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
use special::*;
22

3+
34
fn main() {
45
process_lock();
6+
7+
try_lock_example1();
8+
9+
sharded_slab_read();
10+
sharded_slab_write();
11+
sharded_slab_pool();
12+
slab_example();
13+
14+
event_listener_example();
15+
16+
hashmap_example();
17+
concurrent_queue_example();
18+
19+
async_lock_mutex();
520
}

special/src/map.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use std::sync::Arc;
2+
use std::thread;
3+
use dashmap::DashMap;
4+
5+
pub fn hashmap_example() {
6+
let map = Arc::new(DashMap::new());
7+
8+
let map1 = map.clone();
9+
let whandle = thread::spawn(move || {
10+
map1.insert(1, 2);
11+
map1.insert(2, 3);
12+
});
13+
14+
15+
let map2 = map.clone();
16+
let rhandle = thread::spawn(move || {
17+
18+
loop {
19+
if let Some(v) = map2.get(&1) {
20+
println!("get value {} for key 1", *v);
21+
break;
22+
}
23+
}
24+
25+
loop {
26+
if let Some(v) = map2.get(&2) {
27+
println!("get value {} for key 2", *v);
28+
break;
29+
}
30+
}
31+
});
32+
33+
whandle.join().unwrap();
34+
rhandle.join().unwrap();
35+
36+
}

special/src/notify.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use event_listener::Event;
2+
use std::sync::atomic::{AtomicBool, Ordering};
3+
use std::sync::Arc;
4+
use std::thread;
5+
use std::time::Duration;
6+
7+
pub fn event_listener_example() {
8+
let flag = Arc::new(AtomicBool::new(false));
9+
let event = Arc::new(Event::new());
10+
11+
// Spawn a thread that will set the flag after 1 second.
12+
thread::spawn({
13+
let flag = flag.clone();
14+
let event = event.clone();
15+
move || {
16+
// Wait for a second.
17+
thread::sleep(Duration::from_secs(1));
18+
19+
// Set the flag.
20+
flag.store(true, Ordering::SeqCst);
21+
22+
// Notify all listeners that the flag has been set.
23+
event.notify(usize::MAX);
24+
}
25+
});
26+
27+
// Wait until the flag is set.
28+
loop {
29+
// Check the flag.
30+
if flag.load(Ordering::SeqCst) {
31+
break;
32+
}
33+
34+
// Start listening for events.
35+
let listener = event.listen();
36+
37+
// Check the flag again after creating the listener.
38+
if flag.load(Ordering::SeqCst) {
39+
break;
40+
}
41+
42+
// Wait for a notification and continue the loop.
43+
listener.wait();
44+
}
45+
46+
println!("flag is set");
47+
}

special/src/oslock.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ pub fn process_lock() {
1111
println!("lock success");
1212
break;
1313
}
14-
if start.elapsed() > Duration::from_secs(10) {
14+
if start.elapsed() > Duration::from_millis(500) {
1515
println!("lock timeout");
1616
break;
1717
}
1818
std::thread::sleep(Duration::from_millis(100));
1919
}
20-
std::thread::sleep(Duration::from_secs(10));
20+
std::thread::sleep(Duration::from_millis(500));
2121

2222
}

special/src/primitive.rs

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use async_lock::*;
2+
use std::sync::Arc;
3+
4+
pub fn async_lock_mutex() {
5+
let lock = Arc::new(Mutex::new(0));
6+
7+
let lock1 = lock.clone();
8+
smol::block_on(async {
9+
let mut guard = lock1.lock().await;
10+
*guard += 1;
11+
});
12+
13+
let lock2 = lock.clone();
14+
smol::block_on(async {
15+
let guard = lock2.lock().await;
16+
println!("lock2 {}", *guard);
17+
});
18+
19+
20+
}

special/src/primitive/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Mutex
2+
// RWLock
3+
// wg
4+
// async-xxx
5+
// awaitgroup
6+
// usync
7+
8+
9+
// waitfor
10+
11+
// atomig
12+
// atomicbox
13+
14+
pub mod try_lock_examples;
15+
pub mod sharded_slab_example;
16+
pub mod async_lock_example;
17+
18+
pub use try_lock_examples::*;
19+
pub use sharded_slab_example::*;
20+
pub use async_lock_example::*;
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use sharded_slab::Pool;
2+
use sharded_slab::Slab;
3+
4+
use std::sync::{Arc, Mutex};
5+
6+
// Slabs provide pre-allocated storage for many instances of a single data type.
7+
// When a large number of values of a single type are required, this can be more efficient than allocating each item individually.
8+
// Since the allocated items are the same size, memory fragmentation is reduced, and creating and removing new items can be very cheap.
9+
10+
pub fn sharded_slab_read() {
11+
let slab = Arc::new(Slab::new());
12+
13+
let slab2 = slab.clone();
14+
let thread2 = std::thread::spawn(move || {
15+
let key = slab2.insert("hello from thread two").unwrap();
16+
assert_eq!(slab2.get(key).unwrap(), "hello from thread two");
17+
key
18+
});
19+
20+
let key1 = slab.insert("hello from thread one").unwrap();
21+
assert_eq!(slab.get(key1).unwrap(), "hello from thread one");
22+
23+
// Wait for thread 2 to complete.
24+
let key2 = thread2.join().unwrap();
25+
26+
// The item inserted by thread 2 remains in the slab.
27+
assert_eq!(slab.get(key2).unwrap(), "hello from thread two");
28+
}
29+
30+
pub fn sharded_slab_write() {
31+
let slab = Arc::new(Slab::new());
32+
33+
let key = slab
34+
.insert(Mutex::new(String::from("hello world")))
35+
.unwrap();
36+
37+
let slab2 = slab.clone();
38+
let thread2 = std::thread::spawn(move || {
39+
let hello = slab2.get(key).expect("item missing");
40+
let mut hello = hello.lock().expect("mutex poisoned");
41+
*hello = String::from("hello everyone!");
42+
});
43+
44+
thread2.join().unwrap();
45+
46+
let hello = slab.get(key).expect("item missing");
47+
let hello = hello.lock().expect("mutex poisoned");
48+
assert_eq!(hello.as_str(), "hello everyone!");
49+
}
50+
51+
pub fn sharded_slab_pool() {
52+
let pool: Pool<String> = Pool::new();
53+
54+
let mut guard = pool.create().unwrap();
55+
let key = guard.key();
56+
guard.push_str("hello world");
57+
58+
drop(guard); // release the guard, allowing immutable access.
59+
assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
60+
61+
// Mark this entry to be cleared.
62+
pool.clear(key);
63+
// The cleared entry is no longer available in the pool
64+
assert!(pool.get(key).is_none());
65+
}
66+
67+
pub fn slab_example() {
68+
let mut slab = slab::Slab::new();
69+
70+
let hello = slab.insert("hello");
71+
let world = slab.insert("world");
72+
73+
assert_eq!(slab[hello], "hello");
74+
assert_eq!(slab[world], "world");
75+
76+
slab[world] = "earth";
77+
assert_eq!(slab[world], "earth");
78+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use std::sync::Arc;
2+
use try_lock::TryLock;
3+
4+
pub fn try_lock_example1() {
5+
// a thing we want to share
6+
struct Widget {
7+
name: String,
8+
}
9+
10+
// lock it up!
11+
let widget1 = Arc::new(TryLock::new(Widget {
12+
name: "Spanner".into(),
13+
}));
14+
15+
let widget2 = widget1.clone();
16+
17+
// mutate the widget
18+
let mut locked = widget1.try_lock().expect("example isn't locked yet");
19+
locked.name.push_str(" Bundle");
20+
21+
// hands off, buddy
22+
let not_locked = widget2.try_lock();
23+
assert!(not_locked.is_none(), "widget1 has the lock");
24+
25+
// ok, you can have it
26+
drop(locked);
27+
28+
let locked2 = widget2.try_lock().expect("widget1 lock is released");
29+
30+
assert_eq!(locked2.name, "Spanner Bundle");
31+
}

special/src/queue.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use concurrent_queue::ConcurrentQueue;
2+
use std::thread;
3+
use std::sync::Arc;
4+
5+
pub fn concurrent_queue_example() {
6+
let q = Arc::new(ConcurrentQueue::unbounded());
7+
8+
let q1 = q.clone();
9+
let whandle = thread::spawn(move || {
10+
for i in 0..10 {
11+
q1.push(i).unwrap();
12+
}
13+
});
14+
15+
let q2 = q.clone();
16+
let rhandle = thread::spawn(move || {
17+
loop {
18+
if let Ok(v) = q2.pop() {
19+
println!("get value {}", v);
20+
} else {
21+
println!("queue closed");
22+
break;
23+
}
24+
}
25+
});
26+
27+
whandle.join().unwrap();
28+
rhandle.join().unwrap();
29+
}

0 commit comments

Comments
 (0)