Skip to content

Commit b813267

Browse files
committed
secondary::VacantEntry: Provide remove_stale_entry
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
1 parent ce6e1e0 commit b813267

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

src/secondary.rs

+52
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,58 @@ impl<'a, K: Key, V> VacantEntry<'a, K, V> {
12831283
}
12841284
unsafe { slot.get_unchecked_mut() }
12851285
}
1286+
1287+
/// Returns the stale key and data, if any, which would be overwritten by
1288+
/// inserting using this `VacantEntry`.
1289+
///
1290+
/// This situation arises if the stale key was removed from the
1291+
/// primary map, and a subsequent insert into the primary map
1292+
/// reused the slot.
1293+
///
1294+
/// `remove_stale_entry` can be used to handle this situation specially ---
1295+
/// for example, if the application wants to lazily clean up tertiary data
1296+
/// in another data structure indexed by the now-stale key, or by the value
1297+
/// stored in the `SecondaryMap`.
1298+
///
1299+
/// Most applications will not need this.
1300+
///
1301+
/// # Examples
1302+
/// ```
1303+
/// # use slotmap::*;
1304+
/// # use slotmap::secondary::Entry;
1305+
/// let mut pri = SlotMap::new();
1306+
/// let mut sec = SecondaryMap::new();
1307+
///
1308+
/// let k1 = pri.insert(1);
1309+
///
1310+
/// let ent = sec.entry(k1);
1311+
/// let mut vacant = match ent { Some(Entry::Vacant(vac)) => vac, _ => panic!("1. {:?}", &ent) };
1312+
/// assert_eq!(vacant.remove_stale_entry(), None);
1313+
///
1314+
/// sec.insert(k1, 'a');
1315+
/// pri.remove(k1);
1316+
/// // Imagine we don't keep a note of k1, after this.
1317+
/// let k2 = pri.insert(2);
1318+
///
1319+
/// let ent = sec.entry(k2);
1320+
/// let mut vacant = match ent { Some(Entry::Vacant(vac)) => vac, _ => panic!("2. {:?}", &ent) };
1321+
/// // Now we have recovered k1 and the associated data:
1322+
/// assert_eq!(vacant.remove_stale_entry(), Some((k1, 'a')));
1323+
/// assert_eq!(vacant.remove_stale_entry(), None);
1324+
///
1325+
/// vacant.insert('b');
1326+
/// assert!(sec.entry(k1).is_none());
1327+
/// ```
1328+
pub fn remove_stale_entry(&mut self) -> Option<(K, V)> {
1329+
let slot = unsafe { self.map.slots.get_unchecked_mut(self.kd.idx as usize) };
1330+
let old_slot = replace(slot, Slot::new_vacant());
1331+
if let Occupied { value, version } = old_slot {
1332+
let stale_kd = KeyData { idx: self.kd.idx, version };
1333+
Some((stale_kd.into(), value))
1334+
} else {
1335+
None
1336+
}
1337+
}
12861338
}
12871339

12881340
// Iterators.

0 commit comments

Comments
 (0)