public IObservable <IChangeSet <T> > Run() { return(Observable.Create <IChangeSet <T> >(observer => { var locker = new object(); var orginal = new ChangeAwareList <T>(); var target = new ChangeAwareList <T>(); var changed = _source.Synchronize(locker).Select(changes => { if (_resetThreshold > 1) { orginal.Clone(changes); } return changes.TotalChanges > _resetThreshold && _comparer != null ? Reset(orginal, target) : Process(target, changes); }); var resort = _resort.Synchronize(locker).Select(changes => Reorder(target)); var changeComparer = _comparerObservable.Synchronize(locker).Select(comparer => ChangeComparer(target, comparer)); return changed.Merge(resort).Merge(changeComparer) .Where(changes => changes.Count != 0) .SubscribeSafe(observer); })); }
public Continuation <IChangeSet <T> > Write(IChangeSet <T> changes) { if (changes == null) { throw new ArgumentNullException(nameof(changes)); } IChangeSet <T> result; lock (_locker) { try { _data.Clone(changes); result = _data.CaptureChanges(); } catch (Exception ex) { return(new Continuation <IChangeSet <T> >(ex)); } } return(new Continuation <IChangeSet <T> >(result)); }
private IChangeSet <T> ProcessImpl(ChangeAwareList <T> target, IChangeSet <T> changes) { if (_comparer == null) { target.Clone(changes); return(target.CaptureChanges()); } foreach (var change in changes) { switch (change.Reason) { case ListChangeReason.Add: { var current = change.Item.Current; Insert(target, current); break; } case ListChangeReason.AddRange: { var ordered = change.Range.OrderBy(t => t, _comparer).ToList(); if (target.Count == 0) { target.AddRange(ordered); } else { ordered.ForEach(item => Insert(target, item)); } break; } case ListChangeReason.Replace: { var current = change.Item.Current; //TODO: check whether an item should stay in the same position //i.e. update and move Remove(target, change.Item.Previous.Value); Insert(target, current); break; } case ListChangeReason.Remove: { var current = change.Item.Current; Remove(target, current); break; } case ListChangeReason.RemoveRange: { target.RemoveMany(change.Range); break; } case ListChangeReason.Clear: { target.Clear(); break; } } } return(target.CaptureChanges()); }