如何创建全局可变布尔状态标志
How to create a global mutable bool status flag
前言:我研究了一下,知道它真的不是一个好东西idea/nor是不是地道的Rust有一个。完全接受解决此问题的其他方法的建议。
背景: 我有一个连接到 websocket 的控制台应用程序,一旦连接成功,服务器就会发送一条 "Connected" 消息。我有发送者,接收者是独立的线程,一切都很好。 connect()
调用后开始循环并在终端中放置提示,表示应用程序已准备好接收用户的输入。
问题:问题是当前执行流程调用connect,然后立即显示提示,然后应用程序收到服务器的消息,说明已连接.
我如何用高级语言解决这个问题: 放置一个全局 bool(我们称之为 ready
),一旦应用程序是 "ready" 然后显示提示。
我认为这在 Rust 中看起来如何:
//Possible global ready flag with 3 states (true, false, None)
let ready: Option<&mut bool> = None;
fn main(){
welcome_message(); //Displays a "Connecting..." message to the user
//These are special callback I created and basically when the
//message is received the `connected` is called.
//If there was an error getting the message (service is down)
//then `not_connected` is called. *This is working code*
let p = mylib::Promise::new(connected, not_connected);
//Call connect and start websocket send and receive threads
mylib::connect(p);
//Loop for user input
loop {
match ready {
Some(x) => {
if x == true { //If ready is true, display the prompt
match prompt_input() {
true => {},
false => break,
}
} else {
return; //If ready is false, quit the program
}
},
None => {} //Ready is None, so continue waiting
}
}
}
fn connected() -> &mut bool{
println!("Connected to Service! Please enter a command. (hint: help)\n\n");
true
}
fn not_connected() -> &mut bool{
println!("Connection to Service failed :(");
false
}
问题:
你会如何在 Rust 中解决这个问题?我尝试将它传递给所有库方法调用,但遇到了一些关于在 FnOnce() 闭包中借用不可变对象的主要问题。
听起来您确实希望有两个线程通过 通道 进行通信。看看这个例子:
use std::thread;
use std::sync::mpsc;
use std::time::Duration;
enum ConsoleEvent {
Connected,
Disconnected,
}
fn main() {
let (console_tx, console_rx) = mpsc::channel();
let socket = thread::spawn(move || {
println!("socket: started!");
// pretend we are taking time to connect
thread::sleep(Duration::from_millis(300));
println!("socket: connected!");
console_tx.send(ConsoleEvent::Connected).unwrap();
// pretend we are taking time to transfer
thread::sleep(Duration::from_millis(300));
println!("socket: disconnected!");
console_tx.send(ConsoleEvent::Disconnected).unwrap();
println!("socket: closed!");
});
let console = thread::spawn(move || {
println!("console: started!");
for msg in console_rx.iter() {
match msg {
ConsoleEvent::Connected => println!("console: I'm connected!"),
ConsoleEvent::Disconnected => {
println!("console: I'm disconnected!");
break;
}
}
}
});
socket.join().expect("Unable to join socket thread");
console.join().expect("Unable to join console thread");
}
这里有 3 个线程在运行:
- 主线程。
- 要从 "socket" 中读取的线程。
- 与用户交互的线程。
这些线程中的每一个都可以保持它自己的非共享 状态。这使得对每个线程的推理变得更容易。线程使用 channel
在它们之间安全地发送更新。跨线程的数据封装在一个枚举中。
当我运行这个时,我得到
socket: started!
console: started!
socket: connected!
console: I'm connected!
socket: disconnected!
socket: closed!
console: I'm disconnected!
前言:我研究了一下,知道它真的不是一个好东西idea/nor是不是地道的Rust有一个。完全接受解决此问题的其他方法的建议。
背景: 我有一个连接到 websocket 的控制台应用程序,一旦连接成功,服务器就会发送一条 "Connected" 消息。我有发送者,接收者是独立的线程,一切都很好。 connect()
调用后开始循环并在终端中放置提示,表示应用程序已准备好接收用户的输入。
问题:问题是当前执行流程调用connect,然后立即显示提示,然后应用程序收到服务器的消息,说明已连接.
我如何用高级语言解决这个问题: 放置一个全局 bool(我们称之为 ready
),一旦应用程序是 "ready" 然后显示提示。
我认为这在 Rust 中看起来如何:
//Possible global ready flag with 3 states (true, false, None)
let ready: Option<&mut bool> = None;
fn main(){
welcome_message(); //Displays a "Connecting..." message to the user
//These are special callback I created and basically when the
//message is received the `connected` is called.
//If there was an error getting the message (service is down)
//then `not_connected` is called. *This is working code*
let p = mylib::Promise::new(connected, not_connected);
//Call connect and start websocket send and receive threads
mylib::connect(p);
//Loop for user input
loop {
match ready {
Some(x) => {
if x == true { //If ready is true, display the prompt
match prompt_input() {
true => {},
false => break,
}
} else {
return; //If ready is false, quit the program
}
},
None => {} //Ready is None, so continue waiting
}
}
}
fn connected() -> &mut bool{
println!("Connected to Service! Please enter a command. (hint: help)\n\n");
true
}
fn not_connected() -> &mut bool{
println!("Connection to Service failed :(");
false
}
问题: 你会如何在 Rust 中解决这个问题?我尝试将它传递给所有库方法调用,但遇到了一些关于在 FnOnce() 闭包中借用不可变对象的主要问题。
听起来您确实希望有两个线程通过 通道 进行通信。看看这个例子:
use std::thread;
use std::sync::mpsc;
use std::time::Duration;
enum ConsoleEvent {
Connected,
Disconnected,
}
fn main() {
let (console_tx, console_rx) = mpsc::channel();
let socket = thread::spawn(move || {
println!("socket: started!");
// pretend we are taking time to connect
thread::sleep(Duration::from_millis(300));
println!("socket: connected!");
console_tx.send(ConsoleEvent::Connected).unwrap();
// pretend we are taking time to transfer
thread::sleep(Duration::from_millis(300));
println!("socket: disconnected!");
console_tx.send(ConsoleEvent::Disconnected).unwrap();
println!("socket: closed!");
});
let console = thread::spawn(move || {
println!("console: started!");
for msg in console_rx.iter() {
match msg {
ConsoleEvent::Connected => println!("console: I'm connected!"),
ConsoleEvent::Disconnected => {
println!("console: I'm disconnected!");
break;
}
}
}
});
socket.join().expect("Unable to join socket thread");
console.join().expect("Unable to join console thread");
}
这里有 3 个线程在运行:
- 主线程。
- 要从 "socket" 中读取的线程。
- 与用户交互的线程。
这些线程中的每一个都可以保持它自己的非共享 状态。这使得对每个线程的推理变得更容易。线程使用 channel
在它们之间安全地发送更新。跨线程的数据封装在一个枚举中。
当我运行这个时,我得到
socket: started!
console: started!
socket: connected!
console: I'm connected!
socket: disconnected!
socket: closed!
console: I'm disconnected!