0

Is there an elegant way to iterate over each key-value pair in this concurrent hash map?

use std::collections::HashMap;
use std::hash::Hash;
use std::sync::RwLock;

const N_SHARDS: usize = 16;

#[derive(Default)]
struct ConcurrentHashMap<K, V>
where
    K: Eq + Hash,
{
    shards: [RwLock<HashMap<K, V>>; N_SHARDS],
}

Hopefully this suggests what I'm trying to accomplish:

impl<K, V> ConcurrentHashMap<K, V>
where
    K: Eq + Hash,
{
    fn iter_mut(&self) -> impl Iterator<Item = (&K, &mut V)> {
        self.shards
            .iter()
            .flat_map(|shard| shard.write().expect("Poisoned").iter_mut())
    }
}
error[E0515]: cannot return value referencing temporary value
  --> src/lib.rs:22:31
   |
22 |             .flat_map(|shard| shard.write().expect("Poisoned").iter_mut())
   |                               --------------------------------^^^^^^^^^^^
   |                               |
   |                               returns a value referencing data owned by the current function
   |                               temporary value created here
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
paulkernfeld
  • 2,171
  • 1
  • 16
  • 16
  • It looks like your question might be answered by the answers of [How to implement Iterator and IntoIterator for a simple struct?](https://stackoverflow.com/q/30218886/155423) / [How can I create my own data structure with an iterator that returns mutable references?](https://stackoverflow.com/q/25730586/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Oct 14 '19 at 19:33
  • 1
    No, I think this is more like a duplicate of [How do I return an iterator that has a reference to something inside a RefCell?](https://stackoverflow.com/questions/42676541/how-do-i-return-an-iterator-that-has-a-reference-to-something-inside-a-refcell) The `iter_mut` here would be unsound if it worked because you can call it twice to get two `&mut` references to the same value. The difference between `RwLock` and `RefCell` is not relevant to this error. – trent Oct 14 '19 at 20:02
  • 1
    @trentcl what about [Returning a RWLockReadGuard independently from a method](https://stackoverflow.com/q/50496879/155423) or [How to return a reference to a sub-value of a value that is under a mutex?](https://stackoverflow.com/q/40095383/155423) – Shepmaster Oct 16 '19 at 01:01
  • @Shepmaster Both those look similar, but they can be resolved using rental, which I don't think is true of this one. I'm not sure how to alter the signature of `iter_mut` so this is solvable -- internal iteration, as suggested in your answer to the question I linked, seems like the most direct approach. – trent Oct 16 '19 at 01:37
  • [Borrow data out of a mutex “borrowed value does not live long enough”](https://stackoverflow.com/questions/32083065/borrow-data-out-of-a-mutex-borrowed-value-does-not-live-long-enough) is also closely related and the answer there may be helpful. `Mutex`, like `RefCell` and `RwLock`, uses guards to enforce borrowing rules at runtime. – trent Oct 16 '19 at 13:14
  • Thanks for the links! I found all of them helpful in understanding the issue more deeply. To me, [Borrow data out of a mutex “borrowed value does not live long enough”](https://stackoverflow.com/questions/32083065/borrow-data-out-of-a-mutex-borrowed-value-does-not-live-long-enough) is the best duplicate since it's almost exactly what I was trying to do. – paulkernfeld Oct 23 '19 at 16:00

0 Answers0