- rust thread is actually running in a real thread, or is it a virtual thread ?
- rust thread.sleep cause main thread sleeped.
my test code is
use std::thread;
use std::time::{Duration};
use chrono::Local;
struct HelloWorld { }
impl HelloWorld {
fn output(&self) {
println!("HelloWorld.output! current thread is {:?}. time is {}", thread::current().id(), Local::now().format("%H:%M:%S.%3f"));
thread::sleep(Duration::from_secs(30));
println!("after sleeping current thread is {:?}. time is {}", thread::current().id(), Local::now().format("%H:%M:%S.%3f"));
}
fn say_hello(&self) {
thread::scope(|scope| {
scope.spawn( || {
self.output();
});
});
println!("after Thread. current thread is {:?}. time is {}", thread::current().id(), Local::now().format("%H:%M:%S.%3f"));
}
}
fn main() {
println!("Hello, main! current thread is {:?}, time is {}", thread::current().id(), Local::now().format("%H:%M:%S.%3f"));
let hw = HelloWorld {};
hw.say_hello();
println!("after. thread is {:?}, time is {}", thread::current().id(), Local::now().format("%H:%M:%S.%3f"));
}
click here to view test code runs video.
-------- update code with mio udp server test ---------
Cargo.toml
[dependencies]
chrono = "0.4.44"
mio = {version = "1.2.0", features = ["net", "os-poll", "os-ext"]}
main.rs
use chrono::Local;
use std::thread;
use std::time::Duration;
use mio::{event::Event, net::UdpSocket, Events, Interest, Poll, Token};
use std::{
io::{self, ErrorKind::WouldBlock},
str::from_utf8,
};
const SERVER: Token = Token(0);
struct HelloWorld {}
impl HelloWorld {
fn output(&self) {
println!(
"HelloWorld.output! current thread is {:?}. time is {}",
thread::current().id(),
Local::now().format("%H:%M:%S.%3f")
);
thread::sleep(Duration::from_secs(30));
println!(
"after sleeping current thread is {:?}. time is {}",
thread::current().id(),
Local::now().format("%H:%M:%S.%3f")
);
}
fn say_hello(&self) {
thread::scope(|scope| {
scope.spawn(|| {
self.output();
});
print!("say_hello ???-----");
});
println!(
"after Thread. current thread is {:?}. time is {}",
thread::current().id(),
Local::now().format("%H:%M:%S.%3f")
);
}
fn handle(&self, event: &Event, server: &UdpSocket) -> io::Result<()> {
if event.token() != SERVER {
return Ok(());
}
let mut buffer = vec![0; 4096];
loop {
match server.recv_from(&mut buffer) {
Ok((size, address)) => {
println!("客户端: {}", address);
let received = &buffer[..size];
let str = from_utf8(received).unwrap();
println!("收到数据:{}", str);
server.send_to(str.to_ascii_uppercase().as_bytes(), address)?;
}
Err(e) if e.kind() == WouldBlock => break,
Err(err) => return Err(err),
}
}
Ok(())
}
fn start(&self) -> io::Result<()> {
let addr = "127.0.0.1:4444".parse().unwrap();
let mut server = UdpSocket::bind(addr)?;
let mut poll = Poll::new()?;
let mut events = Events::with_capacity(128);
poll.registry()
.register(&mut server, SERVER, Interest::READABLE)?;
loop {
poll.poll(&mut events, None)?; <---- here
for event in events.iter() {
self.handle(event, &server)?;
}
}
}
fn test_start(&self) {
thread::scope(|scope| {
scope.spawn(|| {
let t = self.start();
});
});
}
}
fn main() {
println!(
"Hello, main! current thread is {:?}, time is {}",
thread::current().id(),
Local::now().format("%H:%M:%S.%3f")
);
let hw = HelloWorld {};
hw.test_start();
println!(
"after. thread is {:?}, time is {}",
thread::current().id(),
Local::now().format("%H:%M:%S.%3f")
);
}
run the code , it will be blcoked at
poll.poll(&mut events, None)?;
I want function start runs in a thread. if using scope , main thread should wait , if using thread::spawn , self should be borrowed .
------------------------- update2, -----------------------
use chrono::Local;
use std::thread;
use std::time::Duration;
use mio::{event::Event, net::UdpSocket, Events, Interest, Poll, Token, Waker};
use std::{io::{self, ErrorKind::WouldBlock}, str::from_utf8};
use std::thread::sleep;
const SERVER: Token = Token(0);
const WAKER_TOKEN: Token = Token(1);
struct UdpWrapper {
socket: UdpSocket,
events: Events,
poll: Poll,
waker: Waker,
}
impl UdpWrapper {
fn new(ip_address: &str) -> Self {
let addr = ip_address.parse().unwrap();
let mut server = UdpSocket::bind(addr).expect("Failed to bind UDP socket");
let poll = Poll::new().expect("Failed to create Poll");
let events = Events::with_capacity(128);
poll.registry().register(&mut server, SERVER, Interest::READABLE).expect("Failed to register socket");
let waker = Waker::new(poll.registry(), WAKER_TOKEN).expect("Failed to register waker");
UdpWrapper {
socket: server,
events: events,
poll: poll,
waker: waker
}
}
fn handle(event: &Event, server: &UdpSocket) -> io::Result<()> {
if event.token() == WAKER_TOKEN {
println!("received WAKER_TOKEN single。");
return Ok(());
}
if event.token() != SERVER {
return Ok(());
}
let mut buffer = vec![0; 4096];
loop {
match server.recv_from(&mut buffer) {
Ok((size, address)) => {
println!("客户端: {}", address);
let received = &buffer[..size];
let str = from_utf8(received).unwrap();
println!("收到数据:{}", str);
server.send_to(str.to_ascii_uppercase().as_bytes(), address)?;
}
Err(e) if e.kind() == WouldBlock => break,
Err(err) => return Err(err),
}
}
Ok(())
}
fn start(self) -> io::Result<()> {
let mut poll = self.poll;
let mut events = self.events;
let server = self.socket;
loop {
poll.poll(&mut events, None)?;
for event in events.iter() {
Self::handle(event, &server).expect("Failed to handle event");
}
}
}
// fn stop(&mut self){
fn stop(self){
let waker = self.waker;
waker.wake().expect("wake failed");
println!("-------------- waker.wake() ------------");
}
fn test_start(self) {
thread::spawn(move || {
self.start().unwrap();
});
}
}
fn main() {
println!(
"Hello, main! current thread is {:?}, time is {}",
thread::current().id(),
Local::now().format("%H:%M:%S.%3f")
);
let wrapper = UdpWrapper::new("127.0.0.1:9621");
wrapper.test_start(); <--- test_start() will take ownership of wrapper, so wrapper.stop() got error.
sleep(Duration::from_mins(2));
wrapper.stop(); <-----error here.
println!(
"after. thread is {:?}, time is {}",
thread::current().id(),
Local::now().format("%H:%M:%S.%3f")
);
}
