Skip to content

Commit 210776b

Browse files
author
chaoyuepan
committed
add primitives and syncs examples
1 parent 5df3c1b commit 210776b

File tree

30 files changed

+886
-2
lines changed

30 files changed

+886
-2
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
[workspace]
2-
members = ["thread", "asyncwait", "pool"]
2+
members = ["thread", "pool", "asyncwait", "primitive", "collections", "process", "syncs"]

asyncwait/src/future.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
use std::sync::Arc;
3+
use std::sync::Mutex;
4+
use std::task::Waker;
5+
use std::task::Poll;
6+
use std::task::Context;
7+
use std::time::Duration;
8+
use std::thread;
9+
use std::future::Future;
10+
use std::pin::Pin;
11+
12+
13+
pub struct TimerFuture {
14+
shared_state: Arc<Mutex<SharedState>>,
15+
}
16+
17+
/// Shared state between the future and the waiting thread
18+
struct SharedState {
19+
completed: bool,
20+
waker: Option<Waker>,
21+
}
22+
23+
impl TimerFuture {
24+
pub fn new(duration: Duration) -> TimerFuture {
25+
let shared_state = Arc::new(Mutex::new(SharedState {
26+
completed: false,
27+
waker: None,
28+
}));
29+
30+
let thread_shared_state = shared_state.clone();
31+
32+
thread::spawn(move || {
33+
thread::sleep(duration);
34+
let mut shared_state = thread_shared_state.lock().unwrap();
35+
36+
shared_state.completed = true;
37+
if let Some(waker) = shared_state.waker.take() {
38+
waker.wake();
39+
}
40+
});
41+
42+
TimerFuture { shared_state }
43+
}
44+
}
45+
46+
impl Future for TimerFuture {
47+
type Output = ();
48+
49+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
50+
let mut shared_state = self.shared_state.lock().unwrap();
51+
52+
if shared_state.completed {
53+
println!("TimerFuture completed");
54+
Poll::Ready(())
55+
} else {
56+
shared_state.waker = Some(cx.waker().clone());
57+
Poll::Pending
58+
}
59+
}
60+
}
61+
62+
pub fn timefuture_async() {
63+
let tf = TimerFuture::new(Duration::from_millis(1000));
64+
smol::block_on(tf)
65+
}

asyncwait/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
pub mod asyncio;
2+
pub mod future;
23

34
pub use asyncio::*;
5+
pub use future::*;
46

57
use futures::channel::mpsc;
68
use futures::executor::{self, ThreadPool};

asyncwait/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ fn main() {
77
async_std();
88
smol_async();
99

10+
timefuture_async();
11+
1012
join();
1113
select();
1214

collections/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "collections"
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]

collections/src/lib.rs

Whitespace-only changes.

collections/src/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use collections;
2+
3+
fn main() {
4+
println!("Hello, world!");
5+
}

primitive/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "primitive"
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]

primitive/src/box.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Box<T>, casually referred to as a ‘box’, provides the simplest form of heap allocation in Rust.
2+
// Boxes provide ownership for this allocation, and drop their contents when they go out of scope.
3+
// Boxes also ensure that they never allocate more than isize::MAX bytes.
4+
pub fn box_example() {
5+
let b = Box::new(5);
6+
println!("b = {}", b);
7+
}
8+
9+
pub fn box_example2() {
10+
#[derive(Debug)]
11+
enum List<T> {
12+
Cons(T, Box<List<T>>),
13+
Nil,
14+
}
15+
16+
let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
17+
println!("{list:?}");
18+
}
19+

primitive/src/cell.rs

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#![allow(dead_code)]
2+
3+
use std::cell::*;
4+
use std::collections::HashMap;
5+
use std::rc::Rc;
6+
7+
// Shareable mutable containers.
8+
// Shareable mutable containers exist to permit mutability in a controlled manner, even in the presence of aliasing.
9+
// Both Cell<T> and RefCell<T> allow doing this in a single-threaded way. However, neither Cell<T> nor RefCell<T> are thread safe (they do not implement Sync).
10+
// If you need to do aliasing and mutation between multiple threads it is possible to use Mutex<T>, RwLock<T> or atomic types.
11+
//
12+
// Cell<T> implements interior mutability by moving values in and out of the Cell<T>.
13+
// To use references instead of values, one must use the RefCell<T> type, acquiring a write lock before mutating.
14+
15+
pub fn cell_example() {
16+
struct SomeStruct {
17+
regular_field: u8,
18+
special_field: Cell<u8>,
19+
}
20+
21+
// not mutable
22+
let my_struct = SomeStruct {
23+
regular_field: 0,
24+
special_field: Cell::new(1),
25+
};
26+
27+
let _ = my_struct.regular_field;
28+
// my_struct.regular_field = 100;
29+
my_struct.special_field.set(100);
30+
}
31+
32+
pub fn refcell_example() {
33+
#[allow(dead_code)]
34+
struct SomeStruct {
35+
regular_field: u8,
36+
special_field: RefCell<u8>,
37+
}
38+
39+
// not mutable
40+
let my_struct = SomeStruct {
41+
regular_field: 0,
42+
special_field: RefCell::new(1),
43+
};
44+
45+
// my_struct.regular_field = 100;
46+
let mut special_field = (&my_struct.special_field).borrow_mut();
47+
*special_field = 100;
48+
drop(special_field);
49+
50+
println!("special_field = {}", my_struct.special_field.borrow());
51+
52+
(&my_struct).special_field.replace(200);
53+
println!("special_field = {}", my_struct.special_field.borrow());
54+
}
55+
56+
pub fn rc_refcell_example() {
57+
let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
58+
// Create a new block to limit the scope of the dynamic borrow
59+
{
60+
let mut map: RefMut<_> = shared_map.borrow_mut();
61+
map.insert("africa", 92388);
62+
map.insert("kyoto", 11837);
63+
map.insert("piccadilly", 11826);
64+
map.insert("marbles", 38);
65+
}
66+
67+
// Note that if we had not let the previous borrow of the cache fall out
68+
// of scope then the subsequent borrow would cause a dynamic thread panic.
69+
// This is the major hazard of using `RefCell`.
70+
let total: i32 = shared_map.borrow().values().sum();
71+
println!("{total}");
72+
}
73+
74+
pub fn once_cell_example() {
75+
let cell = OnceCell::new();
76+
assert!(cell.get().is_none());
77+
78+
let value: &String = cell.get_or_init(|| "Hello, World!".to_string());
79+
assert_eq!(value, "Hello, World!");
80+
assert!(cell.get().is_some());
81+
}
82+
83+
pub fn lazy_cell_example() {
84+
let lazy: LazyCell<i32> = LazyCell::new(|| {
85+
println!("initializing");
86+
92
87+
});
88+
println!("one_cell ready");
89+
println!("{}", *lazy);
90+
println!("{}", *lazy);
91+
}
92+
93+
pub fn myrc_example() {
94+
let s = example::Rc::new("hello world");
95+
let s1 = s.clone();
96+
97+
let v = s1.value();
98+
println!("myrc value: {}", v);
99+
}
100+
101+
pub mod example {
102+
use std::cell::Cell;
103+
use std::marker::PhantomData;
104+
use std::process::abort;
105+
use std::ptr::NonNull;
106+
107+
pub struct Rc<T: ?Sized> {
108+
ptr: NonNull<RcBox<T>>,
109+
phantom: PhantomData<RcBox<T>>,
110+
}
111+
112+
impl<T> Rc<T> {
113+
pub fn new(t: T) -> Self {
114+
let ptr = Box::new(RcBox {
115+
strong: Cell::new(1),
116+
refcount: Cell::new(1),
117+
value: t,
118+
});
119+
let ptr = NonNull::new(Box::into_raw(ptr)).unwrap();
120+
Self {
121+
ptr: ptr,
122+
phantom: PhantomData,
123+
}
124+
}
125+
126+
pub fn value(&self) -> &T {
127+
&self.inner().value
128+
}
129+
}
130+
131+
132+
struct RcBox<T: ?Sized> {
133+
strong: Cell<usize>,
134+
refcount: Cell<usize>,
135+
value: T,
136+
}
137+
138+
impl<T: ?Sized> Clone for Rc<T> {
139+
fn clone(&self) -> Rc<T> {
140+
self.inc_strong();
141+
Rc {
142+
ptr: self.ptr,
143+
phantom: PhantomData,
144+
}
145+
}
146+
}
147+
148+
trait RcBoxPtr<T: ?Sized> {
149+
fn inner(&self) -> &RcBox<T>;
150+
151+
fn strong(&self) -> usize {
152+
self.inner().strong.get()
153+
}
154+
155+
fn inc_strong(&self) {
156+
self.inner()
157+
.strong
158+
.set(self.strong().checked_add(1).unwrap_or_else(|| abort()));
159+
}
160+
}
161+
162+
impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
163+
fn inner(&self) -> &RcBox<T> {
164+
unsafe { self.ptr.as_ref() }
165+
}
166+
}
167+
}

0 commit comments

Comments
 (0)