How to resolve problem about future cannot be sent between threads safely without tokio-mutex and channel?

Viewed 47

I know this question has been asked by many people, and in the past, either tokio::sync::Mutex was recommended to replace std::sync::Mutex, or it was made to be called in the same task via Channel.

What I want to know is if there is any other way to do this? In the case of my current TcpStream send.

#[tokio::test]
async fn test_send_arc_mutex_tcps() {
    async fn one(tcps: Arc<std::sync::Mutex<TcpStream>>, src: String) {
        tcps.lock().unwrap().write(src.as_bytes()).await.unwrap();
        //--------------------                      ^^^^^^ await occurs here, with `tcps.lock().unwrap()` maybe used later
        // |
        // has type `std::sync::MutexGuard<'_, tokio::net::TcpStream>` which is not `Send`
    }

    async fn two(tcps: Arc<std::sync::Mutex<TcpStream>>, src: String) {
        let w = {
            let mut tcps = tcps.lock().unwrap();
            tcps.write(src.as_bytes()) // `tcps` does not live long enough
                                       // borrowed value does not live long enough
        };
        let _ = w.await;
    }

    let tcps = TcpStream::connect("192.168.1.10:8080").await.unwrap();
    let tcps = Arc::new(std::sync::Mutex::new(tcps));
    let datum = [
        "hello".to_string(),
        "rustl".to_string(),
        "tokio".to_string(),
    ];
    for data in datum.iter() {
        let tcps1 = tcps.clone();
        let tcps2 = tcps.clone();
        let data1 = data.clone();
        let data2 = data.clone();
        tokio::spawn(async move {
            // error: future cannot be sent between threads safely
            one(tcps1, data1).await;
            two(tcps2, data2).await;
        });
    }
}
0 Answers
Related