public Progressor(TryTake <T> tryTake, Func <bool> isDone) { if (tryTake == null) { throw new ArgumentNullException("tryTake"); } if (isDone == null) { throw new ArgumentNullException("isDone"); } var tryTakeCopy = tryTake; _proxy = new ProxyObservable <T>(); _tryTake = (out T value) => { // This is not an overridable method, and it is not being called on the constructor. if (tryTakeCopy(out value)) { _proxy.OnNext(value); return(true); } _done = new ValueFuncClosure <bool>(isDone).InvokeReturn(); return(false); }; }
public Progressor(IObservable <T> wrapped) { var buffer = new SafeQueue <T>(); wrapped.Subscribe ( new CustomObserver <T> ( () => _done = true, exception => _done = true, buffer.Add ) ); _proxy = new ProxyObservable <T>(); _tryTake = (out T value) => { if (buffer.TryTake(out value)) { _proxy.OnNext(value); return(true); } value = default(T); return(false); }; }
protected ProgressiveLookup(TryTake <IGrouping <TKey, T> > tryTake, IDictionary <TKey, IGrouping <TKey, T> > cache, IEqualityComparer <TKey> keyComparer, IEqualityComparer <T> itemComparer) { _cache = Check.NotNullArgument(cache, "cache"); _progressor = new Progressor <IGrouping <TKey, T> >(tryTake, false); // false because the underlaying structure may change _progressor.SubscribeAction(obj => _cache.Add(new KeyValuePair <TKey, IGrouping <TKey, T> >(obj.Key, obj))); _keyComparer = keyComparer ?? EqualityComparer <TKey> .Default; _itemComparer = itemComparer ?? EqualityComparer <T> .Default; _keysReadonly = new ProgressiveSet <TKey>(Progressor <TKey> .CreateConverted(Progressor, input => input.Key), keyComparer); }
public static IEnumerable <T> Create <T>(TryTake <T> tryTake) { var _tryTake = Check.NotNullArgument(tryTake, "tryTake"); T item; while (_tryTake.Invoke(out item)) { yield return(item); } }
public static IEnumerable <TResult> Create <TState, TResult>(TryTake <TState> tryTake, Converter <TState, TResult> converter) { var _tryTake = Check.NotNullArgument(tryTake, "tryTake"); var _converter = Check.NotNullArgument(converter, "resultSelector"); TState item; while (_tryTake.Invoke(out item)) { yield return(_converter.Invoke(item)); } }
protected ProgressiveCollection(TryTake <T> tryTake, ICollection <T> cache, IEqualityComparer <T> comparer) { if (cache == null) { throw new ArgumentNullException("cache"); } _cache = cache; _progressor = new Progressor <T>(tryTake, false); // false because the underlaying structure may change _progressor.SubscribeAction(obj => _cache.Add(obj)); _comparer = comparer ?? EqualityComparer <T> .Default; }
public Progressor(IEnumerable <T> wrapped) { if (wrapped == null) { throw new ArgumentNullException("wrapped"); } var enumerator = wrapped.GetEnumerator(); if (enumerator == null) { throw new ArgumentException("wrapped.GetEnumerator()"); } var guard = 0; _proxy = new ProxyObservable <T>(); TryTake <T> tryTakeReplacement = (out T value) => { value = default(T); return(false); }; _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; } return(false); }; }
public static IEnumerable <T> Create <T>(TryTake <T> tryTake) { if (tryTake == null) { throw new ArgumentNullException("tryTake"); } T item; while (tryTake.Invoke(out item)) { yield return(item); } }
public static IEnumerable <T> Create <T>(TryTake <T> tryTake) { if (tryTake == null) { throw new ArgumentNullException(nameof(tryTake)); } return(CreateExtracted()); IEnumerable <T> CreateExtracted() { while (tryTake.Invoke(out var item)) { yield return(item); } } }
public static IEnumerable <TResult> Create <TState, TResult>(TryTake <TState> tryTake, Func <TState, TResult> converter) { if (tryTake == null) { throw new ArgumentNullException("tryTake"); } if (converter == null) { throw new ArgumentNullException("converter"); } TState item; while (tryTake.Invoke(out item)) { yield return(converter.Invoke(item)); } }
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 Progressor(TryTake <T> tryTake, bool doneOnFalse) { if (tryTake == null) { throw new ArgumentNullException("tryTake"); } _proxy = new ProxyObservable <T>(); _tryTake = (out T value) => { // This is not an overridable method, and it is not being called on the constructor. if (tryTake(out value)) { _proxy.OnNext(value); return(true); } _done = doneOnFalse; return(false); }; }
public static IEnumerable <TResult> Create <TState, TResult>(TryTake <TState> tryTake, Func <TState, TResult> converter) { if (tryTake == null) { throw new ArgumentNullException(nameof(tryTake)); } if (converter == null) { throw new ArgumentNullException(nameof(converter)); } return(CreateExtracted()); IEnumerable <TResult> CreateExtracted() { while (tryTake.Invoke(out var item)) { yield return(converter.Invoke(item)); } } }
public Progressor(T[] wrapped) { if (wrapped == null) { throw new ArgumentNullException("wrapped"); } var guard = 0; var index = -1; _proxy = new ProxyObservable <T>(); TryTake <T> tryTakeReplacement = (out T value) => { value = default(T); return(false); }; _tryTake = (out T value) => { value = default(T); if (Thread.VolatileRead(ref guard) == 0) { var currentIndex = Interlocked.Increment(ref index); if (currentIndex < wrapped.Length) { value = wrapped[currentIndex]; _proxy.OnNext(value); return(true); } Interlocked.CompareExchange(ref guard, 1, 0); } if (Interlocked.CompareExchange(ref guard, 2, 1) == 1) { _tryTake = tryTakeReplacement; } return(false); }; }
private Progressor(TryTake <T> tryTake, ProxyObservable <T> proxy) { _proxy = proxy; _tryTake = tryTake; }
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 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)); }; }
public void Close() { _tryTake = null; _proxy.OnCompleted(); _proxy = null; }
public static Progressor <T> CreateFromIObservable(IObservable <T> observable, Action exhaustedCallback = null, CancellationToken token = default) { if (observable == null) { throw new ArgumentNullException(nameof(observable)); } if (exhaustedCallback == null) { exhaustedCallback = ActionHelper.GetNoopAction(); } var buffer = new ThreadSafeQueue <T>(); var semaphore = new SemaphoreSlim(0); var source = new CancellationTokenSource(); var subscription = observable.Subscribe ( new CustomObserver <T> ( source.Cancel, _ => source.Cancel(), OnNext ) ); var proxy = new ProxyObservable <T>(); var tryTake = new TryTake <T>[] { null }; tryTake[0] = TakeInitial; void OnNext(T item) { buffer.Add(item); semaphore.Release(); } bool TakeInitial(out T value) { if (source.IsCancellationRequested || token.IsCancellationRequested) { if (Interlocked.CompareExchange(ref tryTake[0], TakeReplacement, tryTake[0]) == tryTake[0]) { Interlocked.Exchange(ref subscription, null)?.Dispose(); semaphore.Dispose(); source.Dispose(); } } else { if (exhaustedCallback != null) { var spinWait = new SpinWait(); while ( semaphore.CurrentCount == 0 && !source.IsCancellationRequested && !token.IsCancellationRequested ) { exhaustedCallback(); spinWait.SpinOnce(); } } } if (source.IsCancellationRequested || token.IsCancellationRequested) { return(TakeReplacement(out value)); } try { semaphore.Wait(source.Token); } catch (OperationCanceledException exception) { No.Op(exception); } return(TakeReplacement(out value)); } bool TakeReplacement(out T value) { if (buffer.TryTake(out value)) { return(true); } value = default; return(false); } bool Take(out T value) { return(tryTake[0](out value)); } return(new Progressor <T>(proxy, Take)); }