IDisposable SubscribeInner(IObservable <T> obs, IndexTrackerList <SingleAssignmentDisposable> .IndexedItem indexedItem) { return(obs.Subscribe( Observer.Create <T>( onNext: item => { lock (_gate) foreach (var currentIndex in indexedItem.Index) { foreach (var change in _changeMapper.Replace(currentIndex, item, true)) { _observer.OnNext(change); } } }, onError: OnError, onCompleted: () => { lock (_gate) { foreach (var currentIndex in indexedItem.Index) { _innerSubscriptions[currentIndex].Dispose(); _innerCompleted = _innerCompleted.ReplaceAt(currentIndex, true); if (_outerCompleted && _innerCompleted.Sum()) { Disposable.Combine(_innerSubscriptions).Dispose(); _innerSubscriptions.Clear(); _observer.OnCompleted(); } } } }))); }
public Optional <ListChange <T> > Insert <T>(int index, T item, bool predicateTrue) { var toIndex = _items.Sum(index); _items = _items.Insert(index, predicateTrue ? 1 : 0); return(predicateTrue ? ListChange.Insert(toIndex, item) : Optional.None <ListChange <T> >()); }
public Optional <ListChange <T> > Clear <T>() { var oldTrueCount = _items.Sum(); _items = _items.Clear(); return(oldTrueCount == 0 ? Optional.None <ListChange <T> >() : ListChange.Clear <T>()); }
public void OnError(Exception error) { lock (_gate) { _observer.OnError(error); Disposable.Combine(_innerSubscriptions).Dispose(); _innerSubscriptions.Clear(); _innerCompleted = SumTree <bool> .Empty(false, (d1, d2) => d1 && d2); } }
public Optional <ListChange <T> > Remove <T>(int index) { var toIndex = _items.Sum(index); var predicateTrue = _items[index] == 1; _items = _items.RemoveAt(index); return(predicateTrue ? ListChange.Remove <T>(toIndex) : Optional.None <ListChange <T> >()); }
public static IObservable <T> AggregateAssoc <T>( this IObservableList <T> self, T seed, Func <T, T, T> associativeAccumulator) { return(self .Scan( SumTree <T> .Empty(seed, associativeAccumulator), (tree, changes) => changes.Apply(tree)) .Select(tree => tree.Sum())); }
public static SumTree <T> Apply <T>(this ListChange <T> changes, SumTree <T> tree) { var result = tree; changes( insert: (i, x) => result = result.Insert(i, x), replace: (i, x) => result = result.ReplaceAt(i, x), remove: i => result = result.RemoveAt(i), clear: () => result = result.Clear()); return(result); }
public void OnNext(ListChange <IObservable <T> > changes) { lock (_gate) { changes( insert: (index, obs) => { var indexedItem = new IndexTrackerList <SingleAssignmentDisposable> .IndexedItem(new SingleAssignmentDisposable()); _innerSubscriptions.Insert(index, indexedItem); _changeMapper.InsertFalse(index); _innerCompleted = _innerCompleted.Insert(index, false); indexedItem.Value.Disposable = SubscribeInner(obs, indexedItem); }, replace: (index, obs) => { _innerSubscriptions[index].Dispose(); var indexedItem = new IndexTrackerList <SingleAssignmentDisposable> .IndexedItem(new SingleAssignmentDisposable()); _innerSubscriptions.Replace(index, indexedItem); _innerCompleted = _innerCompleted.ReplaceAt(index, false); indexedItem.Value.Disposable = SubscribeInner(obs, indexedItem); // The new observable hasn't produced any values left, so remove any leftover old values foreach (var change in _changeMapper.ReplaceFalse <T>(index)) { _observer.OnNext(change); } }, remove: (index) => { _innerSubscriptions[index].Dispose(); _innerSubscriptions.Remove(index); _innerCompleted = _innerCompleted.RemoveAt(index); foreach (var change in _changeMapper.Remove <T>(index)) { _observer.OnNext(change); } }, clear: () => { Disposable.Combine(_innerSubscriptions).Dispose(); _innerSubscriptions.Clear(); _innerCompleted = SumTree <bool> .Empty(false, (d1, d2) => d1 && d2); foreach (var change in _changeMapper.Clear <T>()) { _observer.OnNext(change); } }); } }
public Optional <ListChange <T> > Replace <T>(int index, T item, bool predicateTrue) { var toIndex = _items.Sum(index); var oldPredicateTrue = _items[index] == 1; _items = _items.ReplaceAt(index, predicateTrue ? 1 : 0); if (predicateTrue) { return(oldPredicateTrue ? ListChange.Replace(toIndex, item) : ListChange.Insert(toIndex, item)); } else { return(oldPredicateTrue ? ListChange.Remove <T>(toIndex) : Optional.None <ListChange <T> >()); } }
public void InsertFalse(int index) { _items = _items.Insert(index, 0); }