void Signal(PublisherSwitchMapSubscriber sender, R value, bool done)
        {
            if (Volatile.Read(ref index) != sender.Index())
            {
                if (done)
                {
                    Exception e = sender.Error();

                    if (e != null)
                    {
                        RxAdvancedFlowPlugins.OnError(e);
                    }
                }
                return;
            }

            PublisherSwitchMapStruct s = new PublisherSwitchMapStruct();

            s.sender = sender;
            s.value  = value;
            s.done   = done;

            lock (this)
            {
                q.OfferRef(ref s);
            }

            if (done)
            {
                sender.SetDone();
            }

            Drain();
        }
        public void Cancel()
        {
            s.Cancel();
            bp.Cancel();

            PublisherSwitchMapSubscriber i = Volatile.Read(ref inner);

            if (i != Cancelled)
            {
                i = Interlocked.Exchange(ref inner, Cancelled);
                if (i != Cancelled)
                {
                    i?.Cancel();
                }
            }
        }
        public void OnNext(T t)
        {
            long idx = Interlocked.Increment(ref index);

            PublisherSwitchMapSubscriber curr = inner;

            if (curr == Cancelled)
            {
                return;
            }

            inner?.Cancel();

            IPublisher <R> p;

            try
            {
                p = mapper(t);
            }
            catch (Exception ex)
            {
                OnError(ex);
                return;
            }
            if (p == null)
            {
                OnError(new NullReferenceException("The mapper returned a null IPublisher"));
                return;
            }

            PublisherSwitchMapSubscriber i = new PublisherSwitchMapSubscriber(idx, this, bp.Requested());

            if (Interlocked.CompareExchange(ref inner, i, curr) == curr)
            {
                p.Subscribe(i);
            }
        }
        void Drain()
        {
            if (!bp.Enter())
            {
                return;
            }

            ISubscriber <R> a      = actual;
            int             missed = 1;

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

                for (;;)
                {
                    PublisherSwitchMapStruct v;

                    bool empty = q.Peek(out v);

                    if (CheckTerminated(Volatile.Read(ref done), empty, a))
                    {
                        return;
                    }

                    if (empty)
                    {
                        if (e != 0L)
                        {
                            bp.Produced(e);
                        }
                        break;
                    }

                    PublisherSwitchMapSubscriber sender = v.sender;

                    if (Volatile.Read(ref index) == sender.Index())
                    {
                        if (v.done)
                        {
                            Exception ex = sender.Error();
                            if (ex != null)
                            {
                                Cancel();

                                q.Clear();

                                a.OnError(ex);
                                return;
                            }

                            q.Drop();
                        }
                        else
                        if (r != e)
                        {
                            a.OnNext(v.value);

                            q.Drop();
                            e++;
                        }
                        else
                        {
                            if (e != 0L)
                            {
                                bp.Produced(e);

                                sender.Request(e);
                            }
                            break;
                        }
                    }
                    else
                    {
                        q.Drop();
                    }
                }

                if (CheckTerminated(Volatile.Read(ref done), q.IsEmpty(), a))
                {
                    return;
                }

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

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