[SOLVED] Is this way of using map with rc correct?

#1

I have a caching mechanism. I am planning to use the following type.

 std::sync::Arc<std::sync::RwLock<std::collections::HashMap<String, Rc<crate::user::user_data>>>>;

My goal here, data should be accessed by multiple threads (Arc) it should not have race conditions (RwLock) and finally, I don’t want to clone the values but want to be able to access the originals (Rc).
and now and then I should be able to update the fields of the user_data contained in the Rc.
Is this structure correct, am I missing or overlooking something?

0 Likes

#2

Rc is permanently tied to the thread it has been created on, so types containing Rc won’t be usable across threads (because another thread could lock the lock, clone Rc from under it, and you’d have two thread-unsafe Rcs in two threads). You need Arc everywhere.

Other than that, it is correct.

BTW, the type is a bit hard to read. You can shorten the names with use statements:

use std::sync::Arc;
use std::sync::RwLock;
1 Like

#3

Thanks. Btw actually i was thinking do i rally need the top level Arc to share RwLock since it makes sure single write access at a time ? I am still having difficulty with all those pointer types :slight_smile:

0 Likes

#4

The Rc inside will make the entire thing not threadsafe, so you will have to use Arc inside the Hashmap too. This will fail to compile if used in a multithreaded context because Rc is !Send.

1 Like

#5

If you’re going to send the cache to multiple threads, you will need the top-level Arc, so that each thread may have its own “copy” without having to coordinate lifetimes.

It’s also avoidable if you share it differently, e.g. it’s &RwLock<_> shared by scoped threadpool or rayon iterator.

Arc has a cost only when you .clone() it, and that cost is still tiny, so generally there’s no reason to bend backwards to avoid it.

2 Likes

#6

i see thanks you all for clarity.

1 Like