1 use crate::fx::FxHashMap;
9 pub struct SnapshotMap<K, V>
14 undo_log: Vec<UndoLog<K, V>>,
15 num_open_snapshots: usize,
18 // HACK(eddyb) manual impl avoids `Default` bounds on `K` and `V`.
19 impl<K, V> Default for SnapshotMap<K, V>
23 fn default() -> Self {
24 SnapshotMap { map: Default::default(), undo_log: Default::default(), num_open_snapshots: 0 }
38 impl<K, V> SnapshotMap<K, V>
42 pub fn clear(&mut self) {
44 self.undo_log.clear();
45 self.num_open_snapshots = 0;
48 fn in_snapshot(&self) -> bool {
49 self.num_open_snapshots > 0
52 pub fn insert(&mut self, key: K, value: V) -> bool {
53 match self.map.insert(key.clone(), value) {
55 if self.in_snapshot() {
56 self.undo_log.push(UndoLog::Inserted(key));
61 if self.in_snapshot() {
62 self.undo_log.push(UndoLog::Overwrite(key, old_value));
69 pub fn remove(&mut self, key: K) -> bool {
70 match self.map.remove(&key) {
72 if self.in_snapshot() {
73 self.undo_log.push(UndoLog::Overwrite(key, old_value));
81 pub fn get(&self, key: &K) -> Option<&V> {
85 pub fn snapshot(&mut self) -> Snapshot {
86 let len = self.undo_log.len();
87 self.num_open_snapshots += 1;
91 fn assert_open_snapshot(&self, snapshot: &Snapshot) {
92 assert!(self.undo_log.len() >= snapshot.len);
93 assert!(self.num_open_snapshots > 0);
96 pub fn commit(&mut self, snapshot: Snapshot) {
97 self.assert_open_snapshot(&snapshot);
98 if self.num_open_snapshots == 1 {
99 // The root snapshot. It's safe to clear the undo log because
100 // there's no snapshot further out that we might need to roll back
102 assert!(snapshot.len == 0);
103 self.undo_log.clear();
106 self.num_open_snapshots -= 1;
109 pub fn partial_rollback<F>(&mut self, snapshot: &Snapshot, should_revert_key: &F)
113 self.assert_open_snapshot(snapshot);
114 for i in (snapshot.len..self.undo_log.len()).rev() {
115 let reverse = match self.undo_log[i] {
116 UndoLog::Purged => false,
117 UndoLog::Inserted(ref k) => should_revert_key(k),
118 UndoLog::Overwrite(ref k, _) => should_revert_key(k),
122 let entry = mem::replace(&mut self.undo_log[i], UndoLog::Purged);
128 pub fn rollback_to(&mut self, snapshot: Snapshot) {
129 self.assert_open_snapshot(&snapshot);
130 while self.undo_log.len() > snapshot.len {
131 let entry = self.undo_log.pop().unwrap();
135 self.num_open_snapshots -= 1;
138 fn reverse(&mut self, entry: UndoLog<K, V>) {
140 UndoLog::Inserted(key) => {
141 self.map.remove(&key);
144 UndoLog::Overwrite(key, old_value) => {
145 self.map.insert(key, old_value);
148 UndoLog::Purged => {}
153 impl<'k, K, V> ops::Index<&'k K> for SnapshotMap<K, V>
155 K: Hash + Clone + Eq,
158 fn index(&self, key: &'k K) -> &V {