global-variables - 如何创建全局可变 bool 状态标志

标签 global-variables rust

前言:我做了研究,知道这真的不是一个好主意/也不是惯用的 Rust。完全接受有关解决此问题的其他方法的建议。

背景: 我有一个连接到 websocket 的控制台应用程序,一旦连接成功,服务器就会发送“已连接”消息。我有发送者,接收者是独立的线程,一切都很好。在 connect() 调用之后,一个循环开始并在终端中放置一个提示,表示应用程序已准备好接收用户的输入。

问题:问题是当前的执行流程调用连接,然后立即显示提示,然后应用程序收到服务器的消息,表明它已连接。

我如何用高级语言解决这个问题: 放置一个全局 bool 值(我们称它为 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() 闭包中借用不可变对象(immutable对象)的主要问题。

最佳答案

听起来您确实希望有两个线程通过 channel 进行通信。看看这个例子:

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 个线程在起作用:

  1. 主线程。
  2. 从“套接字”中读取的线程。
  3. 与用户交互的线程。

这些线程中的每一个都可以保持它自己的非共享 状态。这使得对每个线程的推理变得更容易。线程使用 channel安全地在它们之间发送更新。跨线程的数据被封装在一个枚举中。

当我运行这个时,我得到

socket: started!
console: started!
socket: connected!
console: I'm connected!
socket: disconnected!
socket: closed!
console: I'm disconnected!

关于global-variables - 如何创建全局可变 bool 状态标志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28401589/

相关文章:

javascript - 无法将 $.get 返回的数据传递给 JavaScript 中的变量或数组

c - 特定功能与许多参数与上下文相关

c++ - 头文件中的 C 与 C++ 全局变量

generics - Rust Option<impl Fn(i64)> 的空显式泛型参数

rust - clippy::missing_const_for_fn在构造函数和获取方法上触发。那是真的吗?

rust - 如何从构建脚本 (build.rs) 访问当前的 cargo profile (build, test, bench, doc, ....)

javascript - 为什么我的变量在 javascript 中返回未定义?

rust - 为什么我的 Future 实现在被轮询一次并且 NotReady 后被阻止?

generics - 接受受多个特征中的任何一个约束的参数的函数

javascript - NodeJS 全局变量不可重新分配