Esempio n. 1
0
        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);
            };
        }
Esempio n. 2
0
        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);
             }
         }
     }
 }
Esempio n. 4
0
        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);
                }
            }
        }
Esempio n. 5
0
        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);
                }
            };
        }
Esempio n. 6
0
 public bool TryDequeue(out T result)
 {
     return(_wrapped.TryTake(out result));
 }
Esempio n. 7
0
        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));
            };
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        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));
            };
        }
Esempio n. 10
0
 public bool TryTake(out T item)
 {
     return(_wrapped.TryTake(out item));
 }
Esempio n. 11
0
 bool IProducerConsumerCollection <T> .TryTake(out T item)
 {
     return(_wrapped.TryTake(out item));
 }
Esempio n. 12
0
        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));
        }
Esempio n. 13
0
 private bool GetPendingResults(out Grouping <TKey, TElement> pendingResult)
 {
     return(_results.TryTake(out pendingResult));
 }