feat: reuse tracker

This commit is contained in:
Zixuan Chen 2022-10-26 10:39:56 +08:00
parent 78faec33a1
commit a1d1517de0
3 changed files with 46 additions and 10 deletions

View file

@ -150,8 +150,10 @@ impl Container for TextContainer {
&self.head
);
// TODO: reuse tracker
// let head = if common_ancestors.is_empty() || !common_ancestors.iter().all(|x| self.tracker.contains(*x))
let head = if true {
// let head = if true {
let head = if common_ancestors.is_empty()
|| !common_ancestors.iter().all(|x| self.tracker.contains(*x))
{
debug_log!("NewTracker");
// FIXME use common ancestors
self.tracker = Tracker::new(common_ancestors_vv, Counter::MAX / 2);

View file

@ -2,7 +2,8 @@ use rle::HasLength;
use crate::{
container::text::text_content::ListSlice,
id::Counter,
debug_log,
id::{Counter, ID},
span::{CounterSpan, HasId, HasIdSpan, IdSpan},
version::IdSpanVector,
};
@ -13,7 +14,7 @@ pub struct EffectIter<'a> {
tracker: &'a mut Tracker,
left_spans: Vec<IdSpan>,
current_span: Option<IdSpan>,
current_delete_targets: Option<Vec<IdSpan>>,
current_delete_targets: Option<(ID, Vec<IdSpan>)>,
}
impl<'a> EffectIter<'a> {
@ -43,7 +44,9 @@ impl<'a> Iterator for EffectIter<'a> {
fn next(&mut self) -> Option<Self::Item> {
loop {
while let Some(ref mut delete_targets) = self.current_delete_targets {
while let Some((ref mut delete_op_id, ref mut delete_targets)) =
self.current_delete_targets
{
if let Some(target) = delete_targets.pop() {
let result = self
.tracker
@ -73,6 +76,8 @@ impl<'a> Iterator for EffectIter<'a> {
// SAFETY: we know that the cursor is valid here
let pos = unsafe { cursor.get_index() };
let len = cursor.len;
*delete_op_id = delete_op_id.inc(cursor.len as Counter);
self.tracker.head_vv.set_end(*delete_op_id);
let length = -self.tracker.update_cursors(cursor, StatusChange::Delete);
assert!(length >= 0);
if length > 0 {
@ -92,8 +97,8 @@ impl<'a> Iterator for EffectIter<'a> {
if let Some(cursor) = cursor {
match cursor {
FirstCursorResult::Ins(id, cursor) => {
assert!(current.contains_id(id));
assert!(current.contains_id(id.inc(cursor.len as Counter - 1)));
debug_assert!(current.contains_id(id));
debug_assert!(current.contains_id(id.inc(cursor.len as Counter - 1)));
current
.counter
.set_start(id.counter + cursor.len as Counter);
@ -102,6 +107,7 @@ impl<'a> Iterator for EffectIter<'a> {
// SAFETY: cursor is valid here
let content = unsafe { cursor.get_sliced().slice };
let len = cursor.len;
self.tracker.head_vv.set_end(id.inc(cursor.len as Counter));
let length_diff = self
.tracker
.update_cursors(cursor, StatusChange::SetAsCurrent);
@ -115,12 +121,14 @@ impl<'a> Iterator for EffectIter<'a> {
}
}
FirstCursorResult::Del(id, del) => {
assert!(current.contains_id(id));
assert!(current.contains_id(id.inc(del.atom_len() as Counter - 1)));
debug_assert!(current.contains_id(id));
debug_assert!(
current.contains_id(id.inc(del.atom_len() as Counter - 1))
);
current
.counter
.set_start(id.counter + del.atom_len() as Counter);
self.current_delete_targets = Some(del.iter().cloned().collect());
self.current_delete_targets = Some((id, del.iter().cloned().collect()));
}
}
} else {

View file

@ -306,6 +306,32 @@ mod test {
use super::Action::*;
use super::*;
#[test]
fn test_12() {
// retreat failed
test_multi_sites(
3,
vec![
Ins {
content: "x".into(),
pos: 0,
site: 0,
},
Sync { from: 0, to: 1 },
Ins {
content: "y".into(),
pos: 1,
site: 1,
},
Del {
pos: 0,
len: 1,
site: 0,
},
],
)
}
#[test]
fn test_11() {
test_multi_sites(