user19864059
user19864059

Reputation: 33

Why does !Send value that is drop()'d before .await mean the Future is !Send?

The logic of test_use_std_mutex_1 and test_use_std_mutex_2 is the same. Why does one report an error while the other compiles successfully?

fn main() {
    let rt = tokio::runtime::Builder::new_multi_thread().worker_threads(2)
        .enable_all().build().unwrap();
    rt.block_on(async {
        let (sen, mut rec) = tokio::sync::mpsc::channel::<()>(1);
        // Why can it be compiled by commenting out here? Isn't their logic the same?
        tokio::spawn(test_use_std_mutex_1(sen.clone()));
        tokio::spawn(test_use_std_mutex_2(sen.clone()));
        drop(sen);
        let _ = rec.recv().await;
        println!("over");
    });
}

async fn test_use_std_mutex_1(sen: Sender<()>) {
    let _sen = sen;
    let mut rwlock_list: Arc<Mutex<LinkedList<String>>> = Default::default();
    let mut lock = rwlock_list.lock().unwrap();
    println!("push_back hello");
    lock.push_back("hello".to_string());
    // Is it not deleted here?
    drop(lock);
    time::sleep(Duration::from_secs(1)).await;
}

async fn test_use_std_mutex_2(sen: Sender<()>) {
    let _sen = sen;
    let mut rwlock_list: Arc<Mutex<LinkedList<String>>> = Default::default();
    {
        let mut lock = rwlock_list.lock().unwrap();
        println!("push_back hello");
        lock.push_back("hello".to_string());
    }
    time::sleep(Duration::from_secs(1)).await;
}
error: future cannot be sent between threads safely
   --> src\main.rs:39:22
    |
39  |         tokio::spawn(test_use_std_mutex_1(sen.clone()));
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `test_use_std_mutex_1` is not `Send`
    |
    = help: within `impl futures_util::Future<Output = ()>`, the trait `Send` is not implemented for `std::sync::MutexGuard<'_, LinkedList<std::string::String>>`
note: future is not `Send` as this value is used across an await
   --> src\main.rs:55:40
    |
50  |     let mut lock = rwlock_list.lock().unwrap();
    |         -------- has type `std::sync::MutexGuard<'_, LinkedList<std::string::String>>` which is not `Send`
...
55  |     time::sleep(Duration::from_secs(1)).await;
    |                                        ^^^^^^ await occurs here, with `mut lock` maybe used later
56  | }
    | - `mut lock` is later dropped here

What is causing this?

Upvotes: 3

Views: 281

Answers (1)

Related Questions