Skip to content

Commit d65d86c

Browse files
fix downgrade (#329)
* fix downgrade * add test for downgrade * fix mapped refs to use ?Sized and introduce some additional tests for map * more mappedref coverage * fix drop order with temp result
1 parent 9b74a37 commit d65d86c

File tree

2 files changed

+91
-21
lines changed

2 files changed

+91
-21
lines changed

src/mapref/one.rs

Lines changed: 84 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl<'a, K: Eq + Hash, V> Ref<'a, K, V> {
3030
(self.k, self.v)
3131
}
3232

33-
pub fn map<F, T>(self, f: F) -> MappedRef<'a, K, T>
33+
pub fn map<F, T: ?Sized>(self, f: F) -> MappedRef<'a, K, T>
3434
where
3535
F: FnOnce(&V) -> &T,
3636
{
@@ -41,7 +41,7 @@ impl<'a, K: Eq + Hash, V> Ref<'a, K, V> {
4141
}
4242
}
4343

44-
pub fn try_map<F, T>(self, f: F) -> Result<MappedRef<'a, K, T>, Self>
44+
pub fn try_map<F, T: ?Sized>(self, f: F) -> Result<MappedRef<'a, K, T>, Self>
4545
where
4646
F: FnOnce(&V) -> Option<&T>,
4747
{
@@ -113,7 +113,7 @@ impl<'a, K: Eq + Hash, V> RefMut<'a, K, V> {
113113
)
114114
}
115115

116-
pub fn map<F, T>(self, f: F) -> MappedRefMut<'a, K, T>
116+
pub fn map<F, T: ?Sized>(self, f: F) -> MappedRefMut<'a, K, T>
117117
where
118118
F: FnOnce(&mut V) -> &mut T,
119119
{
@@ -124,7 +124,7 @@ impl<'a, K: Eq + Hash, V> RefMut<'a, K, V> {
124124
}
125125
}
126126

127-
pub fn try_map<F, T>(self, f: F) -> Result<MappedRefMut<'a, K, T>, Self>
127+
pub fn try_map<F, T: ?Sized>(self, f: F) -> Result<MappedRefMut<'a, K, T>, Self>
128128
where
129129
F: FnOnce(&mut V) -> Option<&mut T>,
130130
{
@@ -165,13 +165,13 @@ impl<'a, K: Eq + Hash, V> DerefMut for RefMut<'a, K, V> {
165165
}
166166
}
167167

168-
pub struct MappedRef<'a, K, T> {
168+
pub struct MappedRef<'a, K, T: ?Sized> {
169169
_guard: RwLockReadGuardDetached<'a>,
170170
k: &'a K,
171171
v: &'a T,
172172
}
173173

174-
impl<'a, K: Eq + Hash, T> MappedRef<'a, K, T> {
174+
impl<'a, K: Eq + Hash, T: ?Sized> MappedRef<'a, K, T> {
175175
pub fn key(&self) -> &K {
176176
self.pair().0
177177
}
@@ -195,7 +195,7 @@ impl<'a, K: Eq + Hash, T> MappedRef<'a, K, T> {
195195
}
196196
}
197197

198-
pub fn try_map<F, T2>(self, f: F) -> Result<MappedRef<'a, K, T2>, Self>
198+
pub fn try_map<F, T2: ?Sized>(self, f: F) -> Result<MappedRef<'a, K, T2>, Self>
199199
where
200200
F: FnOnce(&T) -> Option<&T2>,
201201
{
@@ -212,7 +212,7 @@ impl<'a, K: Eq + Hash, T> MappedRef<'a, K, T> {
212212
}
213213
}
214214

215-
impl<'a, K: Eq + Hash + Debug, T: Debug> Debug for MappedRef<'a, K, T> {
215+
impl<'a, K: Eq + Hash + Debug, T: Debug + ?Sized> Debug for MappedRef<'a, K, T> {
216216
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
217217
f.debug_struct("MappedRef")
218218
.field("k", &self.k)
@@ -221,33 +221,35 @@ impl<'a, K: Eq + Hash + Debug, T: Debug> Debug for MappedRef<'a, K, T> {
221221
}
222222
}
223223

224-
impl<'a, K: Eq + Hash, T> Deref for MappedRef<'a, K, T> {
224+
impl<'a, K: Eq + Hash, T: ?Sized> Deref for MappedRef<'a, K, T> {
225225
type Target = T;
226226

227227
fn deref(&self) -> &T {
228228
self.value()
229229
}
230230
}
231231

232-
impl<'a, K: Eq + Hash, T: std::fmt::Display> std::fmt::Display for MappedRef<'a, K, T> {
232+
impl<'a, K: Eq + Hash, T: std::fmt::Display + ?Sized> std::fmt::Display for MappedRef<'a, K, T> {
233233
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234234
std::fmt::Display::fmt(self.value(), f)
235235
}
236236
}
237237

238-
impl<'a, K: Eq + Hash, T: AsRef<TDeref>, TDeref: ?Sized> AsRef<TDeref> for MappedRef<'a, K, T> {
238+
impl<'a, K: Eq + Hash, T: ?Sized + AsRef<TDeref>, TDeref: ?Sized> AsRef<TDeref>
239+
for MappedRef<'a, K, T>
240+
{
239241
fn as_ref(&self) -> &TDeref {
240242
self.value().as_ref()
241243
}
242244
}
243245

244-
pub struct MappedRefMut<'a, K, T> {
246+
pub struct MappedRefMut<'a, K, T: ?Sized> {
245247
_guard: RwLockWriteGuardDetached<'a>,
246248
k: &'a K,
247249
v: &'a mut T,
248250
}
249251

250-
impl<'a, K: Eq + Hash, T> MappedRefMut<'a, K, T> {
252+
impl<'a, K: Eq + Hash, T: ?Sized> MappedRefMut<'a, K, T> {
251253
pub fn key(&self) -> &K {
252254
self.pair().0
253255
}
@@ -268,7 +270,7 @@ impl<'a, K: Eq + Hash, T> MappedRefMut<'a, K, T> {
268270
(self.k, self.v)
269271
}
270272

271-
pub fn map<F, T2>(self, f: F) -> MappedRefMut<'a, K, T2>
273+
pub fn map<F, T2: ?Sized>(self, f: F) -> MappedRefMut<'a, K, T2>
272274
where
273275
F: FnOnce(&mut T) -> &mut T2,
274276
{
@@ -279,7 +281,7 @@ impl<'a, K: Eq + Hash, T> MappedRefMut<'a, K, T> {
279281
}
280282
}
281283

282-
pub fn try_map<F, T2>(self, f: F) -> Result<MappedRefMut<'a, K, T2>, Self>
284+
pub fn try_map<F, T2: ?Sized>(self, f: F) -> Result<MappedRefMut<'a, K, T2>, Self>
283285
where
284286
F: FnOnce(&mut T) -> Option<&mut T2>,
285287
{
@@ -297,7 +299,7 @@ impl<'a, K: Eq + Hash, T> MappedRefMut<'a, K, T> {
297299
}
298300
}
299301

300-
impl<'a, K: Eq + Hash + Debug, T: Debug> Debug for MappedRefMut<'a, K, T> {
302+
impl<'a, K: Eq + Hash + Debug, T: Debug + ?Sized> Debug for MappedRefMut<'a, K, T> {
301303
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
302304
f.debug_struct("MappedRefMut")
303305
.field("k", &self.k)
@@ -306,16 +308,80 @@ impl<'a, K: Eq + Hash + Debug, T: Debug> Debug for MappedRefMut<'a, K, T> {
306308
}
307309
}
308310

309-
impl<'a, K: Eq + Hash, T> Deref for MappedRefMut<'a, K, T> {
311+
impl<'a, K: Eq + Hash, T: ?Sized> Deref for MappedRefMut<'a, K, T> {
310312
type Target = T;
311313

312314
fn deref(&self) -> &T {
313315
self.value()
314316
}
315317
}
316318

317-
impl<'a, K: Eq + Hash, T> DerefMut for MappedRefMut<'a, K, T> {
319+
impl<'a, K: Eq + Hash, T: ?Sized> DerefMut for MappedRefMut<'a, K, T> {
318320
fn deref_mut(&mut self) -> &mut T {
319321
self.value_mut()
320322
}
321323
}
324+
325+
#[cfg(test)]
326+
mod tests {
327+
use crate::DashMap;
328+
329+
#[test]
330+
fn downgrade() {
331+
let data = DashMap::new();
332+
data.insert("test", "test");
333+
if let Some(mut w_ref) = data.get_mut("test") {
334+
*w_ref.value_mut() = "test2";
335+
let r_ref = w_ref.downgrade();
336+
assert_eq!(*r_ref.value(), "test2");
337+
};
338+
}
339+
340+
#[test]
341+
fn mapped_mut() {
342+
let data = DashMap::new();
343+
data.insert("test", *b"test");
344+
if let Some(b_ref) = data.get_mut("test") {
345+
let mut s_ref = b_ref.try_map(|b| std::str::from_utf8_mut(b).ok()).unwrap();
346+
s_ref.value_mut().make_ascii_uppercase();
347+
}
348+
349+
assert_eq!(data.get("test").unwrap().value(), b"TEST");
350+
}
351+
352+
#[test]
353+
fn mapped_mut_again() {
354+
let data = DashMap::new();
355+
data.insert("test", *b"hello world");
356+
if let Some(b_ref) = data.get_mut("test") {
357+
let s_ref = b_ref.try_map(|b| std::str::from_utf8_mut(b).ok()).unwrap();
358+
let mut hello_ref = s_ref.try_map(|s| s.get_mut(..5)).unwrap();
359+
hello_ref.value_mut().make_ascii_uppercase();
360+
}
361+
362+
assert_eq!(data.get("test").unwrap().value(), b"HELLO world");
363+
}
364+
365+
#[test]
366+
fn mapped_ref() {
367+
let data = DashMap::new();
368+
data.insert("test", *b"test");
369+
if let Some(b_ref) = data.get("test") {
370+
let s_ref = b_ref.try_map(|b| std::str::from_utf8(b).ok()).unwrap();
371+
372+
assert_eq!(s_ref.value(), "test");
373+
};
374+
}
375+
376+
#[test]
377+
fn mapped_ref_again() {
378+
let data = DashMap::new();
379+
data.insert("test", *b"hello world");
380+
if let Some(b_ref) = data.get("test") {
381+
let s_ref = b_ref.try_map(|b| std::str::from_utf8(b).ok()).unwrap();
382+
let hello_ref = s_ref.try_map(|s| s.get(..5)).unwrap();
383+
384+
assert_eq!(hello_ref.value(), "hello");
385+
};
386+
}
387+
}

src/util.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,15 @@ impl<'a, R: RawRwLockDowngrade> RwLockWriteGuardDetached<'a, R> {
113113
///
114114
/// The associated data must not mut mutated after downgrading
115115
pub(crate) unsafe fn downgrade(self) -> RwLockReadGuardDetached<'a, R> {
116+
// Do not drop the write guard - otherwise we will trigger a downgrade + unlock_exclusive,
117+
// which is incorrect
118+
let this = ManuallyDrop::new(self);
119+
116120
// Safety: An RwLockWriteGuardDetached always holds an exclusive lock.
117-
unsafe { self.lock.downgrade() }
121+
unsafe { this.lock.downgrade() }
118122
RwLockReadGuardDetached {
119-
lock: self.lock,
120-
_marker: self._marker,
123+
lock: this.lock,
124+
_marker: this._marker,
121125
}
122126
}
123127
}

0 commit comments

Comments
 (0)