From 51683457c7fe5749a2cdfb67f16c538582af6c34 Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Fri, 21 Apr 2023 16:12:33 +0900 Subject: [PATCH] index: abstract CompositeIndex away from RevWalkQueue --- lib/src/default_index_store.rs | 86 ++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 24 deletions(-) diff --git a/lib/src/default_index_store.rs b/lib/src/default_index_store.rs index df7b99d29..00aa234e5 100644 --- a/lib/src/default_index_store.rs +++ b/lib/src/default_index_store.rs @@ -1166,6 +1166,40 @@ impl PartialOrd for IndexEntryByGeneration<'_> { } } +trait RevWalkIndex<'a> { + type Entry: Ord + RevWalkIndexEntry<'a>; + + fn entry_by_pos(&self, pos: IndexPosition) -> Self::Entry; + fn adjacent_positions(&self, entry: &IndexEntry<'_>) -> Vec; +} + +trait RevWalkIndexEntry<'a> { + fn as_index_entry(&self) -> &IndexEntry<'a>; + fn into_index_entry(self) -> IndexEntry<'a>; +} + +impl<'a> RevWalkIndex<'a> for CompositeIndex<'a> { + type Entry = IndexEntryByPosition<'a>; + + fn entry_by_pos(&self, pos: IndexPosition) -> Self::Entry { + IndexEntryByPosition(CompositeIndex::entry_by_pos(self, pos)) + } + + fn adjacent_positions(&self, entry: &IndexEntry<'_>) -> Vec { + entry.parent_positions() + } +} + +impl<'a> RevWalkIndexEntry<'a> for IndexEntryByPosition<'a> { + fn as_index_entry(&self) -> &IndexEntry<'a> { + &self.0 + } + + fn into_index_entry(self) -> IndexEntry<'a> { + self.0 + } +} + #[derive(Clone, Eq, PartialEq, Ord, PartialOrd)] struct RevWalkWorkItem { entry: E, @@ -1203,14 +1237,14 @@ impl RevWalkWorkItem { } #[derive(Clone)] -struct RevWalkQueue<'a, T> { - index: CompositeIndex<'a>, - items: BinaryHeap, T>>, +struct RevWalkQueue<'a, I: RevWalkIndex<'a>, T> { + index: I, + items: BinaryHeap>, unwanted_count: usize, } -impl<'a, T: Ord> RevWalkQueue<'a, T> { - fn new(index: CompositeIndex<'a>) -> Self { +impl<'a, I: RevWalkIndex<'a>, T: Ord> RevWalkQueue<'a, I, T> { + fn new(index: I) -> Self { Self { index, items: BinaryHeap::new(), @@ -1218,7 +1252,7 @@ impl<'a, T: Ord> RevWalkQueue<'a, T> { } } - fn map_wanted(self, mut f: impl FnMut(T) -> U) -> RevWalkQueue<'a, U> { + fn map_wanted(self, mut f: impl FnMut(T) -> U) -> RevWalkQueue<'a, I, U> { RevWalkQueue { index: self.index, items: self @@ -1232,30 +1266,30 @@ impl<'a, T: Ord> RevWalkQueue<'a, T> { fn push_wanted(&mut self, pos: IndexPosition, t: T) { self.items.push(RevWalkWorkItem { - entry: IndexEntryByPosition(self.index.entry_by_pos(pos)), + entry: self.index.entry_by_pos(pos), state: RevWalkWorkItemState::Wanted(t), }); } fn push_unwanted(&mut self, pos: IndexPosition) { self.items.push(RevWalkWorkItem { - entry: IndexEntryByPosition(self.index.entry_by_pos(pos)), + entry: self.index.entry_by_pos(pos), state: RevWalkWorkItemState::Unwanted, }); self.unwanted_count += 1; } - fn push_wanted_parents(&mut self, entry: &IndexEntry<'_>, t: T) + fn push_wanted_adjacents(&mut self, entry: &IndexEntry<'_>, t: T) where T: Clone, { - for pos in entry.parent_positions() { + for pos in self.index.adjacent_positions(entry) { self.push_wanted(pos, t.clone()); } } - fn push_unwanted_parents(&mut self, entry: &IndexEntry<'_>) { - for pos in entry.parent_positions() { + fn push_unwanted_adjacents(&mut self, entry: &IndexEntry<'_>) { + for pos in self.index.adjacent_positions(entry) { self.push_unwanted(pos); } } @@ -1263,7 +1297,7 @@ impl<'a, T: Ord> RevWalkQueue<'a, T> { fn pop(&mut self) -> Option, T>> { if let Some(x) = self.items.pop() { self.unwanted_count -= !x.is_wanted() as usize; - Some(x.map_entry(|e| e.0)) + Some(x.map_entry(RevWalkIndexEntry::into_index_entry)) } else { None } @@ -1271,7 +1305,7 @@ impl<'a, T: Ord> RevWalkQueue<'a, T> { fn pop_eq(&mut self, entry: &IndexEntry<'_>) -> Option, T>> { if let Some(x) = self.items.peek() { - (&x.entry.0 == entry).then(|| self.pop().unwrap()) + (x.entry.as_index_entry() == entry).then(|| self.pop().unwrap()) } else { None } @@ -1286,7 +1320,7 @@ impl<'a, T: Ord> RevWalkQueue<'a, T> { #[derive(Clone)] pub struct RevWalk<'a> { - queue: RevWalkQueue<'a, ()>, + queue: RevWalkQueue<'a, CompositeIndex<'a>, ()>, } impl<'a> RevWalk<'a> { @@ -1334,14 +1368,14 @@ impl<'a> Iterator for RevWalk<'a> { while let Some(item) = self.queue.pop() { self.queue.skip_while_eq(&item.entry); if item.is_wanted() { - self.queue.push_wanted_parents(&item.entry, ()); + self.queue.push_wanted_adjacents(&item.entry, ()); return Some(item.entry); } else if self.queue.items.len() == self.queue.unwanted_count { // No more wanted entries to walk debug_assert!(!self.queue.items.iter().any(|x| x.is_wanted())); return None; } else { - self.queue.push_unwanted_parents(&item.entry); + self.queue.push_unwanted_adjacents(&item.entry); } } @@ -1356,12 +1390,12 @@ impl<'a> Iterator for RevWalk<'a> { #[derive(Clone)] pub struct RevWalkGenerationRange<'a> { // Sort item generations in ascending order - queue: RevWalkQueue<'a, Reverse>, + queue: RevWalkQueue<'a, CompositeIndex<'a>, Reverse>, generation_end: u32, } impl<'a> RevWalkGenerationRange<'a> { - fn new(queue: RevWalkQueue<'a, ()>, generation_range: Range) -> Self { + fn new(queue: RevWalkQueue<'a, CompositeIndex<'a>, ()>, generation_range: Range) -> Self { // Translate filter range to item ranges so that overlapped ranges can be // merged later. // @@ -1380,7 +1414,11 @@ impl<'a> RevWalkGenerationRange<'a> { } } - fn enqueue_wanted_parents(&mut self, entry: &IndexEntry<'_>, gen: RevWalkItemGenerationRange) { + fn enqueue_wanted_adjacents( + &mut self, + entry: &IndexEntry<'_>, + gen: RevWalkItemGenerationRange, + ) { // `gen.start` is incremented from 0, which should never overflow if gen.start + 1 >= self.generation_end { return; @@ -1389,7 +1427,7 @@ impl<'a> RevWalkGenerationRange<'a> { start: gen.start + 1, end: gen.end.saturating_add(1), }; - self.queue.push_wanted_parents(entry, Reverse(succ_gen)); + self.queue.push_wanted_adjacents(entry, Reverse(succ_gen)); } } @@ -1410,14 +1448,14 @@ impl<'a> Iterator for RevWalkGenerationRange<'a> { pending_gen = if let Some(merged) = pending_gen.try_merge_end(gen) { merged } else { - self.enqueue_wanted_parents(&item.entry, pending_gen); + self.enqueue_wanted_adjacents(&item.entry, pending_gen); gen }; } else { unreachable!("no more unwanted items of the same entry"); } } - self.enqueue_wanted_parents(&item.entry, pending_gen); + self.enqueue_wanted_adjacents(&item.entry, pending_gen); if some_in_range { return Some(item.entry); } @@ -1427,7 +1465,7 @@ impl<'a> Iterator for RevWalkGenerationRange<'a> { return None; } else { self.queue.skip_while_eq(&item.entry); - self.queue.push_unwanted_parents(&item.entry); + self.queue.push_unwanted_adjacents(&item.entry); } }