Пример #1
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);
            }
Пример #2
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);
                }
            }
Пример #3
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;
                    }
                }
            }