예제 #1
0
        void OnNext(PublisherMergeInner inner, R value)
        {
            if (bp.TryEnter())
            {
                long r = bp.Requested();

                if (r != 0L)
                {
                    actual.OnNext(value);

                    if (r != long.MaxValue)
                    {
                        bp.Produced(1);
                    }

                    inner.Request(1);
                }
                else
                {
                    inner.Enqueue(value);
                }

                if (bp.Leave())
                {
                    return;
                }
            }
            else
            {
                inner.Enqueue(value);

                if (!bp.Enter())
                {
                    return;
                }
            }

            DrainLoop();
        }
예제 #2
0
        void DrainLoop()
        {
            ISubscriber <R> a = actual;

            int missed = 1;

            for (;;)
            {
                bool d = IsDone();
                PublisherMergeInner[] inners = Volatile.Read(ref subscribers);
                int n = inners.Length;

                bool empty = n == 0 && q.IsEmpty();

                if (CheckTerminated(d, empty, a))
                {
                    return;
                }

                long r = bp.Requested();
                long e = 0L;

                if (r != 0L)
                {
                    if (q.IsConsumable())
                    {
                        while (e != r)
                        {
                            d = IsDone();

                            R t;

                            empty = !q.Poll(out t);

                            if (CheckTerminated(d, empty, a))
                            {
                                return;
                            }

                            if (empty)
                            {
                                break;
                            }

                            a.OnNext(t);

                            e++;
                        }

                        if (e != 0L)
                        {
                            r = bp.Produced(e);

                            s.Request(e);

                            e = 0L;
                        }
                    }

                    d      = IsDone();
                    inners = Volatile.Read(ref subscribers);
                    n      = inners.Length;

                    empty = n == 0 && q.IsEmpty();

                    if (CheckTerminated(d, empty, a))
                    {
                        return;
                    }
                }

                int idx = lastIndex;
                if (idx >= n)
                {
                    idx = 0;
                }

                for (int i = 0; i < n; i++)
                {
                    PublisherMergeInner inner = inners[idx];

                    d     = inner.IsDone();
                    empty = inner.IsEmpty();

                    if (d && empty)
                    {
                        Remove(inner);

                        s.Request(1);

                        inners = Volatile.Read(ref subscribers);
                        n      = inners.Length;
                        idx--;
                    }
                    else
                    if (r != e && !empty)
                    {
                        while (e != r)
                        {
                            d = inner.IsDone();

                            R t;

                            empty = !inner.Poll(out t);

                            if (d && empty)
                            {
                                Remove(inner);

                                s.Request(1);

                                inners = Volatile.Read(ref subscribers);
                                n      = inners.Length;
                                idx--;

                                break;
                            }
                            else
                            if (empty)
                            {
                                break;
                            }

                            a.OnNext(t);

                            e++;
                        }

                        d     = inner.IsDone();
                        empty = inner.IsEmpty();

                        if (e == r && d && empty)
                        {
                            Remove(inner);

                            s.Request(1);

                            inners = Volatile.Read(ref subscribers);
                            n      = inners.Length;
                            idx--;
                        }

                        if (e != 0L)
                        {
                            r = bp.Produced(e);

                            if (!d)
                            {
                                inner.Request((int)e);
                            }

                            e = 0L;
                        }
                    }

                    idx++;
                    if (idx >= n)
                    {
                        idx = 0;
                    }
                }

                d      = IsDone();
                inners = Volatile.Read(ref subscribers);
                n      = inners.Length;

                empty = n == 0 && q.IsEmpty();

                if (CheckTerminated(d, empty, a))
                {
                    return;
                }

                lastIndex = idx;

                missed = bp.Leave(missed);
                if (missed == 0)
                {
                    break;
                }
            }
        }