Skip to content

Commit 1891d4f

Browse files
committed
all examples in ch10 finished!
1 parent c3077fb commit 1891d4f

File tree

13 files changed

+623
-45
lines changed

13 files changed

+623
-45
lines changed
File renamed without changes.

ch10/d-pin/src/main.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
use std::{
2+
marker::PhantomPinned,
3+
pin::{pin, Pin},
4+
};
5+
6+
fn main() {
7+
// heap_pinning();
8+
//stack_pinning_manual();
9+
//stack_pinning_manual_problem();
10+
//stack_pinning_macro();
11+
//pin_projection();
12+
}
13+
14+
fn heap_pinning() {
15+
let mut x = Box::pin(MaybeSelfRef::default());
16+
x.as_mut().init();
17+
println!("{}", x.as_ref().a);
18+
*x.as_mut().b().unwrap() = 2;
19+
println!("{}", x.as_ref().a);
20+
}
21+
22+
// Pinning stack
23+
fn stack_pinning_manual() {
24+
let mut x = MaybeSelfRef::default();
25+
let mut x = unsafe { Pin::new_unchecked(&mut x) };
26+
x.as_mut().init();
27+
println!("{}", x.as_ref().a);
28+
*x.as_mut().b().unwrap() = 2;
29+
println!("{}", x.as_ref().a);
30+
}
31+
32+
use std::mem::swap;
33+
fn stack_pinning_manual_problem() {
34+
let mut x = MaybeSelfRef::default();
35+
let mut y = MaybeSelfRef::default();
36+
37+
{
38+
let mut x = unsafe { Pin::new_unchecked(&mut x) };
39+
x.as_mut().init();
40+
*x.as_mut().b().unwrap() = 2;
41+
}
42+
swap(&mut x, &mut y);
43+
println!("
44+
x: {{
45+
+----->a: {:p},
46+
| b: {:?},
47+
| }}
48+
|
49+
| y: {{
50+
| a: {:p},
51+
+-----|b: {:?},
52+
}}",
53+
&x.a,
54+
x.b,
55+
&y.a,
56+
y.b,
57+
);
58+
}
59+
60+
fn stack_pinning_macro() {
61+
let mut x = pin!(MaybeSelfRef::default());
62+
MaybeSelfRef::init(x.as_mut());
63+
println!("{}", x.as_ref().a);
64+
*x.as_mut().b().unwrap() = 2;
65+
println!("{}", x.as_ref().a);
66+
}
67+
68+
fn pin_projection() {
69+
#[derive(Default)]
70+
struct Foo {
71+
a: MaybeSelfRef,
72+
b: String,
73+
}
74+
75+
impl Foo {
76+
fn a(self: Pin<&mut Self>) -> Pin<&mut MaybeSelfRef> {
77+
unsafe {
78+
self.map_unchecked_mut(|s| &mut s.a)
79+
}
80+
}
81+
82+
fn b(self: Pin<&mut Self>) -> &mut String {
83+
unsafe {
84+
&mut self.get_unchecked_mut().b
85+
}
86+
}
87+
}
88+
}
89+
90+
91+
#[derive(Default, Debug)]
92+
struct MaybeSelfRef {
93+
a: usize,
94+
b: Option<*mut usize>,
95+
_pin: PhantomPinned,
96+
}
97+
98+
impl MaybeSelfRef {
99+
fn init(self: Pin<&mut Self>) {
100+
unsafe {
101+
let Self { a, b, .. } = self.get_unchecked_mut();
102+
*b = Some(a);
103+
}
104+
}
105+
106+
fn b(self: Pin<&mut Self>) -> Option<&mut usize> {
107+
unsafe { self.get_unchecked_mut().b.map(|b| &mut *b) }
108+
}
109+
}
File renamed without changes.
File renamed without changes.

ch10/e-coroutines-pin/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "e-coroutines-pin"
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+
mio = { version = "0.8", features = ["net", "os-poll"] }

ch10/e-coroutines-pin/src/future.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// NEW
2+
use std::pin::Pin;
3+
4+
use crate::runtime::Waker;
5+
6+
7+
pub trait Future {
8+
type Output;
9+
10+
fn poll(self: Pin<&mut Self>, waker: &Waker) -> PollState<Self::Output>;
11+
}
12+
13+
pub enum PollState<T> {
14+
Ready(T),
15+
NotReady,
16+
}
17+
18+
pub fn join_all<F: Future>(futures: Vec<F>) -> JoinAll<F> {
19+
let futures = futures.into_iter().map(|f| (false, Box::pin(f))).collect();
20+
JoinAll {
21+
futures,
22+
finished_count: 0,
23+
}
24+
}
25+
26+
pub struct JoinAll<F: Future> {
27+
futures: Vec<(bool, Pin<Box<F>>)>,
28+
finished_count: usize,
29+
}
30+
31+
impl<F: Future> Future for JoinAll<F> {
32+
type Output = String;
33+
fn poll(self: Pin<&mut Self>, waker: &Waker) -> PollState<Self::Output> {
34+
let Self { futures, finished_count} = self.get_mut();
35+
for (finished, fut) in futures.iter_mut() {
36+
if *finished {
37+
continue;
38+
}
39+
40+
match fut.as_mut().poll(waker) {
41+
PollState::Ready(_) => {
42+
*finished = true;
43+
*finished_count += 1;
44+
}
45+
46+
PollState::NotReady => continue,
47+
}
48+
}
49+
50+
if *finished_count == futures.len() {
51+
PollState::Ready(String::new())
52+
} else {
53+
PollState::NotReady
54+
}
55+
}
56+
}

ch10/e-coroutines-pin/src/http.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
use std::{io::{ErrorKind, Read, Write}, pin::Pin};
2+
3+
use mio::{Interest, Registry, Token};
4+
5+
use crate::{
6+
future::PollState,
7+
runtime::{self, reactor, Waker},
8+
Future,
9+
};
10+
11+
fn get_req(path: &str) -> String {
12+
format!(
13+
"GET {path} HTTP/1.1\r\n\
14+
Host: localhost\r\n\
15+
Connection: close\r\n\
16+
\r\n"
17+
)
18+
}
19+
20+
pub struct Http;
21+
22+
impl Http {
23+
pub fn get(path: &str) -> impl Future<Output = String> {
24+
HttpGetFuture::new(path.to_string())
25+
}
26+
}
27+
struct HttpGetFuture {
28+
stream: Option<mio::net::TcpStream>,
29+
buffer: Vec<u8>,
30+
path: String,
31+
id: usize,
32+
}
33+
34+
impl HttpGetFuture {
35+
fn new(path: String) -> Self {
36+
let id = reactor().next_id();
37+
Self {
38+
stream: None,
39+
buffer: vec![],
40+
path,
41+
id,
42+
}
43+
}
44+
45+
fn write_request(&mut self) {
46+
let stream = std::net::TcpStream::connect("127.0.0.1:8080").unwrap();
47+
stream.set_nonblocking(true).unwrap();
48+
let mut stream = mio::net::TcpStream::from_std(stream);
49+
stream.write_all(get_req(&self.path).as_bytes()).unwrap();
50+
self.stream = Some(stream);
51+
}
52+
}
53+
54+
impl Future for HttpGetFuture {
55+
type Output = String;
56+
57+
fn poll(self: Pin<&mut Self>, waker: &Waker) -> PollState<Self::Output> {
58+
// If this is first time polled, start the operation
59+
// see: https://users.rust-lang.org/t/is-it-bad-behaviour-for-a-future-or-stream-to-do-something-before-being-polled/61353
60+
// Avoid dns lookup this time
61+
let this = self.get_mut();
62+
63+
if this.stream.is_none() {
64+
println!("FIRST POLL - START OPERATION");
65+
this.write_request();
66+
// CHANGED
67+
let stream = this.stream.as_mut().unwrap();
68+
runtime::reactor().register(stream, Interest::READABLE, this.id);
69+
runtime::reactor().set_waker(waker, this.id);
70+
// ============
71+
}
72+
73+
let mut buff = vec![0u8; 147];
74+
loop {
75+
match this.stream.as_mut().unwrap().read(&mut buff) {
76+
Ok(0) => {
77+
let s = String::from_utf8_lossy(&this.buffer).to_string();
78+
runtime::reactor().deregister(this.stream.as_mut().unwrap(), this.id);
79+
break PollState::Ready(s.to_string());
80+
}
81+
Ok(n) => {
82+
this.buffer.extend(&buff[0..n]);
83+
continue;
84+
}
85+
Err(e) if e.kind() == ErrorKind::WouldBlock => {
86+
// always store the last given Waker
87+
runtime::reactor().set_waker(waker, this.id);
88+
break PollState::NotReady;
89+
}
90+
91+
Err(e) => panic!("{e:?}"),
92+
}
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)