mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-24 13:12:31 +00:00
merged_tree: drop outer loop in TreeDiffStreamImpl::poll_next()
As suggested by Yuya. I also added a comment and an assertion in the case where return `Poll::Pending`.
This commit is contained in:
parent
d989d4093d
commit
c77417d4e4
1 changed files with 49 additions and 49 deletions
|
@ -1176,59 +1176,59 @@ impl Stream for TreeDiffStreamImpl<'_> {
|
||||||
type Item = (RepoPath, BackendResult<(MergedTreeValue, MergedTreeValue)>);
|
type Item = (RepoPath, BackendResult<(MergedTreeValue, MergedTreeValue)>);
|
||||||
|
|
||||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||||
while !(self.items.is_empty() && self.pending_trees.is_empty()) {
|
// Go through all pending tree futures and poll them.
|
||||||
// Go through all pending tree futures and poll them.
|
let mut pending_index = 0;
|
||||||
let mut pending_index = 0;
|
while pending_index < self.pending_trees.len()
|
||||||
while pending_index < self.pending_trees.len()
|
&& (pending_index < self.max_concurrent_reads
|
||||||
&& (pending_index < self.max_concurrent_reads
|
|| self.items.len() < self.max_queued_items)
|
||||||
|| self.items.len() < self.max_queued_items)
|
{
|
||||||
{
|
let (_, future) = &mut self.pending_trees[pending_index];
|
||||||
let (_, future) = &mut self.pending_trees[pending_index];
|
if let Poll::Ready(tree_diff) = future.as_mut().poll(cx) {
|
||||||
if let Poll::Ready(tree_diff) = future.as_mut().poll(cx) {
|
let (dir, _) = self.pending_trees.remove(pending_index).unwrap();
|
||||||
let (dir, _) = self.pending_trees.remove(pending_index).unwrap();
|
let key = DiffStreamKey::normal(dir);
|
||||||
let key = DiffStreamKey::normal(dir);
|
// Whenever we add an entry to `self.pending_trees`, we also add an Ok() entry
|
||||||
// Whenever we add an entry to `self.pending_trees`, we also add an Ok() entry
|
// to `self.items`.
|
||||||
// to `self.items`.
|
let (before, after) = self.items.remove(&key).unwrap().unwrap();
|
||||||
let (before, after) = self.items.remove(&key).unwrap().unwrap();
|
// If this was a transition from file to tree or vice versa, add back an item
|
||||||
// If this was a transition from file to tree or vice versa, add back an item
|
// for just the removal/addition of the file.
|
||||||
// for just the removal/addition of the file.
|
if before.is_present() && !before.is_tree() {
|
||||||
if before.is_present() && !before.is_tree() {
|
self.items
|
||||||
self.items
|
.insert(key.clone(), Ok((before, Merge::absent())));
|
||||||
.insert(key.clone(), Ok((before, Merge::absent())));
|
} else if after.is_present() && !after.is_tree() {
|
||||||
} else if after.is_present() && !after.is_tree() {
|
self.items.insert(
|
||||||
self.items.insert(
|
DiffStreamKey::file_after_dir(key.path.clone()),
|
||||||
DiffStreamKey::file_after_dir(key.path.clone()),
|
Ok((Merge::absent(), after)),
|
||||||
Ok((Merge::absent(), after)),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
self.add_dir_diff_items(key.path, tree_diff);
|
|
||||||
} else {
|
|
||||||
pending_index += 1;
|
|
||||||
}
|
}
|
||||||
}
|
self.add_dir_diff_items(key.path, tree_diff);
|
||||||
|
} else {
|
||||||
// Now emit the first file, or the first tree that completed with an error
|
pending_index += 1;
|
||||||
while let Some(entry) = self.items.first_entry() {
|
|
||||||
match entry.get() {
|
|
||||||
Err(_) => {
|
|
||||||
// File or tree with error
|
|
||||||
let (key, result) = entry.remove_entry();
|
|
||||||
return Poll::Ready(Some((key.path, result)));
|
|
||||||
}
|
|
||||||
Ok((before, after)) if !before.is_tree() && !after.is_tree() => {
|
|
||||||
let (key, result) = entry.remove_entry();
|
|
||||||
return Poll::Ready(Some((key.path, result)));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
if !self.pending_trees.is_empty() {
|
|
||||||
return Poll::Pending;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Poll::Ready(None)
|
// Now emit the first file, or the first tree that completed with an error
|
||||||
|
if let Some(entry) = self.items.first_entry() {
|
||||||
|
match entry.get() {
|
||||||
|
Err(_) => {
|
||||||
|
// File or tree with error
|
||||||
|
let (key, result) = entry.remove_entry();
|
||||||
|
Poll::Ready(Some((key.path, result)))
|
||||||
|
}
|
||||||
|
Ok((before, after)) if !before.is_tree() && !after.is_tree() => {
|
||||||
|
// A diff with no trees involved
|
||||||
|
let (key, result) = entry.remove_entry();
|
||||||
|
Poll::Ready(Some((key.path, result)))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// The first entry has a tree on at least one side (before or after). We need to
|
||||||
|
// wait for that future to complete.
|
||||||
|
assert!(!self.pending_trees.is_empty());
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Poll::Ready(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue