Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

question when iter to remove key #284

Open
vCassius opened this issue Oct 20, 2023 · 1 comment
Open

question when iter to remove key #284

vCassius opened this issue Oct 20, 2023 · 1 comment

Comments

@vCassius
Copy link

vCassius commented Oct 20, 2023

will fail to remove key when iter,i don't know why.

use dashmap::DashMap;
use serde::{Deserialize, Serialize};
use std::process::exit;
use std::time::Duration;
use tokio::sync::OnceCell;
use tokio::time::sleep;
pub static MESSAGE: OnceCell<DashMap<String, i64>> = OnceCell::const_new();
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Message {
    pub id: u32,
    pub data_len: u32,
    pub data: String,
}

pub enum MessageType {
    Write(Message),
    Close,
}

#[tokio::main]
async fn main() {
    match MESSAGE.set(DashMap::new()) {
        Ok(_) => {}
        Err(e) => {
            println!("fail to set message,err: {e}");
            exit(-1)
        }
    };
    let mut handles = Vec::new();
    let insert = tokio::spawn(async move { insert_hashmap().await });
    handles.push(insert);
    let read = tokio::spawn(async move { read_hashmap().await });
    handles.push(read);
    for h in handles {
        match h.await {
            Ok(_) => {}
            Err(e) => {
                println!("handle err: {e}")
            }
        }
    }
}
async fn insert_hashmap() {
    let Some(message) = MESSAGE.get() else {
        println!("fail to get global static router pool");
        exit(-1)
    };
    let mut count = 0u64;
    loop {
        let value = count + 1;
        message.insert(count.to_string(), value as i64);
        println!("insert key: {value} value: {value} succeed");
        count += 1
    }
}

async fn read_hashmap() {
    let Some(message) = MESSAGE.get() else {
        println!("fail to get global static router pool");
        exit(-1)
    };
    loop {
        // sleep(Duration::from_millis(10)).await;
        for m in message.iter() {
            message.remove(m.key());
            println!("got key: {} value: {}", m.key(), m.value())
        }
    }
}
@AshfordN
Copy link

AshfordN commented Apr 8, 2024

Does the process appear to freeze after the first attempt? If so, then you are likely experiencing a deadlock. The docs for DashMap::remove() says this:

Locking behaviour: May deadlock if called when holding any sort of reference into the map

In your case, you are holding a reference to m while also trying to remove that element. For something like this, consider using DashMap::retain() instead.

// sleep(Duration::from_millis(10)).await;
message.retain(|key, value| {
    println!("got key: {key} value: {value}");

    false
});

As a side note, it is better to isolate your issue as a minimal reproducible example next time. The code above was quite a bit to unpack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants