diff --git a/src/lib.rs b/src/lib.rs index a3e5a496..69ab7388 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,6 +59,21 @@ pub struct DashMap { hasher: S, } +impl Clone for DashMap { + fn clone(&self) -> Self { + let mut inner_shards = Vec::new(); + for shard in self.shards.iter() { + let shard = shard.read(); + inner_shards.push(RwLock::new((*shard).clone())); + } + Self { + ncb: self.ncb, + shards: inner_shards.into_boxed_slice(), + hasher: self.hasher.clone(), + } + } +} + impl Default for DashMap where K: Eq + Hash, diff --git a/src/util.rs b/src/util.rs index 414fb223..9de245fa 100644 --- a/src/util.rs +++ b/src/util.rs @@ -40,19 +40,28 @@ pub unsafe fn change_lifetime_mut<'a, 'b, T>(x: &'a mut T) -> &'b mut T { } /// A simple wrapper around `T` -/// +/// /// This is to prevent UB when using `HashMap::get_key_value`, because /// `HashMap` doesn't expose an api to get the key and value, where /// the value is a `&mut T`. -/// +/// /// See [#10](https://github.com/xacrimon/dashmap/issues/10) for details -/// +/// /// This type is meant to be an implementation detail, but must be exposed due to the `Dashmap::shards` #[repr(transparent)] pub struct SharedValue { value: UnsafeCell, } +impl Clone for SharedValue { + fn clone(&self) -> Self { + let inner = self.get().clone(); + Self { + value: UnsafeCell::new(inner), + } + } +} + unsafe impl Send for SharedValue {} unsafe impl Sync for SharedValue {}