I obviously don't have a firm grasp on lifetimes, yet, so apologies up front.
I have the following code:
let mut my_hash: HashMap<String, u32> = HashMap::new();
// ... add data
for i in 0..5 {
let my_hash_clone = my_hash.clone();
// pass to a different thread, thus the need to clone
// -- the thread will not modify this data, so I'm trying
// to limit the overhead to the one-time copy/clone.
}
however, I get the following error:
---------------------- move occurs because my_hash has type HashMap<Utf8String, u32>, which does not implement the Copy trait
and that in-turn, creates a borrowing issue for the next iteration of the loop.
Am I even approaching this correctly? I've tried as many different permutations of fixes as I can think of without using an Arc < Mutex > > arrangement. The later actually works but causes performance issues from the threads trying to look up the data quickly and getting tied up waiting on each other.
In my mind, a clone should be straightforward, but this is kicking my tail...
If all the threads need is a read-only view only, you can use an Arc<HashMap>, without the Mutex. Then the clone will be cheap due to Arc, and access will be cheap die to the fact that Arc directly coerces to the plain shared reference.
this code compiles fine for me, so whatever error is in the code you ommited. without more info, best i can do is a wild guess: have you tried move closures?
If the threads don't mutate the data you don't need the Mutex, just an Arc<_> will be enough and basically free.
An even cheaper way would be using std::thread::scope to create the threads, which will allow you to use plain references to the HashMap. However this will only work if your threads are supposed to finish before the scope ends. For example:
let mut my_hash: HashMap<String, u32> = HashMap::new();
// ... add data
std::thread::scope(|s| {
for i in 0..5 {
s.spawn(|| {
// You can use `my_hash` here
});
}
// When it reaches this point it will wait for all threds to end, as it you `.join()`ed them.
})
Thanks for posting this -- I created a new project and verified your assessment. The full code had about 5 references scattered over several hundred lines and one of those lines referenced my_hash instead of my_hash_clone.
I literally spent about 4 hours chasing the wrong path - focused mainly on the Utf8String error.
Thanks for the reminder to verify my assumptions prior to looking for a solution!
Thanks for the idea. I can actually use this in another part of my code to simply things. I'm relatively new to Rust, so getting my head wrapped around intentional scoping will take a minute.
Yes. You and SkiFire13 correctly pointed out my unnecessary use of Mutex. This whole effort has been an exercise is simplifying / cleaning old code. I eliminated the original reason for the Mutex, and then missed the fact that I could simplify that part of the code.