Exemple #1
0
        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.Edit(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.Edit(updater => updater.Remove(key));
                            }
                        }
                    });
                }
            }));
        }
Exemple #2
0
        public IObservable <IChangeSet <TObject, TKey> > ExpireAfter()
        {
            return(Observable.Create <IChangeSet <TObject, TKey> >(observer =>
            {
                var cache = new IntermediateCache <TObject, TKey>(_source);

                var published = cache.Connect().Publish();
                var subscriber = published.SubscribeSafe(observer);

                var autoRemover = published.ForExpiry(_timeSelector, _interval, _scheduler)
                                  .Finally(observer.OnCompleted)
                                  .Subscribe(keys =>
                {
                    try
                    {
                        cache.Edit(updater => updater.Remove(keys.Select(kv => kv.Key)));
                    }
                    catch (Exception ex)
                    {
                        observer.OnError(ex);
                    }
                });

                var connected = published.Connect();

                return Disposable.Create(() =>
                {
                    connected.Dispose();
                    subscriber.Dispose();
                    autoRemover.Dispose();
                    cache.Dispose();
                });
            }));
        }
Exemple #3
0
        public IObservable <IChangeSet <TObject, TKey> > Run()
        {
            return(Observable.Create <IChangeSet <TObject, TKey> >(observer =>
            {
                var sizeLimiter = new SizeLimiter <TObject, TKey>(_size);
                var root = new IntermediateCache <TObject, TKey>(_source);

                var subscriber = root.Connect()
                                 .Transform((t, v) => new ExpirableItem <TObject, TKey>(t, v, DateTime.Now))
                                 .Select(changes =>
                {
                    var result = sizeLimiter.Change(changes);

                    var removes = result.Where(c => c.Reason == ChangeReason.Remove);
                    root.Edit(updater => removes.ForEach(c => updater.Remove(c.Key)));
                    return result;
                })
                                 .Finally(observer.OnCompleted)
                                 .SubscribeSafe(observer);

                return Disposable.Create(() =>
                {
                    subscriber.Dispose();
                    root.Dispose();
                });
            }));
        }
Exemple #4
0
 internal void Update(Action <IIntermediateUpdater <TObject, TKey> > updateAction)
 {
     _cache.Edit(updateAction);
 }