internal JoinSubscription(ISubscriber <T> actual, int n, int prefetch)
            {
                this.actual = actual;
                var a = new JoinInnerSubscriber[n];

                for (int i = 0; i < n; i++)
                {
                    a[i] = new JoinInnerSubscriber(this, prefetch);
                }
                this.subscribers = a;
                Volatile.Write(ref done, n);
            }
            internal void InnerNext(JoinInnerSubscriber inner, T value)
            {
                if (QueueDrainHelper.TryEnter(ref wip))
                {
                    long r = Volatile.Read(ref requested);
                    if (r != 0L)
                    {
                        actual.OnNext(value);
                        if (r != long.MaxValue)
                        {
                            Interlocked.Decrement(ref requested);
                        }
                        inner.RequestOne();
                    }
                    else
                    {
                        var q = inner.Queue();

                        if (!q.Offer(value))
                        {
                            InnerError(BackpressureHelper.MissingBackpressureException("Queue full?!"));
                            return;
                        }
                    }

                    if (QueueDrainHelper.Leave(ref wip, 1) == 0)
                    {
                        return;
                    }
                }
                else
                {
                    var q = inner.Queue();

                    if (!q.Offer(value))
                    {
                        InnerError(BackpressureHelper.MissingBackpressureException("Queue full?!"));
                        return;
                    }

                    if (!QueueDrainHelper.Enter(ref wip))
                    {
                        return;
                    }
                }

                DrainLoop();
            }