public IObservable <IChangeSet <T> > Run() { return(Observable.Create <IChangeSet <T> >(observer => { var disposable = new CompositeDisposable(); var sourceLists = new List <ReferenceCountTracker <T> >(); var resultList = new ChangeAwareListWithRefCounts <T>(); lock (_locker) { foreach (var item in _source) { var list = new ReferenceCountTracker <T>(); sourceLists.Add(list); disposable.Add(item.Synchronize(_locker).Subscribe(changes => { CloneSourceList(list, changes); var notifications = UpdateResultList(changes, sourceLists, resultList); if (notifications.Count != 0) { observer.OnNext(notifications); } })); } } return disposable; })); }
private static void CloneSourceList(ReferenceCountTracker <T> tracker, IChangeSet <T> changes) { foreach (var change in changes) { switch (change.Reason) { case ListChangeReason.Add: tracker.Add(change.Item.Current); break; case ListChangeReason.AddRange: foreach (var t in change.Range) { tracker.Add(t); } break; case ListChangeReason.Replace: tracker.Remove(change.Item.Previous.Value); tracker.Add(change.Item.Current); break; case ListChangeReason.Remove: tracker.Remove(change.Item.Current); break; case ListChangeReason.RemoveRange: case ListChangeReason.Clear: foreach (var t in change.Range) { tracker.Remove(t); } break; } } }