CompareAndSet() public method

Atomically set the value to the given updated value if the current value == the expected value.
public CompareAndSet ( long expectedSequence, long nextSequence ) : bool
expectedSequence long the expected value for the sequence
nextSequence long the new value for the sequence
return bool
示例#1
0
        internal long NextInternal(int n)
        {
            long current;
            long next;

            var spinWait = default(AggressiveSpinWait);

            do
            {
                current = _cursor.Value;
                next    = current + n;

                long wrapPoint            = next - _bufferSize;
                long cachedGatingSequence = _gatingSequenceCache.Value;

                if (wrapPoint > cachedGatingSequence || cachedGatingSequence > current)
                {
                    long gatingSequence = Util.GetMinimumSequence(Volatile.Read(ref _gatingSequences), current);

                    if (wrapPoint > gatingSequence)
                    {
                        spinWait.SpinOnce();
                        continue;
                    }

                    _gatingSequenceCache.SetValue(gatingSequence);
                }
                else if (_cursor.CompareAndSet(current, next))
                {
                    break;
                }
            } while (true);

            return(next);
        }
        ///<summary>
        /// Serialise publishers in sequence and set cursor to latest available sequence.
        ///</summary>
        ///<param name="sequence">sequence to be applied</param>
        ///<param name="cursor">cursor to serialise against.</param>
        ///<param name="batchSize">batchSize of the sequence.</param>
        public override void SerialisePublishing(long sequence, Sequence cursor, long batchSize)
        {
            var spinWait = default(SpinWait);
            while (sequence - cursor.Value > _pendingPublication.Length)
            {
                spinWait.SpinOnce();
            }

            long expectedSequence = sequence - batchSize;
            for (long pendingSequence = expectedSequence + 1; pendingSequence <= sequence; pendingSequence++)
            {
                _pendingPublication.WriteCompilerOnlyFence((int)pendingSequence & _pendingMask, pendingSequence);                
            }
            _pendingPublication.WriteFullFence((int)sequence & _pendingMask, sequence);

            long cursorSequence = cursor.Value;
            if (cursorSequence >= sequence)
            {
                return;
            }
            expectedSequence = Math.Max(expectedSequence, cursorSequence);
            long nextSequence = expectedSequence + 1;
            while (cursor.CompareAndSet(expectedSequence, nextSequence))
            {
                expectedSequence = nextSequence;
                nextSequence++;
                if (_pendingPublication.ReadFullFence((int)nextSequence & _pendingMask) != nextSequence)
                {
                    break;
                }
            }
        }
示例#3
0
        ///<summary>
        /// Serialise publishers in sequence and set cursor to latest available sequence.
        ///</summary>
        ///<param name="sequence">sequence to be applied</param>
        ///<param name="cursor">cursor to serialise against.</param>
        ///<param name="batchSize">batchSize of the sequence.</param>
        public void SerialisePublishing(long sequence, Sequence cursor, long batchSize)
        {
            var spinWait = default(SpinWait);

            while (sequence - cursor.Value > _pendingPublication.Length)
            {
                spinWait.SpinOnce();
            }

            long expectedSequence = sequence - batchSize;

            for (long pendingSequence = expectedSequence + 1; pendingSequence <= sequence; pendingSequence++)
            {
                _pendingPublication.WriteFullFence((int)pendingSequence & _pendingMask, pendingSequence);
            }

            if (cursor.Value != expectedSequence)
            {
                return;
            }

            long nextSequence = expectedSequence + 1;

            while (cursor.CompareAndSet(expectedSequence, nextSequence))
            {
                expectedSequence = nextSequence;
                nextSequence++;
                if (_pendingPublication.ReadFullFence((int)nextSequence & _pendingMask) != nextSequence)
                {
                    break;
                }
            }
        }
 /// <summary>
 /// Atomically checks the available capacity of the ring buffer and claims the next sequence.  Will
 /// throw InsufficientCapacityException if the capacity not available.
 /// </summary>
 /// <param name="availableCapacity">the capacity that should be available before claiming the next slot</param>
 /// <param name="delta">the number of slots to claim</param>
 /// <param name="dependentSequences">the set of sequences to check to ensure capacity is available</param>
 /// <returns>the slot after incrementing</returns>
 public long CheckAndIncrement(int availableCapacity, int delta, Sequence[] dependentSequences)
 {
     for (;;)
     {
         long sequence = _claimSequence.Value;
         if (HasAvailableCapacity(sequence, availableCapacity, dependentSequences))
         {
             long nextSequence = sequence + delta;
             if (_claimSequence.CompareAndSet(sequence, nextSequence))
             {
                 return(nextSequence);
             }
         }
         else
         {
             throw InsufficientCapacityException.Instance;
         }
     }
 }
示例#5
0
        internal bool TryNextInternal(int n, out long sequence)
        {
            long current;
            long next;

            do
            {
                current = _cursor.Value;
                next    = current + n;

                if (!HasAvailableCapacity(n, current))
                {
                    sequence = default;
                    return(false);
                }
            }while (!_cursor.CompareAndSet(current, next));

            sequence = next;
            return(true);
        }