public void InnerComplete(InnerSignalObserver <R> sender)
 {
     sender.Dispose();
     if (Volatile.Read(ref active) == sender)
     {
         sender.SetDone();
         Drain();
     }
 }
 public void InnerError(InnerSignalObserver <R> sender, Exception error)
 {
     sender.Dispose();
     if (Volatile.Read(ref active) == sender)
     {
         if (delayErrors)
         {
             ExceptionHelper.AddException(ref errors, error);
             sender.SetDone();
             Drain();
         }
         else
         {
             if (Interlocked.CompareExchange(ref errors, error, null) == null)
             {
                 sender.SetDone();
                 Drain();
             }
         }
     }
 }
            void DrainLoop()
            {
                int missed    = 1;
                var observers = this.observers;

                for (; ;)
                {
                    if (Volatile.Read(ref disposed))
                    {
                        if (current != null)
                        {
                            current.Dispose();
                            current = null;
                        }

                        for (; ;)
                        {
                            var inner = observers.TryPoll(out var success);
                            if (!success)
                            {
                                break;
                            }
                            inner.Dispose();
                        }
                        Cleanup();
                    }
                    else
                    {
                        var curr = current;
                        if (curr == null)
                        {
                            var d = Volatile.Read(ref done);

                            if (d)
                            {
                                var ex = Volatile.Read(ref error);
                                if (ex != null)
                                {
                                    downstream.OnError(ex);
                                    Volatile.Write(ref disposed, true);
                                    base.Dispose();
                                    continue;
                                }
                            }

                            curr = observers.TryPoll(out var success);
                            var empty = !success;

                            if (d && empty)
                            {
                                downstream.OnCompleted();
                                Volatile.Write(ref disposed, true);
                                base.Dispose();
                            }

                            current = curr;
                        }
                        if (curr != null)
                        {
                            var continueOuter = false;
                            for (; ;)
                            {
                                if (Volatile.Read(ref disposed))
                                {
                                    continueOuter = true;
                                    break;
                                }

                                var d = curr.IsDone();
                                var q = curr.GetQueue();

                                var v       = default(R);
                                var success = false;

                                if (q != null)
                                {
                                    try
                                    {
                                        v = q.TryPoll(out success);
                                    }
                                    catch (Exception ex)
                                    {
                                        Interlocked.CompareExchange(ref this.error, ex, null);
                                        Volatile.Write(ref disposed, true);
                                        continueOuter = true;
                                        break;
                                    }
                                }

                                if (d && !success)
                                {
                                    curr.Dispose();
                                    current = null;
                                    curr    = null;
                                    InnerConsumed();
                                    continueOuter = true;
                                    break;
                                }

                                if (!success)
                                {
                                    break;
                                }

                                downstream.OnNext(v);
                            }

                            if (continueOuter)
                            {
                                continue;
                            }
                        }
                    }

                    missed = Interlocked.Add(ref wip, -missed);
                    if (missed == 0)
                    {
                        break;
                    }
                }
            }