Michael Stachowsky
Michael Stachowsky

Reputation: 787

How to update a value in a CHashMap based on the value itself?

I am trying to create a concurrent hash map that stores Strings as keys and i32s as values. Essentially, I am parsing a large corpus of text and every time the same String is encountered, I add 1 to value that String maps to. Using HashMap I can do this just fine, but it is not concurrent, and I'd like to parallelize this.

The problem I seem to be encountering is that I need to read the value, then update that value. Since CHashMap locks the value (as it should), this is not possible. However, if values cannot be updated then CHashMap is useless, which implies that I must be doing something wrong. Here is the relevant code. Note that the function "token_split" works and the string parsing in general works just fine. This algorithm has been tested thoroughly in a single-threaded environment using HashMap. What you see here is that same single-threaded code, but this time using CHashMap instead of HashMap. The text corpus is inside of a big vector.

let mut d1: CHashMap<String,i32> = CHashMap::new();
    let sep = Regex::new(r"([ ]+)").unwrap();
    for i in 0..la.len() {
        let strs: Vec<String> = token_split(&la[i],&sep);
        if let mut Some(count) = d1.get_mut(&strs[0]){
            d1.insert(strs[0].clone(),count+1);
        }
        else{
            d1.insert(strs[0].clone(),1);
        }
    }

When compiled (or when using cargo check), the error is:

error[E0369]: cannot add `{integer}` to `WriteGuard<'_, String, i32>`
  --> src/main.rs:61:35
   |
61 |             d1.insert(strs[0].clone(),count+1);
   |                                       -----^- {integer}
   |                                       |
   |                                       WriteGuard<'_, String, i32>

Upvotes: 0

Views: 187

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 71380

To access the value guarded by the WriteGuard dereference it:

d1.insert(strs[0].clone(), *count + 1);

However, this is still incorrect as it may deadlock. You already have a guard for the entry, just modify it:

*count += 1;

Upvotes: 1

Related Questions