Exemple #1
0
 void InnerNext(InnerSubscriber inner, T item)
 {
     if (Volatile.Read(ref wip) == 0 && Interlocked.CompareExchange(ref wip, 1, 0) == 0)
     {
         long r = Volatile.Read(ref requested);
         long e = emitted;
         if (e != r)
         {
             actual.OnNext(item);
             emitted = e + 1;
             inner.Produced(limit);
         }
         else
         {
             var q = inner.GetOrCreateQueue(limit);
             q.Offer(item);
         }
         int w = Interlocked.Decrement(ref wip);
         if (w == 0)
         {
             return;
         }
         DrainLoop(w);
     }
     else
     {
         var q = inner.GetOrCreateQueue(limit);
         q.Offer(item);
         if (Interlocked.Increment(ref wip) != 1)
         {
             return;
         }
         DrainLoop(1);
     }
 }
            public void OnNext(T element)
            {
                if (done)
                {
                    return;
                }
                IPublisher <R> p;

                try
                {
                    p = mapper(element);
                    if (p == null)
                    {
                        throw new NullReferenceException("The mapper returned a null IPublisher");
                    }
                } catch (Exception ex)
                {
                    upstream.Cancel();
                    OnError(ex);
                    return;
                }

                InnerSubscriber inner = new InnerSubscriber(this, prefetch);

                if (Add(inner))
                {
                    p.Subscribe(inner);
                }
            }
Exemple #3
0
 void InnerError(InnerSubscriber inner, Exception cause)
 {
     ExceptionHelper.AddException(ref error, cause);
     Volatile.Write(ref inner.done, true);
     Interlocked.Decrement(ref done);
     Drain();
 }
Exemple #4
0
 public PublisherConcatMap(ISubscriber <R> actual, Func <T, IPublisher <R> > mapper, int prefetch)
 {
     this.actual.Init(actual);
     this.prefetch = prefetch;
     this.mapper   = mapper;
     this.inner    = new InnerSubscriber(actual, this);
 }
            public void Clear()
            {
                current = null;
                var s  = subscribers;
                var n  = s.Length;
                int ci = consumerIndex;

                for (;;)
                {
                    var inner = Volatile.Read(ref s[ci]);
                    if (inner == null || inner == CancelledInner)
                    {
                        break;
                    }
                    if (Interlocked.CompareExchange(ref s[ci], null, inner) == inner)
                    {
                        ci++;
                        if (ci == n)
                        {
                            ci = 0;
                        }
                    }
                }
                consumerIndex = ci;
            }
 internal ConcatMapSubscriber(IFlowableSubscriber<R> actual, Func<T, IPublisher<R>> mapper, int prefetch)
 {
     this.actual = actual;
     this.mapper = mapper;
     this.prefetch = prefetch;
     this.limit = prefetch - (prefetch >> 2);
     this.inner = new InnerSubscriber(actual, this);
 }
Exemple #7
0
        public IDisposable Subscribe(IObserver <T> observer)
        {
            InnerSubscriber inner = new InnerSubscriber(observer, second);

            first.Subscribe(inner);

            return(inner);
        }
 public void Cancel()
 {
     upstream.Cancel();
     CancelAll();
     if (Interlocked.Increment(ref wip) != 1)
     {
         current = null;
     }
 }
            void DrainLoopFused()
            {
                int missed = 1;
                var s      = subscribers;
                var n      = s.Length;
                var curr   = current;
                var a      = actual;

                for (;;)
                {
                    if (Volatile.Read(ref cancelled))
                    {
                        current = null;
                        return;
                    }

                    bool d = Volatile.Read(ref done);

                    int ci = consumerIndex;
                    curr = Volatile.Read(ref s[ci]);

                    if (curr != null)
                    {
                        a.OnNext(default(R));
                    }

                    if (d)
                    {
                        var ex = ExceptionHelper.Terminate(ref error);
                        if (ex == null)
                        {
                            a.OnComplete();
                        }
                        else
                        {
                            a.OnError(ex);
                        }
                        return;
                    }

                    int w = Volatile.Read(ref wip);
                    if (w == missed)
                    {
                        missed = Interlocked.Add(ref wip, -missed);
                        if (missed == 0)
                        {
                            break;
                        }
                    }
                    else
                    {
                        missed = w;
                    }
                }
            }
Exemple #10
0
            public ReduceFullCoordinator(ISubscriber <T> actual, int n, Func <T, T, T> reducer) : base(actual)
            {
                var a = new InnerSubscriber[n];

                for (int i = 0; i < n; i++)
                {
                    a[i] = new InnerSubscriber(this, reducer);
                }
                this.subscribers = a;
                this.reducer     = reducer;
                Volatile.Write(ref remaining, n);
            }
            internal OrderedJoin(ISubscriber <T> actual, int n, int prefetch)
            {
                this.actual = actual;
                var a = new InnerSubscriber[n];

                for (int i = 0; i < n; i++)
                {
                    a[i] = new InnerSubscriber(this, prefetch);
                }
                this.subscribers = a;
                this.peek        = new IOrderedItem <T> [n];
            }
Exemple #12
0
            internal BaseWithLatestFomrSubscriber(int n, Func <T[], R> combiner)
            {
                var s = new IDisposable[n];

                for (int i = 0; i < n; i++)
                {
                    s[i] = new InnerSubscriber(this, i);
                }
                this.subscribers = s;
                this.values      = new Node[n];
                this.n           = n;
                this.combiner    = combiner;
            }
Exemple #13
0
            internal JoinSubscription(IFlowableSubscriber <T> actual, int n, int bufferSize)
            {
                this.actual     = actual;
                this.bufferSize = bufferSize;
                this.done       = n;
                this.limit      = bufferSize - (bufferSize >> 2);
                var subs = new InnerSubscriber[n];

                for (int i = 0; i < n; i++)
                {
                    subs[i] = new InnerSubscriber(this);
                }
                this.subscribers = subs;
            }
            bool Remove(InnerSubscriber inner)
            {
                var s  = subscribers;
                var n  = s.Length;
                int ci = consumerIndex;

                if (Interlocked.CompareExchange(ref s[ci], null, inner) == inner)
                {
                    ci++;
                    consumerIndex = ci == n ? 0 : ci;
                    return(true);
                }
                return(false);
            }
            bool Add(InnerSubscriber inner)
            {
                var s  = subscribers;
                var n  = s.Length;
                int pi = producerIndex;

                if (Interlocked.CompareExchange(ref s[pi], inner, null) == null)
                {
                    pi++;
                    producerIndex = pi == n ? 0 : pi;
                    return(true);
                }
                return(false);
            }
            internal SortedJoinSubscription(ISubscriber <T> actual, int n, IComparer <T> comparer)
            {
                this.actual  = actual;
                this.values  = new IList <T> [n];
                this.indexes = new int[n];
                var a = new InnerSubscriber[n];

                for (int i = 0; i < n; i++)
                {
                    a[i] = new InnerSubscriber(this, i);
                }
                this.subscribers = a;
                this.remaining   = n;
                this.comparer    = comparer;
            }
Exemple #17
0
 bool SetInner(InnerSubscriber b)
 {
     for (;;)
     {
         var a = Volatile.Read(ref inner);
         if (a == Cancelled)
         {
             return(false);
         }
         if (Interlocked.CompareExchange(ref inner, b, a) == a)
         {
             return(true);
         }
     }
 }
 void InnerNext(InnerSubscriber inner, R item)
 {
     if (Volatile.Read(ref wip) == 0 && Interlocked.CompareExchange(ref wip, 1, 0) == 0)
     {
         var  q     = Volatile.Read(ref inner.queue);
         bool offer = true;
         if (current == inner)
         {
             if (q == null || q.IsEmpty())
             {
                 var e = emitted;
                 if (e != Volatile.Read(ref requested))
                 {
                     actual.OnNext(item);
                     emitted = e + 1;
                     inner.RequestOne();
                     offer = false;
                 }
             }
         }
         if (offer)
         {
             if (q == null)
             {
                 q = inner.GetOrCreateQueue();
             }
             q.Offer(item);
         }
         if (Interlocked.Decrement(ref wip) == 0)
         {
             return;
         }
     }
     else
     {
         var q = inner.GetOrCreateQueue();
         q.Offer(item);
         if (Interlocked.Increment(ref wip) != 1)
         {
             return;
         }
     }
     DrainLoop();
 }
Exemple #19
0
            public void OnNext(T element)
            {
                var curr = Volatile.Read(ref current);

                if (curr != Terminated)
                {
                    curr?.Cancel();

                    IPublisher <R> p;

                    try
                    {
                        p = mapper(element);
                        if (p == null)
                        {
                            throw new NullReferenceException("The mapper returned a null IPublisher");
                        }
                    }
                    catch (Exception ex)
                    {
                        upstream.Cancel();
                        OnError(ex);
                        return;
                    }

                    var inner = new InnerSubscriber(this, prefetch);

                    for (;;)
                    {
                        curr = Volatile.Read(ref current);
                        if (curr == Terminated)
                        {
                            break;
                        }
                        if (Interlocked.CompareExchange(ref current, inner, curr) == curr)
                        {
                            p.Subscribe(inner);
                            break;
                        }
                    }
                }
            }
            public bool Poll(out R item)
            {
                var curr = current;
                var s    = subscribers;
                var n    = s.Length;

                for (;;)
                {
                    if (curr == null)
                    {
                        int ci = consumerIndex;
                        curr = Volatile.Read(ref s[ci]);
                        if (curr == null)
                        {
                            item = default(R);
                            return(false);
                        }
                        current = curr;
                    }
                    if (curr != null)
                    {
                        bool d = Volatile.Read(ref curr.done);
                        var  q = Volatile.Read(ref curr.queue);
                        if (q != null && q.Poll(out item))
                        {
                            return(true);
                        }
                        if (d)
                        {
                            Remove(curr);
                            int ci = consumerIndex + 1;
                            consumerIndex = ci == n ? 0 : ci;
                            current       = null;
                            curr          = null;
                            upstream.Request(1);
                            continue;
                        }
                    }
                    item = default(R);
                    return(false);
                }
            }
        public void Subscribe(IPublisher <T>[] sources, int n)
        {
            values   = new T[n];
            nonempty = new ulong[1 + ((n - 1) >> 4)];

            InnerSubscriber[] a = new InnerSubscriber[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = new InnerSubscriber(this, i);
            }

            subscribers = a;
            actual.OnSubscribe(this);

            for (int i = 0; i < n; i++)
            {
                if (bp.IsCancelled() || LvDone())
                {
                    break;
                }
                sources[i].Subscribe(a[i]);
            }
        }
Exemple #22
0
 void InnerComplete(InnerSubscriber inner)
 {
     Volatile.Write(ref inner.done, true);
     Interlocked.Decrement(ref done);
     Drain();
 }
Exemple #23
0
            void Drain()
            {
                if (Interlocked.Increment(ref wip) != 1)
                {
                    return;
                }

                int missed = 1;
                var a      = actual;
                var q      = queue;
                var m      = q.Length - 1;
                var e      = emitted;
                var c      = consumed;
                var ci     = consumerIndex;
                var lim    = limit;

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

                    while (e != r)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            ClearQueue(q, m + 1);
                            return;
                        }

                        bool d = Volatile.Read(ref done);

                        int  offset = (int)ci & m;
                        bool empty  = Volatile.Read(ref q[offset].state) == 0;

                        if (d && empty)
                        {
                            Exception ex = ExceptionHelper.Terminate(ref error);
                            if (ex != null)
                            {
                                a.OnError(ex);
                            }
                            else
                            {
                                a.OnComplete();
                            }
                            return;
                        }

                        if (empty)
                        {
                            break;
                        }

                        T t = q[offset].item;

                        int s = Volatile.Read(ref state);

                        if (s == STATE_FRESH)
                        {
                            IPublisher <bool> pub;
                            try
                            {
                                pub = predicate(t);
                            }
                            catch (Exception ex)
                            {
                                upstream.Cancel();
                                a.OnError(ex);
                                return;
                            }

                            if (pub is IVariableSource <bool> vu)
                            {
                                q[offset].item  = default(T);
                                q[offset].state = 0;

                                if (vu.Value(out bool u))
                                {
                                    if (u)
                                    {
                                        a.OnNext(t);

                                        e++;
                                    }
                                }
                                ci++;

                                if (++c == lim)
                                {
                                    c = 0;
                                    upstream.Request(lim);
                                }
                            }
                            else
                            {
                                InnerSubscriber sub = new InnerSubscriber(this);
                                if (SetInner(sub))
                                {
                                    Volatile.Write(ref state, STATE_RUNNING);
                                    pub.Subscribe(sub);
                                }
                            }
                        }
                        else
                        if (s == STATE_RESULT_EMPTY)
                        {
                            q[offset].item  = default(T);
                            q[offset].state = 0;
                            ci++;
                            Volatile.Write(ref state, STATE_FRESH);

                            if (++c == lim)
                            {
                                c = 0;
                                upstream.Request(lim);
                            }
                        }
                        else
                        if (s == STATE_RESULT_VALUE)
                        {
                            q[offset].item  = default(T);
                            q[offset].state = 0;

                            a.OnNext(t);

                            e++;
                            ci++;
                            Volatile.Write(ref state, STATE_FRESH);

                            if (++c == lim)
                            {
                                c = 0;
                                upstream.Request(lim);
                            }
                        }
                    }


                    if (e == r)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            ClearQueue(q, m + 1);
                            return;
                        }

                        bool d = Volatile.Read(ref done);

                        int  offset = (int)ci & m;
                        bool empty  = Volatile.Read(ref q[offset].state) == 0;

                        if (d && empty)
                        {
                            Exception ex = ExceptionHelper.Terminate(ref error);
                            if (ex != null)
                            {
                                a.OnError(ex);
                            }
                            else
                            {
                                a.OnComplete();
                            }
                            return;
                        }
                    }

                    int w = Volatile.Read(ref wip);
                    if (w == missed)
                    {
                        consumed      = c;
                        emitted       = e;
                        consumerIndex = ci;
                        missed        = Interlocked.Add(ref wip, -missed);
                        if (missed == 0)
                        {
                            break;
                        }
                    }
                    else
                    {
                        missed = w;
                    }
                }
            }
            void DrainLoopAsync()
            {
                int missed = 1;
                var s      = subscribers;
                var n      = s.Length;
                var curr   = current;
                var e      = emitted;
                var a      = actual;

                for (;;)
                {
                    if (curr == null)
                    {
                        if (Volatile.Read(ref cancelled))
                        {
                            return;
                        }

                        bool d = Volatile.Read(ref done);

                        int ci = consumerIndex;
                        curr = Volatile.Read(ref s[ci]);

                        if (d && curr == null)
                        {
                            current = null;
                            var ex = ExceptionHelper.Terminate(ref error);
                            if (ex == null)
                            {
                                a.OnComplete();
                            }
                            else
                            {
                                a.OnError(ex);
                            }
                            return;
                        }
                        if (curr == CancelledInner)
                        {
                            current = null;
                            return;
                        }
                    }

                    if (curr != null)
                    {
                        long r = Volatile.Read(ref requested);

                        if (Volatile.Read(ref cancelled))
                        {
                            current = null;
                            return;
                        }

                        bool d = Volatile.Read(ref curr.done);
                        var  q = Volatile.Read(ref curr.queue);

                        if (d && q == null)
                        {
                            Remove(curr);
                            curr = null;
                        }
                        else
                        if (q != null)
                        {
                            while (e != r)
                            {
                                if (Volatile.Read(ref cancelled))
                                {
                                    current = null;
                                    return;
                                }

                                d = Volatile.Read(ref curr.done);

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

                                if (d && empty)
                                {
                                    Remove(curr);
                                    curr = null;
                                    break;
                                }

                                if (empty)
                                {
                                    break;
                                }

                                a.OnNext(v);

                                e++;
                                curr.RequestOne();
                            }

                            if (e == r)
                            {
                                if (Volatile.Read(ref cancelled))
                                {
                                    current = null;
                                    return;
                                }
                                if (Volatile.Read(ref curr.done) && q.IsEmpty())
                                {
                                    Remove(curr);
                                    curr = null;
                                }
                            }
                        }

                        if (curr == null)
                        {
                            upstream.Request(1);
                            continue;
                        }
                    }
                    int w = Volatile.Read(ref wip);
                    if (w == missed)
                    {
                        emitted = e;
                        current = curr;
                        missed  = Interlocked.Add(ref wip, -missed);
                        if (missed == 0)
                        {
                            break;
                        }
                    }
                    else
                    {
                        missed = w;
                    }
                }
            }
Exemple #25
0
            void DrainLoop()
            {
                int missed = 1;
                var e      = emitted;
                var a      = actual;

                for (;;)
                {
                    if (Volatile.Read(ref cancelled))
                    {
                        current = null;
                        return;
                    }
                    bool d    = Volatile.Read(ref done);
                    var  curr = Volatile.Read(ref current);

                    if (d && curr == null)
                    {
                        Exception ex = ExceptionHelper.Terminate(ref error);
                        if (ex == null)
                        {
                            a.OnComplete();
                        }
                        else
                        {
                            a.OnError(ex);
                        }
                        return;
                    }

                    if (curr != null)
                    {
                        d = Volatile.Read(ref curr.done);
                        var q = Volatile.Read(ref curr.queue);

                        if (q != null)
                        {
                            if (e != Volatile.Read(ref requested))
                            {
                                bool empty = !q.Poll(out R v);
                                if (d && empty)
                                {
                                    Interlocked.CompareExchange(ref current, null, curr);
                                    continue;
                                }
                                if (!empty)
                                {
                                    a.OnNext(v);
                                    e++;
                                    curr.RequestOne();
                                    continue;
                                }
                            }
                            else
                            {
                                if (d && q.IsEmpty())
                                {
                                    Interlocked.CompareExchange(ref current, null, curr);
                                    continue;
                                }
                            }
                        }
                        else
                        if (d)
                        {
                            Interlocked.CompareExchange(ref current, null, curr);
                            continue;
                        }
                    }

                    int w = Volatile.Read(ref wip);
                    if (w == missed)
                    {
                        emitted = e;
                        missed  = Interlocked.Add(ref wip, -missed);
                        if (missed == 0)
                        {
                            break;
                        }
                    }
                    else
                    {
                        missed = w;
                    }
                }
            }
 void InnerComplete(InnerSubscriber inner)
 {
     Volatile.Write(ref inner.done, true);
     Drain();
 }
 void InnerError(InnerSubscriber inner, Exception error)
 {
     ExceptionHelper.AddException(ref this.error, error);
     Volatile.Write(ref inner.done, true);
     Drain();
 }