Exemple #1
0
        /// <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);
             }
         }
     }
 }
Exemple #5
0
 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;
                }
            }
        }
Exemple #8
0
        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;
                }
            }
        }