public IObservable <Change <TObject, TKey> > Watch(TKey key) { return(Observable.Create <Change <TObject, TKey> > ( observer => { lock (_locker) { //Create or find the existing subscribers var existing = _subscribers.Lookup(key); SubjectWithRefCount <Change <TObject, TKey> > subject; if (existing.HasValue) { subject = existing.Value; } else { subject = new SubjectWithRefCount <Change <TObject, TKey> >(new ReplaySubject <Change <TObject, TKey> >(1)); var initial = _source.Lookup(key); if (initial.HasValue) { var update = new Change <TObject, TKey>(ChangeReason.Add, key, initial.Value); subject.OnNext(update); } _subscribers.BatchUpdate(updater => updater.AddOrUpdate(subject, key)); } //set up subscription var subscriber = subject.Subscribe(observer); return Disposable.Create(() => { //lock to ensure no race condition where the same key could be subscribed //to whilst disposal is taking place lock (_locker) { subscriber.Dispose(); if (subject.RefCount == 0) { _subscribers.BatchUpdate(updater => updater.Remove(key)); } } }); } })); }
internal void Update(Action <IIntermediateUpdater <TObject, TKey> > updateAction) { _cache.BatchUpdate(updateAction); }