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); }; }
private void Awake(int releaseCount) { // Call this to notify that there is room in the semaphore // Allow sync waiters to proceed _event.Set(); TaskCompletionSource <bool> waiter; while (releaseCount > 0 && _asyncWaiters.TryTake(out waiter)) { releaseCount--; if (waiter.Task.IsCompleted) { // Skip - either canceled or timed out continue; } if (TryEnter()) { waiter.SetResult(true); } else { _asyncWaiters.Add(waiter); } } }
private void Awake() { // Call this to notify that there is room in the semaphore // Allow sync waiters to proceed _event.Set(); while (Thread.VolatileRead(ref _count) < _maxCount) { TaskCompletionSource <bool> waiter; if (_asyncWaiters.TryTake(out waiter)) { if (waiter.Task.IsCompleted) { // Skip - either canceled or timed out continue; } if (TryEnter()) { waiter.SetResult(true); } else { _asyncWaiters.Add(waiter); } } } }
private static void ExecutePending(SafeQueue <Action> queue, RuntimeUniqueIdProdiver.UniqueId id) { bool didEnter = false; try { didEnter = ReentryGuardHelper.Enter(id); if (!didEnter) { // called from inside this method - skip return; } Action action; while (queue.TryTake(out action)) { action.Invoke(); } } finally { if (didEnter) { ReentryGuardHelper.Leave(id); } } }
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 TryDequeue(out T result) { return(_wrapped.TryTake(out result)); }
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> 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)); }; }
public bool TryTake(out T item) { return(_wrapped.TryTake(out item)); }
bool IProducerConsumerCollection <T> .TryTake(out T item) { return(_wrapped.TryTake(out item)); }
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 SafeQueue <T>(); var semaphore = new SemaphoreSlim(0); var source = new CancellationTokenSource(); var subscription = observable.Subscribe ( new CustomObserver <T>( onCompleted: source.Cancel, onError: exception => source.Cancel(), onNext: 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(); } } else { if (exhaustedCallback != null) { var spinWait = new SpinWait(); while ( semaphore.CurrentCount == 0 && !source.IsCancellationRequested && !token.IsCancellationRequested ) { exhaustedCallback(); spinWait.SpinOnce(); } } } if (!source.IsCancellationRequested && !token.IsCancellationRequested) { try { semaphore.Wait(source.Token); } catch (OperationCanceledException exception) { GC.KeepAlive(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)); }
private bool GetPendingResults(out Grouping <TKey, TElement> pendingResult) { return(_results.TryTake(out pendingResult)); }