Ejemplo n.º 1
0
            protected override void DrainOutput()
            {
                var a = actual;

                int missed = 1;

                for (;;)
                {
                    bool d = Volatile.Read(ref done);

                    bool empty;

                    try
                    {
                        empty = queue.IsEmpty();
                    }
                    catch (Exception ex)
                    {
                        ExceptionHelper.ThrowIfFatal(ex);

                        s.Cancel();

                        ExceptionHelper.AddError(ref error, ex);
                        ex = ExceptionHelper.Terminate(ref error);

                        a.OnError(ex);

                        worker.Dispose();
                        return;
                    }

                    if (!empty)
                    {
                        a.TryOnNext(default(T));
                    }

                    if (d)
                    {
                        Exception ex = Volatile.Read(ref error);
                        if (ex != null)
                        {
                            a.OnError(ex);
                        }
                        else
                        {
                            a.OnComplete();
                        }

                        worker.Dispose();
                        return;
                    }

                    missed = QueueDrainHelper.Leave(ref wip, missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }
Ejemplo n.º 2
0
        public bool IsValid()
        {
            if (this.Name.Length > 255)
            {
                ExceptionHelper.AddError("FeatureName:", "Should less than 255 characters!");
                return(false);
            }

            return(true);
        }
 public override void OnError(Exception e)
 {
     if (ExceptionHelper.AddError(ref error, e))
     {
         Drain();
     }
     else
     {
         ExceptionHelper.OnErrorDropped(e);
     }
 }
 internal void otherError(Exception e)
 {
     if (ExceptionHelper.AddError(ref error, e))
     {
         Drain();
     }
     else
     {
         ExceptionHelper.OnErrorDropped(e);
     }
 }
Ejemplo n.º 5
0
 public void InnerError(CombineLatestSubscriber sender, Exception e)
 {
     if (ExceptionHelper.AddError(ref error, e))
     {
         InnerComplete(sender);
     }
     else
     {
         ExceptionHelper.OnErrorDropped(e);
     }
 }
Ejemplo n.º 6
0
 internal void CloseError(Exception e)
 {
     open.Cancel();
     if (ExceptionHelper.AddError(ref error, e))
     {
         Drain();
     }
     else
     {
         ExceptionHelper.OnErrorDropped(e);
     }
 }
Ejemplo n.º 7
0
 public void OnError(Exception e)
 {
     if (ExceptionHelper.AddError(ref error, e))
     {
         Volatile.Write(ref done, true);
         Schedule();
     }
     else
     {
         ExceptionHelper.OnErrorDropped(e);
     }
 }
 public override void OnError(Exception e)
 {
     if (ExceptionHelper.AddError(ref error, e))
     {
         Volatile.Write(ref done, true);
         Drain();
     }
     else
     {
         ExceptionHelper.OnErrorDropped(e);
     }
 }
 public void OnError(Exception e)
 {
     other.Cancel();
     if (ExceptionHelper.AddError(ref error, e))
     {
         Drain();
     }
     else
     {
         ExceptionHelper.OnErrorDropped(e);
     }
 }
 public override void InnerError(Exception e)
 {
     if (ExceptionHelper.AddError(ref error, e))
     {
         Volatile.Write(ref active, false);
         Drain();
     }
     else
     {
         ExceptionHelper.OnErrorDropped(e);
     }
 }
 internal void InnerError(Exception ex)
 {
     if (ExceptionHelper.AddError(ref error, ex))
     {
         CancelAll();
         Drain();
     }
     else
     {
         ExceptionHelper.OnErrorDropped(ex);
     }
 }
Ejemplo n.º 12
0
 internal void InnerError(Exception ex)
 {
     if (ExceptionHelper.AddError(ref error, ex))
     {
         Cancel();
         ex = ExceptionHelper.Terminate(ref error);
         actual.OnError(ex);
     }
     else
     {
         ExceptionHelper.OnErrorDropped(ex);
     }
 }
Ejemplo n.º 13
0
        public virtual bool IsValid()
        {
            if (this.CreateBy == null)
            {
                ExceptionHelper.AddError("CreateBy", "Should not have null value!");
            }

            if (this.CreateDate == null || this.CreateDate == DateTime.MinValue)
            {
                this.CreateDate = DateTime.Now;
            }

            return(true);
        }
Ejemplo n.º 14
0
            internal void InnerError(long index, SwitchMapInnerSubscriber inner, Exception ex)
            {
                if (Volatile.Read(ref this.index) == index)
                {
                    if (ExceptionHelper.AddError(ref error, ex))
                    {
                        s.Cancel();
                        inner.SetDone();
                        Drain();
                        return;
                    }
                }

                ExceptionHelper.OnErrorDropped(ex);
            }
Ejemplo n.º 15
0
 internal void InnerError(FlatMapInnerSubscriber sender, Exception ex)
 {
     if (ExceptionHelper.AddError(ref error, ex))
     {
         if (!delayErrors)
         {
             CancelAll();
         }
         sender.svDone();
         Drain();
     }
     else
     {
         ExceptionHelper.OnErrorDropped(ex);
     }
 }
Ejemplo n.º 16
0
            public void OnNext(T t)
            {
                if (done)
                {
                    return;
                }

                long idx = Interlocked.Increment(ref index);

                var current = Volatile.Read(ref inner);

                current?.Cancel();

                IPublisher <R> p;

                try
                {
                    p = mapper(t);
                    if (p == null)
                    {
                        throw new NullReferenceException("The mapper returned a null IPublisher");
                    }
                }
                catch (Exception ex)
                {
                    ExceptionHelper.ThrowIfFatal(ex);
                    s.Cancel();
                    if (ExceptionHelper.AddError(ref error, ex))
                    {
                        Volatile.Write(ref done, true);
                        Drain();
                    }
                    else
                    {
                        Volatile.Write(ref done, true);
                        ExceptionHelper.OnErrorDropped(ex);
                    }
                    return;
                }

                var inr = new SwitchMapInnerSubscriber(this, prefetch, idx);

                if (Interlocked.CompareExchange(ref inner, inr, current) == current)
                {
                    p.Subscribe(inr);
                }
            }
            public override void InnerError(Exception e)
            {
                if (ExceptionHelper.AddError(ref error, e))
                {
                    s.Cancel();

                    if (Interlocked.Increment(ref serializer) == 1)
                    {
                        e = ExceptionHelper.Terminate(ref error);
                        actual.OnError(e);
                    }
                }
                else
                {
                    ExceptionHelper.OnErrorDropped(e);
                }
            }
Ejemplo n.º 18
0
            public void InnerError(ZipInnerSubscriber inner, Exception ex)
            {
                if (ExceptionHelper.AddError(ref error, ex))
                {
                    inner.SetDone();

                    if (!delayErrors)
                    {
                        CancelAll();
                    }

                    Drain();
                }
                else
                {
                    ExceptionHelper.OnErrorDropped(ex);
                }
            }
            internal void InnerError(Exception ex)
            {
                if (ExceptionHelper.AddError(ref error, ex))
                {
                    ex = ExceptionHelper.Terminate(ref error);
                    if (!ExceptionHelper.IsTerminated(ex))
                    {
                        actual.OnError(ex);

                        if (QueueDrainHelper.Enter(ref wip))
                        {
                            Clear();
                        }
                    }
                }
                else
                {
                    ExceptionHelper.OnErrorDropped(ex);
                }
            }
Ejemplo n.º 20
0
 public void OnError(Exception e)
 {
     if (lvDone())
     {
         ExceptionHelper.OnErrorDropped(e);
     }
     else
     if (ExceptionHelper.AddError(ref error, e))
     {
         if (!delayErrors)
         {
             CancelAll();
         }
         Volatile.Write(ref done, true);
         Drain();
     }
     else
     {
         ExceptionHelper.OnErrorDropped(e);
     }
 }
Ejemplo n.º 21
0
 internal void OnError <T>(ISubscriber <T> actual, Exception e)
 {
     if (Volatile.Read(ref wip) == 0 && Interlocked.CompareExchange(ref wip, 1, 0) == 0)
     {
         actual.OnError(e);
     }
     else
     {
         if (ExceptionHelper.AddError(ref this.error, e))
         {
             if (Interlocked.Increment(ref wip) == 1)
             {
                 e = ExceptionHelper.Terminate(ref this.error);
                 actual.OnError(e);
             }
         }
         else
         {
             ExceptionHelper.OnErrorDropped(e);
         }
     }
 }
Ejemplo n.º 22
0
            void Drain()
            {
                if (!QueueDrainHelper.Enter(ref wip))
                {
                    return;
                }

                int missed = 1;
                var a      = actual;
                var q      = queue;
                var bs     = buffers;

                for (;;)
                {
                    for (;;)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            foreach (var close in buffers)
                            {
                                close.Cancel();
                            }
                            buffers.Clear();
                            queue.Clear();
                            return;
                        }

                        if (HandleException(a, q))
                        {
                            return;
                        }

                        BufferWork bw;

                        if (q.Poll(out bw))
                        {
                            switch (bw.type)
                            {
                            case BufferWorkType.COMPLETE:
                            {
                                var c = Interlocked.Exchange(ref this.s, SubscriptionHelper.Cancelled);

                                if (c == null)
                                {
                                    q.Clear();

                                    a.OnSubscribe(EmptySubscription <IList <T> > .Instance);
                                }
                                else
                                {
                                    c.Cancel();

                                    q.Clear();
                                }
                                long p = produced;
                                if (p != 0L)
                                {
                                    BackpressureHelper.Produced(ref requested, produced);
                                }
                                BackpressureHelper.PostComplete(ref requested, actual, this, ref cancelled);
                                return;
                            }

                            case BufferWorkType.OPEN:
                            {
                                var b = bw.buffer;

                                bs.AddLast(b);

                                IPublisher <V> p;

                                try
                                {
                                    p = close(b.u);
                                    if (p == null)
                                    {
                                        throw new NullReferenceException("The close function returned a null IPublisher");
                                    }
                                }
                                catch (Exception exc)
                                {
                                    ExceptionHelper.ThrowIfFatal(exc);
                                    ExceptionHelper.AddError(ref error, exc);
                                    HandleException(a, q);
                                    return;
                                }

                                p.Subscribe(b);
                            }
                            break;

                            case BufferWorkType.CLOSE:
                            {
                                if (bs.Remove(bw.buffer))
                                {
                                    var b = bw.buffer.buffer;
                                    if (b.Count != 0)
                                    {
                                        produced++;
                                        a.OnNext(b);
                                    }
                                    else
                                    {
                                        Request(1);
                                    }
                                }
                            }
                            break;

                            default:
                            {
                                foreach (var buffer in bs)
                                {
                                    buffer.buffer.Add(bw.value);
                                }
                            }
                            break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }

                    missed = QueueDrainHelper.Leave(ref wip, missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }
            void Drain()
            {
                if (!QueueDrainHelper.Enter(ref wip))
                {
                    return;
                }

                int missed = 1;
                var a      = actual;
                var q      = queue;
                var en     = enumerator;

                for (;;)
                {
                    if (en == null)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            q.Clear();
                            en?.Dispose();
                            enumerator = null;

                            return;
                        }

                        Exception ex = Volatile.Read(ref error);
                        if (ex != null)
                        {
                            ex = ExceptionHelper.Terminate(ref error);

                            q.Clear();
                            en?.Dispose();
                            enumerator = null;

                            a.OnError(ex);
                            return;
                        }

                        bool d = Volatile.Read(ref done);

                        T v;

                        if (queue.Poll(out v))
                        {
                            en         = mapper(v).GetEnumerator();
                            enumerator = en;
                        }
                        else
                        {
                            if (d)
                            {
                                en?.Dispose();
                                enumerator = null;

                                a.OnComplete();
                                return;
                            }
                        }
                    }

                    if (en != null)
                    {
                        long r = Volatile.Read(ref requested);
                        long e = 0L;

                        while (e != r)
                        {
                            if (Volatile.Read(ref cancelled))
                            {
                                q.Clear();
                                en?.Dispose();
                                enumerator = null;

                                return;
                            }

                            Exception ex = Volatile.Read(ref error);
                            if (ex != null)
                            {
                                ex = ExceptionHelper.Terminate(ref error);

                                q.Clear();
                                en?.Dispose();
                                enumerator = null;

                                a.OnError(ex);
                                return;
                            }

                            bool b = hasValue;

                            if (!b)
                            {
                                try
                                {
                                    b = en.MoveNext();
                                }
                                catch (Exception exc)
                                {
                                    ExceptionHelper.ThrowIfFatal(exc);

                                    s.Cancel();

                                    q.Clear();

                                    ExceptionHelper.AddError(ref error, exc);
                                    exc = ExceptionHelper.Terminate(ref error);

                                    a.OnError(exc);

                                    return;
                                }
                                hasValue = b;
                            }

                            if (b)
                            {
                                a.OnNext(en.Current);

                                e++;
                                hasValue = false;
                            }
                            else
                            {
                                en?.Dispose();
                                en         = null;
                                enumerator = en;
                                break;
                            }
                        }

                        if (e == r)
                        {
                            if (Volatile.Read(ref cancelled))
                            {
                                q.Clear();
                                en?.Dispose();
                                enumerator = null;

                                return;
                            }

                            Exception ex = Volatile.Read(ref error);
                            if (ex != null)
                            {
                                ex = ExceptionHelper.Terminate(ref error);

                                q.Clear();
                                en?.Dispose();
                                enumerator = null;

                                a.OnError(ex);
                                return;
                            }

                            bool b = hasValue;
                            if (!b)
                            {
                                try
                                {
                                    b = en.MoveNext();
                                }
                                catch (Exception exc)
                                {
                                    ExceptionHelper.ThrowIfFatal(exc);

                                    s.Cancel();

                                    q.Clear();

                                    ExceptionHelper.AddError(ref error, exc);
                                    exc = ExceptionHelper.Terminate(ref error);

                                    a.OnError(exc);

                                    return;
                                }
                                hasValue = b;
                            }

                            if (!b)
                            {
                                en?.Dispose();
                                en         = null;
                                enumerator = en;
                            }
                        }

                        if (e != 0 && r != long.MaxValue)
                        {
                            Interlocked.Add(ref requested, -e);
                        }

                        if (en == null)
                        {
                            continue;
                        }
                    }

                    missed = QueueDrainHelper.Leave(ref wip, missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }
            public override void Drain()
            {
                if (!QueueDrainHelper.Enter(ref wip))
                {
                    return;
                }

                for (;;)
                {
                    if (Volatile.Read(ref cancelled))
                    {
                        queue.Clear();
                        return;
                    }
                    if (!Volatile.Read(ref active))
                    {
                        bool d = Volatile.Read(ref done);

                        T t;

                        bool empty;

                        try
                        {
                            empty = !queue.Poll(out t);
                        }
                        catch (Exception ex)
                        {
                            ExceptionHelper.ThrowIfFatal(ex);
                            s.Cancel();
                            queue.Clear();
                            ExceptionHelper.AddError(ref error, ex);
                            ex = ExceptionHelper.Terminate(ref error);

                            actual.OnError(ex);
                            return;
                        }

                        if (d && empty)
                        {
                            actual.OnComplete();
                            return;
                        }

                        if (!empty)
                        {
                            if (fusionMode != FuseableHelper.SYNC)
                            {
                                int c = consumed + 1;
                                if (c == limit)
                                {
                                    consumed = 0;
                                    s.Request(c);
                                }
                                else
                                {
                                    consumed = c;
                                }
                            }


                            IPublisher <R> p;

                            try
                            {
                                p = mapper(t);
                            }
                            catch (Exception ex)
                            {
                                ExceptionHelper.ThrowIfFatal(ex);
                                s.Cancel();
                                queue.Clear();
                                ExceptionHelper.AddError(ref error, ex);
                                ex = ExceptionHelper.Terminate(ref error);

                                actual.OnError(ex);
                                return;
                            }

                            if (p == null)
                            {
                                s.Cancel();
                                queue.Clear();
                                ExceptionHelper.AddError(ref error, new NullReferenceException("The mapper returned a null IPublisher."));
                                var ex = ExceptionHelper.Terminate(ref error);

                                actual.OnError(ex);
                                return;
                            }

                            Volatile.Write(ref active, true);
                            p.Subscribe(inner);
                        }
                    }

                    if (Interlocked.Decrement(ref wip) == 0)
                    {
                        break;
                    }
                }
            }
Ejemplo n.º 25
0
            protected override void DrainAsyncNoDelay()
            {
                var a = actual;
                var q = queue;

                long e   = emitted;
                long p   = polled;
                int  lim = limit;

                int missed = 1;

                for (;;)
                {
                    long r = Volatile.Read(ref requested);

                    while (e != r)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            q.Clear();
                            return;
                        }

                        bool d = Volatile.Read(ref done);

                        if (d)
                        {
                            Exception ex = error;
                            if (ex != null)
                            {
                                q.Clear();
                                a.OnError(ex);

                                worker.Dispose();
                                return;
                            }
                        }

                        T v;

                        bool empty;

                        try
                        {
                            empty = !q.Poll(out v);
                        }
                        catch (Exception ex)
                        {
                            ExceptionHelper.ThrowIfFatal(ex);

                            s.Cancel();
                            q.Clear();

                            ExceptionHelper.AddError(ref error, ex);
                            ex = ExceptionHelper.Terminate(ref error);

                            a.OnError(ex);

                            worker.Dispose();
                            return;
                        }

                        if (d && empty)
                        {
                            a.OnComplete();

                            worker.Dispose();
                            return;
                        }

                        if (empty)
                        {
                            break;
                        }

                        if (a.TryOnNext(v))
                        {
                            e++;
                        }

                        if (++p == lim)
                        {
                            p = 0L;
                            s.Request(lim);
                        }
                    }

                    if (e == r)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            q.Clear();
                            return;
                        }

                        bool d = Volatile.Read(ref done);

                        if (d)
                        {
                            Exception ex = error;
                            if (ex != null)
                            {
                                q.Clear();
                                a.OnError(ex);

                                worker.Dispose();
                                return;
                            }
                            if (q.IsEmpty())
                            {
                                a.OnComplete();

                                worker.Dispose();
                                return;
                            }
                        }
                    }

                    emitted = e;
                    polled  = p;
                    missed  = QueueDrainHelper.Leave(ref wip, missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }
            void DrainLoop()
            {
                int missed = 1;
                var a      = actual;
                var array  = subscribers;
                int n      = array.Length;

                for (;;)
                {
                    long r = Volatile.Read(ref requested);
                    long e = 0L;

                    while (e != r)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            Cleanup();
                            return;
                        }

                        var ex = Volatile.Read(ref error);
                        if (ex != null)
                        {
                            ex = ExceptionHelper.Terminate(ref error);
                            Cleanup();
                            a.OnError(ex);
                            return;
                        }

                        bool d = Volatile.Read(ref done) == 0;

                        bool empty = true;

                        bool full = false;

                        foreach (var inner in array)
                        {
                            var q = Volatile.Read(ref inner.queue);

                            if (q != null)
                            {
                                T v;

                                bool hasValue;

                                try
                                {
                                    hasValue = q.Poll(out v);
                                }
                                catch (Exception exc)
                                {
                                    ExceptionHelper.AddError(ref error, exc);
                                    ex = ExceptionHelper.Terminate(ref error);
                                    CancelAll();
                                    Cleanup();
                                    a.OnError(ex);
                                    return;
                                }

                                if (hasValue)
                                {
                                    empty = false;
                                    a.OnNext(v);
                                    inner.RequestOne();
                                    if (++e == r)
                                    {
                                        full = true;
                                        break;
                                    }
                                }
                            }
                        }

                        if (full)
                        {
                            break;
                        }

                        if (d && empty)
                        {
                            a.OnComplete();
                            return;
                        }

                        if (empty)
                        {
                            break;
                        }
                    }

                    if (e == r)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            Cleanup();
                            return;
                        }

                        var ex = Volatile.Read(ref error);
                        if (ex != null)
                        {
                            ex = ExceptionHelper.Terminate(ref error);
                            Cleanup();
                            a.OnError(ex);
                            return;
                        }

                        bool d = Volatile.Read(ref done) == 0;

                        bool empty = true;

                        foreach (var inner in array)
                        {
                            var q = Volatile.Read(ref inner.queue);
                            if (q != null && !q.IsEmpty())
                            {
                                empty = false;
                                break;
                            }
                        }

                        if (d && empty)
                        {
                            a.OnComplete();
                            return;
                        }
                    }

                    if (e != 0L && r != long.MaxValue)
                    {
                        Interlocked.Add(ref requested, -e);
                    }

                    missed = QueueDrainHelper.Leave(ref wip, missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }
Ejemplo n.º 27
0
            void DrainLoop()
            {
                int missed = 1;

                var a = actual;

                for (;;)
                {
                    long r = Volatile.Read(ref requested);
                    long m = 0;
                    long e = 0;
                    bool d;

                    var sq = Volatile.Read(ref scalarQueue);

                    if (sq != null)
                    {
                        while (e != r)
                        {
                            if (CheckCancelOrError(a))
                            {
                                return;
                            }

                            R v;

                            if (sq.Poll(out v))
                            {
                                a.OnNext(v);

                                e++;
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    var inners = tracker.Values();

                    int n = inners.Length;

                    for (int i = 0; i < n; i++)
                    {
                        if (CheckCancelOrError(a))
                        {
                            return;
                        }

                        var inner = Volatile.Read(ref inners[i]);
                        if (inner != null)
                        {
                            d = inner.lvDone();
                            IQueue <R> q = inner.GetQueue();

                            if (q == null || q.IsEmpty())
                            {
                                if (d)
                                {
                                    m++;
                                    tracker.Remove(i);
                                }
                            }
                            else
                            {
                                while (e != r)
                                {
                                    if (CheckCancelOrError(a))
                                    {
                                        return;
                                    }

                                    d = inner.lvDone();

                                    R v;

                                    bool hasValue;

                                    try
                                    {
                                        hasValue = q.Poll(out v);
                                    }
                                    catch (Exception ex)
                                    {
                                        ExceptionHelper.ThrowIfFatal(ex);
                                        inner.Cancel();
                                        ExceptionHelper.AddError(ref error, ex);

                                        if (CheckCancelOrError(a))
                                        {
                                            return;
                                        }
                                        d        = true;
                                        hasValue = false;
                                        v        = default(R);
                                    }
                                    if (hasValue)
                                    {
                                        a.OnNext(v);

                                        e++;
                                        inner.RequestOne();
                                    }
                                    else
                                    {
                                        if (d)
                                        {
                                            m++;
                                            tracker.Remove(i);
                                        }
                                        break;
                                    }
                                }

                                if (e == r)
                                {
                                    if (CheckCancelOrError(a))
                                    {
                                        return;
                                    }

                                    if (inner.lvDone() && q.IsEmpty())
                                    {
                                        m++;
                                        tracker.Remove(i);
                                    }
                                }
                            }
                        }
                    }

                    if (CheckCancelOrError(a))
                    {
                        return;
                    }

                    d = lvDone();

                    n = tracker.Size();

                    sq = Volatile.Read(ref scalarQueue);

                    if (d && n == 0 && (sq == null || sq.IsEmpty()))
                    {
                        Exception ex = lvError();
                        if (ex != null)
                        {
                            ex = ExceptionHelper.Terminate(ref error);

                            a.OnError(ex);
                        }
                        else
                        {
                            a.OnComplete();
                        }
                        return;
                    }

                    if (e != 0 && r != long.MaxValue)
                    {
                        Interlocked.Add(ref requested, -e);
                    }

                    if (m != 0 && !lvDone() && !lvCancelled())
                    {
                        s.Request(m);
                    }

                    missed = QueueDrainHelper.Leave(ref wip, missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }
Ejemplo n.º 28
0
            void DrainNoDelay()
            {
                var a = actual;
                var c = latest;
                int n = c.Length;
                var q = queue;

                int missed = 1;

                for (;;)
                {
                    if (Volatile.Read(ref cancelled))
                    {
                        Cleanup();
                        return;
                    }

                    if (Volatile.Read(ref hasEmptySource))
                    {
                        Exception ex = ExceptionHelper.Terminate(ref error);
                        Cleanup();
                        if (ex != null)
                        {
                            a.OnError(ex);
                        }
                        else
                        {
                            a.OnComplete();
                        }

                        return;
                    }

                    long r = Volatile.Read(ref requested);
                    long e = 0L;

                    while (e != r)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            Cleanup();
                            return;
                        }

                        Exception ex = Volatile.Read(ref error);

                        if (ex != null)
                        {
                            ex = ExceptionHelper.Terminate(ref error);
                            Cleanup();
                            a.OnError(ex);
                            return;
                        }

                        bool d = Volatile.Read(ref complete) == n;

                        Entry v;
                        bool  empty = !q.Poll(out v);

                        if (d && empty)
                        {
                            Cleanup();
                            a.OnComplete();
                            return;
                        }

                        R result;

                        try
                        {
                            result = combiner(v.row);
                        }
                        catch (Exception exc)
                        {
                            ExceptionHelper.ThrowIfFatal(exc);

                            CancelAll();
                            Cleanup();

                            ExceptionHelper.AddError(ref error, exc);
                            exc = ExceptionHelper.Terminate(ref error);

                            a.OnError(exc);
                            return;
                        }

                        if (a.TryOnNext(result))
                        {
                            e++;
                        }
                        v.sender.RequestOne();
                    }

                    if (e == r)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            Cleanup();
                            return;
                        }

                        Exception ex = Volatile.Read(ref error);

                        if (ex != null)
                        {
                            ex = ExceptionHelper.Terminate(ref error);
                            Cleanup();
                            a.OnError(ex);
                            return;
                        }

                        if (Volatile.Read(ref complete) == n && q.IsEmpty())
                        {
                            Cleanup();

                            a.OnComplete();
                            return;
                        }
                    }

                    if (e != 0 && r != long.MaxValue)
                    {
                        Interlocked.Add(ref requested, -e);
                    }

                    missed = QueueDrainHelper.Leave(ref wip, missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }
Ejemplo n.º 29
0
            internal void Drain()
            {
                if (!QueueDrainHelper.Enter(ref wip))
                {
                    return;
                }

                int missed = 1;

                var a = actual;

                for (;;)
                {
                    long r = Volatile.Read(ref requested);
                    long e = 0L;

                    while (e != r)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            inner = null;
                            return;
                        }

                        Exception ex = Volatile.Read(ref error);
                        if (ex != null)
                        {
                            ex = ExceptionHelper.Terminate(ref error);

                            inner = null;
                            a.OnError(ex);
                            return;
                        }

                        bool d = Volatile.Read(ref done);

                        var inr = Volatile.Read(ref inner);

                        d = d && (inr == null || inr.IsDone());

                        R v;

                        bool empty;

                        if (inr != null)
                        {
                            try
                            {
                                empty = !inr.queue.Poll(out v);
                            }
                            catch (Exception exc)
                            {
                                ExceptionHelper.ThrowIfFatal(exc);

                                ExceptionHelper.AddError(ref error, exc);

                                s.Cancel();
                                inner = null;

                                exc = ExceptionHelper.Terminate(ref error);

                                a.OnError(exc);
                                return;
                            }
                        }
                        else
                        {
                            v     = default(R);
                            empty = true;
                        }

                        if (d && empty)
                        {
                            inner = null;
                            a.OnComplete();
                            return;
                        }

                        if (empty)
                        {
                            break;
                        }

                        a.OnNext(v);

                        e++;
                        inner.RequestOne();
                    }

                    if (e == r)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            inner = null;
                            return;
                        }

                        Exception ex = Volatile.Read(ref error);
                        if (ex != null)
                        {
                            ex = ExceptionHelper.Terminate(ref error);

                            inner = null;
                            a.OnError(ex);
                            return;
                        }

                        bool d = Volatile.Read(ref done);

                        var inr = Volatile.Read(ref inner);

                        d = d && (inr == null || inr.IsDone());

                        bool empty = inr == null || inr.queue.IsEmpty();

                        if (d && empty)
                        {
                            inner = null;

                            a.OnComplete();
                            return;
                        }
                    }

                    if (e != 0L && r != long.MaxValue)
                    {
                        Interlocked.Add(ref requested, -e);
                    }

                    missed = QueueDrainHelper.Leave(ref wip, missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }
Ejemplo n.º 30
0
            public void Drain()
            {
                if (!QueueDrainHelper.Enter(ref wip))
                {
                    return;
                }

                var a      = actual;
                var s      = subscribers;
                var c      = current;
                int n      = s.Length;
                int missed = 1;

                for (;;)
                {
                    long r = Volatile.Read(ref requested);
                    long e = 0L;

                    for (;;)
                    {
                        if (!delayErrors)
                        {
                            Exception ex = Volatile.Read(ref error);
                            if (ex != null)
                            {
                                ex = ExceptionHelper.Terminate(ref error);
                                ClearAll();
                                ClearCurrent();

                                a.OnError(ex);
                                return;
                            }
                        }


                        int done     = 0;
                        int hasValue = 0;

                        for (int i = 0; i < n; i++)
                        {
                            var inner = s[i];

                            if (inner.IsDone())
                            {
                                done++;

                                if (!inner.NonEmpty())
                                {
                                    CancelAll();
                                    ClearAll();
                                    ClearCurrent();

                                    a.OnComplete();
                                    return;
                                }
                            }

                            if (inner.HasValue())
                            {
                                hasValue++;
                            }
                            else
                            {
                                if (inner.Poll(out c[i]))
                                {
                                    inner.HasValue(true);
                                    hasValue++;
                                }
                            }
                        }

                        if (done == n && hasValue != n)
                        {
                            Exception ex = Volatile.Read(ref error);
                            if (ex != null)
                            {
                                ex = ExceptionHelper.Terminate(ref error);
                                ClearCurrent();

                                a.OnError(ex);
                            }
                            else
                            {
                                a.OnComplete();
                            }

                            return;
                        }

                        if (hasValue != n)
                        {
                            break;
                        }

                        if (e == r)
                        {
                            break;
                        }

                        var row = new T[n];

                        for (int i = 0; i < n; i++)
                        {
                            row[i] = current[i];

                            var inner = s[i];
                            inner.HasValue(false);
                            inner.RequestOne();
                        }

                        R t;

                        try
                        {
                            t = zipper(row);
                        }
                        catch (Exception ex)
                        {
                            ExceptionHelper.ThrowIfFatal(ex);
                            ExceptionHelper.AddError(ref error, ex);

                            ex = ExceptionHelper.Terminate(ref error);

                            CancelAll();
                            ClearAll();
                            ClearCurrent();

                            a.OnError(ex);
                            return;
                        }

                        if (a.TryOnNext(t))
                        {
                            e++;
                        }
                    }

                    if (e != 0L && r != long.MaxValue)
                    {
                        Interlocked.Add(ref requested, -e);
                    }

                    missed = QueueDrainHelper.Leave(ref wip, missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }