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);
            };
        }
示例#2
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);
            };
        }
示例#3
0
 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);
 }
示例#4
0
        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);
            }
        }
示例#5
0
        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));
            }
        }
示例#6
0
 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;
 }
示例#7
0
        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);
            };
        }
示例#8
0
        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);
            }
        }
示例#9
0
        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);
                }
            }
        }
示例#10
0
        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));
            }
        }
示例#11
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);
                }
            };
        }
示例#12
0
 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);
     };
 }
示例#13
0
        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));
                }
            }
        }
示例#14
0
        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);
            };
        }
示例#15
0
 private Progressor(TryTake <T> tryTake, ProxyObservable <T> proxy)
 {
     _proxy   = proxy;
     _tryTake = tryTake;
 }
示例#16
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));
            };
        }
示例#17
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));
            };
        }
示例#18
0
 public void Close()
 {
     _tryTake = null;
     _proxy.OnCompleted();
     _proxy = null;
 }
示例#19
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 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));
        }