protected ProgressiveDictionary(Progressor <KeyValuePair <TKey, TValue> > wrapped, IDictionary <TKey, TValue> cache, IEqualityComparer <TKey> keyComparer, IEqualityComparer <TValue> valueComparer) : base ((out KeyValuePair <TKey, TValue> pair) => { again: if (wrapped.TryTake(out pair)) { if (cache.ContainsKey(pair.Key)) { goto again; } return(true); } else { return(false); } }, cache, new KeyValuePairEqualityComparer <TKey, TValue>(keyComparer, valueComparer)) { _cache = Check.NotNullArgument(cache, "cache"); _keyComparer = keyComparer ?? EqualityComparer <TKey> .Default; _keyComparer = EqualityComparer <TKey> .Default; _valuesReadonly = new ProgressiveSet <TValue>(Progressor <TValue> .CreateConverted(Progressor, input => input.Value), valueComparer); _keysReadonly = new ProgressiveSet <TKey>(Progressor <TKey> .CreateConverted(Progressor, input => input.Key), keyComparer); }
protected ProgressiveSet(Progressor <T> wrapped, ISet <T> cache, IEqualityComparer <T> comparer) : base ( (out T value) => { again: if (wrapped.TryTake(out value)) { if (cache.Contains(value)) { goto again; } return(true); } else { return(false); } }, cache, comparer ) { // Empty }
TValue IDictionary <TKey, TValue> .this[TKey key] { get { try { return(_cache[key]); } catch (KeyNotFoundException) { KeyValuePair <TKey, TValue> _item; while (Progressor.TryTake(out _item)) { if (_keyComparer.Equals(key, _item.Key)) { return(_item.Value); } } throw; } } set { throw new NotSupportedException(); } }
public bool Contains(T item) { if (CacheContains(item)) { return(true); } T found; while (_progressor.TryTake(out found)) { if (_comparer.Equals(item, found)) { return(true); } } return(false); }
public bool Contains(TKey key) { if (_cache.ContainsKey(key)) { return(true); } IGrouping <TKey, T> item; while (_progressor.TryTake(out item)) { if (_keyComparer.Equals(key, item.Key)) { return(true); } } return(false); }
public Progressor(Progressor <T> wrapped) { if (wrapped == null) { throw new ArgumentNullException("wrapped"); } var control = 0; Predicate <T> newFilter = item => Thread.VolatileRead(ref control) == 0; var buffer = new SafeQueue <T>(); wrapped.SubscribeAction ( item => { if (newFilter(item)) { buffer.Add(item); } } ); _proxy = new ProxyObservable <T>(); _tryTake = (out T value) => { Interlocked.Increment(ref control); try { if (buffer.TryTake(out value) || wrapped.TryTake(out value)) { _proxy.OnNext(value); return(true); } else { _done = wrapped._done; return(false); } } finally { Interlocked.Decrement(ref control); } }; }
public bool ContainsKey(TKey key) { if (_cache.ContainsKey(key)) { return(true); } KeyValuePair <TKey, TValue> item; while (Progressor.TryTake(out item)) { if (_keyComparer.Equals(key, item.Key)) { return(true); } } return(false); }
public TValue this[TKey key] { get { try { return(_cache[key]); } catch (KeyNotFoundException) { KeyValuePair <TKey, TValue> _item; while (Progressor.TryTake(out _item)) { if (_keyComparer.Equals(key, _item.Key)) { return(_item.Value); } } throw; } } }
public Progressor(IEnumerable <T> preface, Progressor <T> wrapped) { if (wrapped == null) { throw new ArgumentNullException("wrapped"); } if (preface == null) { throw new ArgumentNullException("preface"); } var enumerator = preface.GetEnumerator(); if (enumerator == null) { throw new ArgumentException("preface.GetEnumerator()"); } var control = 0; var guard = 0; Predicate <T> newFilter = item => Thread.VolatileRead(ref control) == 0; var buffer = new SafeQueue <T>(); wrapped.SubscribeAction ( item => { if (newFilter(item)) { buffer.Add(item); } } ); _proxy = new ProxyObservable <T>(); TryTake <T> tryTakeReplacement = (out T value) => { Interlocked.Increment(ref control); try { if (buffer.TryTake(out value) || wrapped.TryTake(out value)) { _proxy.OnNext(value); return(true); } else { _done = wrapped._done; return(false); } } finally { Interlocked.Decrement(ref control); } }; _tryTake = (out T value) => { value = default(T); if (Thread.VolatileRead(ref guard) == 0) { bool result; // We need a lock, there is no way around it. IEnumerator is just awful. Use another overload if possible. lock (enumerator) { result = enumerator.MoveNext(); if (result) { value = enumerator.Current; } } if (result) { _proxy.OnNext(value); return(true); } enumerator.Dispose(); Interlocked.CompareExchange(ref guard, 1, 0); } if (Interlocked.CompareExchange(ref guard, 2, 1) == 1) { _tryTake = tryTakeReplacement; Thread.VolatileWrite(ref guard, 3); } else { ThreadingHelper.SpinWaitUntil(ref guard, 3); } var tryTake = _tryTake; return(tryTake(out value)); }; }
public static Progressor <T> CreateDistinct(Progressor <T> wrapped) { if (wrapped == null) { throw new ArgumentNullException("wrapped"); } var control = 0; SafeDictionary <T, bool> buffer = new SafeDictionary <T, bool>(); Predicate <T> newFilter = item => Thread.VolatileRead(ref control) == 0; var proxy = new ProxyObservable <T>(); Progressor <T> result = new Progressor <T>( (out T value) => { Interlocked.Increment(ref control); try { again: foreach (KeyValuePair <T, bool> item in buffer) { if (!item.Value) { value = item.Key; buffer.Set(value, true); proxy.OnNext(value); return(true); } } if (wrapped.TryTake(out value)) { bool seen; if (!buffer.TryGetValue(value, out seen) || !seen) { buffer.Set(value, true); proxy.OnNext(value); return(true); } else { goto again; } } else { return(false); } } finally { Interlocked.Decrement(ref control); } }, proxy ); wrapped.Subscribe ( new CustomObserver <T> ( () => result._done = true, exception => result._done = true, item => { if (newFilter(item)) { buffer.TryAdd(item, false); } } ) ); return(result); }
public static Progressor <T> CreatedFilteredConverted <TInput>(Progressor <TInput> wrapped, Predicate <TInput> filter, Converter <TInput, T> converter) { if (wrapped == null) { throw new ArgumentNullException("wrapped"); } if (filter == null) { throw new ArgumentNullException("filter"); } if (converter == null) { throw new ArgumentNullException("converter"); } var control = 0; Predicate <TInput> newFilter = item => Thread.VolatileRead(ref control) == 0 && filter(item); var buffer = new SafeQueue <T>(); var proxy = new ProxyObservable <T>(); var result = new Progressor <T>( (out T value) => { Interlocked.Increment(ref control); try { TInput item; again: if (buffer.TryTake(out value)) { proxy.OnNext(value); return(true); } else if (wrapped.TryTake(out item)) { if (filter(item)) { value = converter(item); proxy.OnNext(value); return(true); } else { goto again; } } value = default(T); return(false); } finally { Interlocked.Decrement(ref control); } }, proxy ); wrapped.Subscribe ( new CustomObserver <TInput> ( () => result._done = true, exception => result._done = true, item => { if (newFilter(item)) { buffer.Add(converter(item)); } } ) ); return(result); }
public Progressor(T[] preface, Progressor <T> wrapped) { if (wrapped == null) { throw new ArgumentNullException("wrapped"); } if (preface == null) { throw new ArgumentNullException("preface"); } var control = 0; var guard = 0; var index = -1; Predicate <T> newFilter = item => Thread.VolatileRead(ref control) == 0; var buffer = new SafeQueue <T>(); wrapped.SubscribeAction ( item => { if (newFilter(item)) { buffer.Add(item); } } ); _proxy = new ProxyObservable <T>(); TryTake <T> tryTakeReplacement = (out T value) => { Interlocked.Increment(ref control); try { if (buffer.TryTake(out value) || wrapped.TryTake(out value)) { _proxy.OnNext(value); return(true); } else { _done = wrapped._done; return(false); } } finally { Interlocked.Decrement(ref control); } }; _tryTake = (out T value) => { if (Thread.VolatileRead(ref guard) == 0) { var currentIndex = Interlocked.Increment(ref index); if (currentIndex < preface.Length) { value = preface[currentIndex]; _proxy.OnNext(value); return(true); } Interlocked.CompareExchange(ref guard, 1, 0); } if (Interlocked.CompareExchange(ref guard, 2, 1) == 1) { _tryTake = tryTakeReplacement; Thread.VolatileWrite(ref guard, 3); } else { ThreadingHelper.SpinWaitUntil(ref guard, 3); } var tryTake = _tryTake; return(tryTake(out value)); }; }