public void InnerNext(InnerSignalObserver <R> sender, R item)
            {
                if (Interlocked.CompareExchange(ref wip, 1, 0) == 0)
                {
                    var q = sender.GetQueue();

                    if (current == sender && (q == null || q.IsEmpty()))
                    {
                        downstream.OnNext(item);
                    }
                    else
                    {
                        if (q == null)
                        {
                            q = sender.CreateQueue(capacityHint);
                        }
                        q.TryOffer(item);
                    }
                    if (Interlocked.Decrement(ref wip) == 0)
                    {
                        return;
                    }
                }
                else
                {
                    var q = sender.GetOrCreateQueue(capacityHint);
                    q.TryOffer(item);
                    if (Interlocked.Increment(ref wip) != 1)
                    {
                        return;
                    }
                }

                DrainLoop();
            }
            public void UpstreamNext(T value)
            {
                if (IsDisposed())
                {
                    return;
                }
                var o = default(IObservableSource <R>);

                try
                {
                    o = ValidationHelper.RequireNonNullRef(mapper(value), "The mapper returned a null IObservableSource");
                }
                catch (Exception ex)
                {
                    base.Dispose();
                    OnError(ex);
                    return;
                }

                var inner = new InnerSignalObserver <R>(this);

                observers.Offer(inner);

                if (!IsDisposed())
                {
                    o.Subscribe(inner);
                }
                Drain();
            }
Esempio n. 3
0
            void Remove(InnerSignalObserver <R> inner)
            {
                for (; ;)
                {
                    var a = Volatile.Read(ref observers);
                    var n = a.Length;
                    if (n == 0)
                    {
                        break;
                    }

                    var j = Array.IndexOf(a, inner);
                    if (j < 0)
                    {
                        break;
                    }

                    var b = default(InnerSignalObserver <R>[]);
                    if (n == 1)
                    {
                        b = Empty;
                    }
                    else
                    {
                        b = new InnerSignalObserver <R> [n - 1];
                        Array.Copy(a, 0, b, 0, j);
                        Array.Copy(a, j + 1, b, j, n - j - 1);
                    }
                    if (Interlocked.CompareExchange(ref observers, b, a) == a)
                    {
                        break;
                    }
                }
            }
 public void InnerNext(InnerSignalObserver <R> sender, R item)
 {
     if (Interlocked.CompareExchange(ref wip, 1, 0) == 0)
     {
         var a = Volatile.Read(ref active);
         if (a == sender)
         {
             downstream.OnNext(item);
         }
         if (Interlocked.Decrement(ref wip) == 0)
         {
             return;
         }
     }
     else
     {
         var a = Volatile.Read(ref active);
         if (a == sender)
         {
             var q = sender.GetOrCreateQueue(capacityHint);
             q.TryOffer(item);
             if (Interlocked.Increment(ref wip) != 1)
             {
                 return;
             }
         }
     }
     DrainLoop();
 }
 public void InnerError(InnerSignalObserver <R> sender, Exception error)
 {
     if (Interlocked.CompareExchange(ref this.error, error, null) == null)
     {
         sender.SetDone();
         Volatile.Write(ref done, true);
         Drain();
     }
 }
 public void InnerComplete(InnerSignalObserver <R> sender)
 {
     sender.Dispose();
     if (Volatile.Read(ref active) == sender)
     {
         sender.SetDone();
         Drain();
     }
 }
Esempio n. 7
0
 public void InnerError(InnerSignalObserver <R> sender, Exception ex)
 {
     if (delayErrors)
     {
         ExceptionHelper.AddException(ref errors, ex);
     }
     else
     {
         Interlocked.CompareExchange(ref errors, ex, null);
     }
     sender.SetDone();
     Drain();
 }
Esempio n. 8
0
            public void OnNext(T item)
            {
                if (done)
                {
                    return;
                }
                var q = sourceQueue;

                if (q == null)
                {
                    var src = default(IObservableSource <R>);

                    try
                    {
                        src = ValidationHelper.RequireNonNullRef(mapper(item), "The mapper returned a null IObservableSource");
                    }
                    catch (Exception ex)
                    {
                        upstream.Dispose();
                        OnError(ex);
                        return;
                    }

                    if (src is IDynamicValue <R> d)
                    {
                        TryEmitScalar(d);
                    }
                    else
                    {
                        var inner = new InnerSignalObserver <R>(this);
                        if (Add(inner))
                        {
                            src.Subscribe(inner);
                        }
                    }
                }
                else
                {
                    q.TryOffer(item);
                    Drain();
                }
            }
Esempio n. 9
0
            bool Add(InnerSignalObserver <R> inner)
            {
                for (; ;)
                {
                    var a = Volatile.Read(ref observers);
                    if (a == Terminated)
                    {
                        return(false);
                    }
                    var n = a.Length;
                    var b = new InnerSignalObserver <R> [n + 1];
                    Array.Copy(a, 0, b, 0, n);
                    b[n] = inner;

                    if (Interlocked.CompareExchange(ref observers, b, a) == a)
                    {
                        return(true);
                    }
                }
            }
 public void InnerError(InnerSignalObserver <R> sender, Exception error)
 {
     sender.Dispose();
     if (Volatile.Read(ref active) == sender)
     {
         if (delayErrors)
         {
             ExceptionHelper.AddException(ref errors, error);
             sender.SetDone();
             Drain();
         }
         else
         {
             if (Interlocked.CompareExchange(ref errors, error, null) == null)
             {
                 sender.SetDone();
                 Drain();
             }
         }
     }
 }
            public override void OnNext(T value)
            {
                if (done)
                {
                    return;
                }

                var o = default(IObservableSource <R>);

                try
                {
                    o = ValidationHelper.RequireNonNullRef(mapper(value), "The mapper returned a null IObservableSource");
                }
                catch (Exception ex)
                {
                    OnError(ex);
                    return;
                }

                var inner = new InnerSignalObserver <R>(this);

                for (; ;)
                {
                    var a = Volatile.Read(ref active);
                    if (a == DISPOSED)
                    {
                        break;
                    }

                    if (Interlocked.CompareExchange(ref active, inner, a) == a)
                    {
                        a?.Dispose();

                        o.Subscribe(inner);
                        break;
                    }
                }
            }
            void DrainLoop()
            {
                int missed    = 1;
                var observers = this.observers;

                for (; ;)
                {
                    if (Volatile.Read(ref disposed))
                    {
                        if (current != null)
                        {
                            current.Dispose();
                            current = null;
                        }

                        for (; ;)
                        {
                            var inner = observers.TryPoll(out var success);
                            if (!success)
                            {
                                break;
                            }
                            inner.Dispose();
                        }
                        Cleanup();
                    }
                    else
                    {
                        var curr = current;
                        if (curr == null)
                        {
                            var d = Volatile.Read(ref done);

                            if (d)
                            {
                                var ex = Volatile.Read(ref error);
                                if (ex != null)
                                {
                                    downstream.OnError(ex);
                                    Volatile.Write(ref disposed, true);
                                    base.Dispose();
                                    continue;
                                }
                            }

                            curr = observers.TryPoll(out var success);
                            var empty = !success;

                            if (d && empty)
                            {
                                downstream.OnCompleted();
                                Volatile.Write(ref disposed, true);
                                base.Dispose();
                            }

                            current = curr;
                        }
                        if (curr != null)
                        {
                            var continueOuter = false;
                            for (; ;)
                            {
                                if (Volatile.Read(ref disposed))
                                {
                                    continueOuter = true;
                                    break;
                                }

                                var d = curr.IsDone();
                                var q = curr.GetQueue();

                                var v       = default(R);
                                var success = false;

                                if (q != null)
                                {
                                    try
                                    {
                                        v = q.TryPoll(out success);
                                    }
                                    catch (Exception ex)
                                    {
                                        Interlocked.CompareExchange(ref this.error, ex, null);
                                        Volatile.Write(ref disposed, true);
                                        continueOuter = true;
                                        break;
                                    }
                                }

                                if (d && !success)
                                {
                                    curr.Dispose();
                                    current = null;
                                    curr    = null;
                                    InnerConsumed();
                                    continueOuter = true;
                                    break;
                                }

                                if (!success)
                                {
                                    break;
                                }

                                downstream.OnNext(v);
                            }

                            if (continueOuter)
                            {
                                continue;
                            }
                        }
                    }

                    missed = Interlocked.Add(ref wip, -missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }
 public void InnerComplete(InnerSignalObserver <R> sender)
 {
     sender.SetDone();
     Drain();
 }
Esempio n. 14
0
            void DrainLoop()
            {
                var missed         = 1;
                var downstream     = this.downstream;
                var delayErrors    = this.delayErrors;
                var maxConcurrency = this.maxConcurrency;

                for (; ;)
                {
                    if (Volatile.Read(ref disposed))
                    {
                        Volatile.Read(ref scalarQueue)?.Clear();
                        sourceQueue?.Clear();
                    }
                    else
                    {
                        if (!delayErrors)
                        {
                            var ex = Volatile.Read(ref errors);
                            if (ex != null)
                            {
                                downstream.OnError(ex);

                                Volatile.Write(ref disposed, true);
                                upstream.Dispose();
                                DisposeAll();
                                continue;
                            }
                        }

                        var d = Volatile.Read(ref done);

                        var sq = Volatile.Read(ref scalarQueue);

                        if (sq != null)
                        {
                            var v = sq.TryPoll(out var success);
                            if (success)
                            {
                                downstream.OnNext(v);
                                continue;
                            }
                        }

                        var obs = Volatile.Read(ref observers);
                        var n   = obs.Length;

                        var srcs = sourceQueue;
                        if (srcs != null)
                        {
                            if (!noMoreSources && n < maxConcurrency && !srcs.IsEmpty())
                            {
                                var v = srcs.TryPoll(out var success);

                                var src = default(IObservableSource <R>);

                                try
                                {
                                    src = ValidationHelper.RequireNonNullRef(mapper(v), "The mapper returned a null IObservableSource");
                                }
                                catch (Exception ex)
                                {
                                    upstream.Dispose();
                                    if (delayErrors)
                                    {
                                        ExceptionHelper.AddException(ref errors, ex);
                                    }
                                    else
                                    {
                                        Interlocked.CompareExchange(ref errors, ex, null);
                                    }
                                    success       = false;
                                    noMoreSources = true;
                                    srcs?.Clear();
                                    continue;
                                }

                                if (success)
                                {
                                    if (src is IDynamicValue <R> dv)
                                    {
                                        var w = default(R);
                                        var s = false;

                                        try
                                        {
                                            w = dv.GetValue(out s);
                                        }
                                        catch (Exception ex)
                                        {
                                            if (delayErrors)
                                            {
                                                ExceptionHelper.AddException(ref errors, ex);
                                            }
                                            else
                                            {
                                                Interlocked.CompareExchange(ref errors, ex, null);
                                            }
                                            continue;
                                        }

                                        if (s)
                                        {
                                            downstream.OnNext(w);
                                        }
                                        continue;
                                    }
                                    else
                                    {
                                        var inner = new InnerSignalObserver <R>(this);
                                        if (Add(inner))
                                        {
                                            src.Subscribe(inner);
                                            continue;
                                        }
                                    }
                                }
                            }
                        }

                        if (d && n == 0 && (sq == null || sq.IsEmpty()) && (noMoreSources || srcs == null || srcs.IsEmpty()))
                        {
                            var ex = Volatile.Read(ref errors);
                            if (ex != null)
                            {
                                downstream.OnError(ex);
                            }
                            else
                            {
                                downstream.OnCompleted();
                            }
                            Volatile.Write(ref disposed, true);
                        }
                        else
                        if (n != 0)
                        {
                            var continueOuter = false;
                            var removed       = false;

                            for (int j = 0; j < n; j++)
                            {
                                var inner = obs[j];

                                for (; ;)
                                {
                                    if (Volatile.Read(ref disposed))
                                    {
                                        continueOuter = true;
                                        break;
                                    }
                                    if (!delayErrors && Volatile.Read(ref errors) != null)
                                    {
                                        continueOuter = true;
                                        break;
                                    }

                                    var innerDone  = inner.IsDone();
                                    var innerQueue = inner.GetQueue();

                                    if (innerDone && (innerQueue == null || innerQueue.IsEmpty()))
                                    {
                                        Remove(inner);
                                        removed = true;
                                        break;
                                    }
                                    else
                                    if (innerQueue != null)
                                    {
                                        if (innerQueue.IsEmpty())
                                        {
                                            break;
                                        }

                                        var v    = default(R);
                                        var succ = false;

                                        try
                                        {
                                            v = innerQueue.TryPoll(out succ);
                                        }
                                        catch (Exception ex)
                                        {
                                            inner.Dispose();
                                            inner.SetDone();
                                            Remove(inner);
                                            if (delayErrors)
                                            {
                                                ExceptionHelper.AddException(ref errors, ex);
                                            }
                                            else
                                            {
                                                Interlocked.CompareExchange(ref errors, ex, null);
                                            }
                                            removed = true;
                                            break;
                                        }

                                        if (succ)
                                        {
                                            downstream.OnNext(v);
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }

                                if (continueOuter)
                                {
                                    break;
                                }
                            }

                            if (continueOuter || removed)
                            {
                                continue;
                            }
                        }
                    }

                    missed = Interlocked.Add(ref wip, -missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }