/// <summary> /// Request the specified amount (not validated) from the current ISubscription if present /// or accumulate it until an ISubscription is set. /// </summary> /// <param name="n">The request amount, positive (not validated)</param> public void Request(long n) { if (Volatile.Read(ref wip) == 0 && Interlocked.CompareExchange(ref wip, 1, 0) == 0) { long r = requested; var curr = current; if (r != long.MaxValue) { requested = BackpressureHelper.AddCap(r, n); } if (Interlocked.Decrement(ref wip) != 0) { Drain(); } curr?.Request(n); } else { BackpressureHelper.GetAndAddCap(ref missedRequested, n); if (Interlocked.Increment(ref wip) != 1) { return; } Drain(); } }
public override void Request(long n) { if (SubscriptionHelper.Validate(n)) { if (Volatile.Read(ref once) == 0 && Interlocked.CompareExchange(ref once, 1, 0) == 0) { long u = BackpressureHelper.MultiplyCap(n - 1, skip); long v = BackpressureHelper.AddCap(u, size); s.Request(v); } else { long u = BackpressureHelper.MultiplyCap(n, skip); s.Request(u); } } }
public void Request(long n) { if (OnSubscribeHelper.ValidateRequest(n)) { if (Volatile.Read(ref requestOnce) == 0 && Interlocked.CompareExchange(ref requestOnce, 1, 0) == 0) { long u = BackpressureHelper.MultiplyCap(skip, n - 1); long v = BackpressureHelper.AddCap(u, n); s.Request(v); } else { long u = BackpressureHelper.MultiplyCap(skip, n); s.Request(u); } } }
public override void Request(long n) { if (SubscriptionHelper.Validate(n)) { if (!BackpressureHelper.PostCompleteRequest <IList <T> >(ref requested, n, actual, lists, ref cancelled)) { if (Volatile.Read(ref once) == 0 && Interlocked.CompareExchange(ref once, 1, 0) == 0) { long r = BackpressureHelper.MultiplyCap(n - 1, size - skip); long u = BackpressureHelper.AddCap(r, size); s.Request(u); } else { long r = BackpressureHelper.MultiplyCap(n, size - skip); s.Request(r); } } } }
public void Request(long n) { if (OnSubscribeHelper.ValidateRequest(n)) { if (BackpressureHelper.PostCompleteRequest(ref requested, n, buffers, actual, ref cancelled)) { if (Volatile.Read(ref once) == 0 && Interlocked.CompareExchange(ref once, 1, 0) == 0) { long u = BackpressureHelper.MultiplyCap(skip, n - 1); long v = BackpressureHelper.AddCap(size, u); s.Request(v); } else { long u = BackpressureHelper.MultiplyCap(skip, n); s.Request(u); } } } }
/// <summary> /// Request from the current actual ISubscriber (validated). /// </summary> /// <param name="n">The request amount. Validated</param> public void Request(long n) { if (Volatile.Read(ref cancelled)) { return; } if (OnSubscribeHelper.ValidateRequest(n)) { if (Volatile.Read(ref wip) == 0) { int j = Interlocked.CompareExchange(ref wip, 1, 0); if (j == 0) { requested = BackpressureHelper.AddCap(requested, n); actual?.Request(n); if (Interlocked.Decrement(ref wip) == 0) { return; } } } BackpressureHelper.Add(ref missedRequested, n); if (Interlocked.Increment(ref wip) == 1) { Drain(); } } }
void Drain() { for (;;) { // missed: check for a non-null value and exchange only then ISubscription ms = Volatile.Read(ref missedSubscription); if (ms != null) { ms = Interlocked.Exchange(ref missedSubscription, null); } long mr = Volatile.Read(ref missedRequested); if (mr != 0) { mr = Interlocked.Exchange(ref missedRequested, 0); } long mp = Volatile.Read(ref missedProduced); if (mp != 0) { Interlocked.Exchange(ref missedProduced, 0); } long r = requested; if (r != long.MaxValue) { long u = BackpressureHelper.AddCap(r, mr); if (u != long.MaxValue) { long v = u - mp; if (v < 0) { ReportMoreProduced(v); v = 0; } u = v; } requested = u; r = u; } ISubscription c = actual; if (Volatile.Read(ref cancelled)) { c?.Cancel(); ms?.Cancel(); } else if (ms != null) { actual = ms; if (r != 0) { ms.Request(r); } } else if (c != null && mr != 0) { c.Request(mr); } if (Interlocked.Decrement(ref wip) == 0) { break; } } }
void Drain() { long requestAmount = 0L; ISubscription requestTarget = null; int missed = 1; for (;;) { long mRequested = Volatile.Read(ref missedRequested); if (mRequested != 0L) { mRequested = Interlocked.Exchange(ref missedRequested, 0L); } long mProduced = Volatile.Read(ref missedProduced); if (mProduced != 0L) { mProduced = Interlocked.Exchange(ref missedProduced, 0L); } long r = requested; if (r != long.MaxValue) { long u = BackpressureHelper.AddCap(r, mRequested); if (u != long.MaxValue) { long v = u - mProduced; if (v < 0L) { ExceptionHelper.OnErrorDropped(new InvalidOperationException("More produced than requested: " + v)); v = 0L; } requested = v; r = v; } else { requested = u; r = u; } } ISubscription mSubscription = Volatile.Read(ref missedSubscription); if (mSubscription != null) { mSubscription = Interlocked.Exchange(ref missedSubscription, null); } var c = current; if (SubscriptionHelper.IsCancelled(c)) { mSubscription?.Cancel(); } else { if (mSubscription != null) { current?.Cancel(); current = mSubscription; if (r != 0L) { requestAmount = BackpressureHelper.AddCap(requestAmount, r); requestTarget = mSubscription; } } else if (mRequested != 0) { requestAmount = BackpressureHelper.AddCap(requestAmount, mRequested); requestTarget = current; } } missed = QueueDrainHelper.Leave(ref wip, missed); if (missed == 0) { if (requestAmount != 0L) { requestTarget?.Request(requestAmount); } break; } } }